Merge squirrelfish-extreme to trunk.
authormrowe@apple.com <mrowe@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 7 Sep 2008 05:44:58 +0000 (05:44 +0000)
committermrowe@apple.com <mrowe@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 7 Sep 2008 05:44:58 +0000 (05:44 +0000)
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@36244 268f45cc-cd09-0410-ab3c-d52691b4dbfc

58 files changed:
JavaScriptCore/ChangeLog
JavaScriptCore/Configurations/JavaScriptCore.xcconfig
JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
JavaScriptCore/VM/CTI.cpp [new file with mode: 0644]
JavaScriptCore/VM/CTI.h [new file with mode: 0644]
JavaScriptCore/VM/CodeBlock.cpp
JavaScriptCore/VM/CodeBlock.h
JavaScriptCore/VM/CodeGenerator.cpp
JavaScriptCore/VM/LabelID.h
JavaScriptCore/VM/Machine.cpp
JavaScriptCore/VM/Machine.h
JavaScriptCore/VM/Register.h
JavaScriptCore/VM/RegisterFile.h
JavaScriptCore/VM/SamplingTool.cpp
JavaScriptCore/VM/SamplingTool.h
JavaScriptCore/kjs/ExecState.h
JavaScriptCore/kjs/InternalFunction.h
JavaScriptCore/kjs/JSArray.h
JavaScriptCore/kjs/JSCell.h
JavaScriptCore/kjs/JSFunction.h
JavaScriptCore/kjs/JSImmediate.h
JavaScriptCore/kjs/JSObject.h
JavaScriptCore/kjs/JSString.h
JavaScriptCore/kjs/JSValue.h
JavaScriptCore/kjs/JSVariableObject.h
JavaScriptCore/kjs/PropertyMap.h
JavaScriptCore/kjs/RegExpConstructor.cpp
JavaScriptCore/kjs/RegExpPrototype.cpp
JavaScriptCore/kjs/ScopeChain.h
JavaScriptCore/kjs/StringPrototype.cpp
JavaScriptCore/kjs/nodes.cpp
JavaScriptCore/kjs/nodes.h
JavaScriptCore/kjs/nodes2string.cpp
JavaScriptCore/kjs/regexp.cpp
JavaScriptCore/kjs/regexp.h
JavaScriptCore/kjs/ustring.h
JavaScriptCore/masm/IA32MacroAsm.h [new file with mode: 0644]
JavaScriptCore/masm/MacroAssembler.h [new file with mode: 0644]
JavaScriptCore/masm/MacroAssemblerWin.cpp [new file with mode: 0644]
JavaScriptCore/wrec/WREC.cpp [new file with mode: 0644]
JavaScriptCore/wrec/WREC.h [new file with mode: 0644]
JavaScriptCore/wtf/ASCIICType.h
JavaScriptCore/wtf/HashTraits.h
JavaScriptCore/wtf/Platform.h
LayoutTests/ChangeLog
LayoutTests/fast/js/array-indexing-expected.txt [new file with mode: 0644]
LayoutTests/fast/js/array-indexing.html [new file with mode: 0644]
LayoutTests/fast/js/deep-recursion-test.html
LayoutTests/fast/js/resources/array-indexing.js [new file with mode: 0644]
WebCore/ChangeLog
WebCore/ForwardingHeaders/masm/IA32MacroAsm.h [new file with mode: 0644]
WebCore/ForwardingHeaders/masm/MacroAssembler.h [new file with mode: 0644]
WebCore/ForwardingHeaders/wrec/WREC.h [new file with mode: 0644]
WebCore/WebCore.vcproj/WebCore.vcproj
WebKitTools/ChangeLog
WebKitTools/Scripts/run-webkit-tests
WebKitTools/Scripts/webkitdirs.pm

index c667744..7b8c4e0 100644 (file)
+=== End merge of squirrelfish-extreme ===
+
+2008-09-06  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Sam Weinig. Adapted somewhat by Maciej Stachowiak.
+        
+        - refactor WREC to share more of the JIT infrastructure with CTI
+
+        * VM/CTI.cpp:
+        (KJS::CTI::emitGetArg):
+        (KJS::CTI::emitGetPutArg):
+        (KJS::CTI::emitPutArg):
+        (KJS::CTI::emitPutArgConstant):
+        (KJS::CTI::emitPutCTIParam):
+        (KJS::CTI::emitGetCTIParam):
+        (KJS::CTI::emitPutToCallFrameHeader):
+        (KJS::CTI::emitGetFromCallFrameHeader):
+        (KJS::CTI::emitPutResult):
+        (KJS::CTI::emitDebugExceptionCheck):
+        (KJS::CTI::emitJumpSlowCaseIfNotImm):
+        (KJS::CTI::emitJumpSlowCaseIfNotImms):
+        (KJS::CTI::emitFastArithDeTagImmediate):
+        (KJS::CTI::emitFastArithReTagImmediate):
+        (KJS::CTI::emitFastArithPotentiallyReTagImmediate):
+        (KJS::CTI::emitFastArithImmToInt):
+        (KJS::CTI::emitFastArithIntToImmOrSlowCase):
+        (KJS::CTI::emitFastArithIntToImmNoCheck):
+        (KJS::CTI::CTI):
+        (KJS::CTI::compileOpCall):
+        (KJS::CTI::privateCompileMainPass):
+        (KJS::CTI::privateCompileSlowCases):
+        (KJS::CTI::privateCompile):
+        (KJS::CTI::privateCompileGetByIdSelf):
+        (KJS::CTI::privateCompileGetByIdProto):
+        (KJS::CTI::privateCompileGetByIdChain):
+        (KJS::CTI::privateCompilePutByIdReplace):
+        (KJS::CTI::privateArrayLengthTrampoline):
+        (KJS::CTI::privateStringLengthTrampoline):
+        (KJS::CTI::compileRegExp):
+        * VM/CTI.h:
+        (KJS::CallRecord::CallRecord):
+        (KJS::JmpTable::JmpTable):
+        (KJS::SlowCaseEntry::SlowCaseEntry):
+        (KJS::CTI::JSRInfo::JSRInfo):
+        * kjs/regexp.cpp:
+        (KJS::RegExp::RegExp):
+        * wrec/WREC.cpp:
+        (KJS::GenerateParenthesesNonGreedyFunctor::GenerateParenthesesNonGreedyFunctor):
+        (KJS::GeneratePatternCharacterFunctor::generateAtom):
+        (KJS::GeneratePatternCharacterFunctor::backtrack):
+        (KJS::GenerateCharacterClassFunctor::generateAtom):
+        (KJS::GenerateCharacterClassFunctor::backtrack):
+        (KJS::GenerateBackreferenceFunctor::generateAtom):
+        (KJS::GenerateBackreferenceFunctor::backtrack):
+        (KJS::GenerateParenthesesNonGreedyFunctor::generateAtom):
+        (KJS::GenerateParenthesesNonGreedyFunctor::backtrack):
+        (KJS::WRECGenerate::generateBacktrack1):
+        (KJS::WRECGenerate::generateBacktrackBackreference):
+        (KJS::WRECGenerate::generateBackreferenceQuantifier):
+        (KJS::WRECGenerate::generateNonGreedyQuantifier):
+        (KJS::WRECGenerate::generateGreedyQuantifier):
+        (KJS::WRECGenerate::generatePatternCharacter):
+        (KJS::WRECGenerate::generateCharacterClassInvertedRange):
+        (KJS::WRECGenerate::generateCharacterClassInverted):
+        (KJS::WRECGenerate::generateCharacterClass):
+        (KJS::WRECGenerate::generateParentheses):
+        (KJS::WRECGenerate::generateParenthesesNonGreedy):
+        (KJS::WRECGenerate::gererateParenthesesResetTrampoline):
+        (KJS::WRECGenerate::generateAssertionBOL):
+        (KJS::WRECGenerate::generateAssertionEOL):
+        (KJS::WRECGenerate::generateAssertionWordBoundary):
+        (KJS::WRECGenerate::generateBackreference):
+        (KJS::WRECGenerate::gernerateDisjunction):
+        (KJS::WRECGenerate::terminateDisjunction):
+        (KJS::WRECParser::parseGreedyQuantifier):
+        (KJS::WRECParser::parseQuantifier):
+        (KJS::WRECParser::parsePatternCharacterQualifier):
+        (KJS::WRECParser::parseCharacterClassQuantifier):
+        (KJS::WRECParser::parseBackreferenceQuantifier):
+        (KJS::WRECParser::parseParentheses):
+        (KJS::WRECParser::parseCharacterClass):
+        (KJS::WRECParser::parseOctalEscape):
+        (KJS::WRECParser::parseEscape):
+        (KJS::WRECParser::parseTerm):
+        (KJS::WRECParser::parseDisjunction):
+        * wrec/WREC.h:
+        (KJS::WRECGenerate::WRECGenerate):
+        (KJS::WRECParser::):
+        (KJS::WRECParser::WRECParser):
+        (KJS::WRECParser::parseAlternative):
+        (KJS::WRECParser::isEndOfPattern):
+
+2008-09-06  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by NOBODY (Build fix).
+
+        Fix the sampler build.
+
+        * VM/SamplingTool.h:
+
+2008-09-06  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Maciej Stachowiak.
+
+        Jump through the necessary hoops required to make MSVC cooperate with SFX
+
+        We now explicitly declare the calling convention on all cti_op_* cfunctions,
+        and return int instead of bool where appropriate (despite the cdecl calling
+        convention seems to state MSVC generates code that returns the result value
+        through ecx).  SFX behaves slightly differently under MSVC, specifically it
+        stores the base argument address for the cti_op_* functions in the first
+        argument, and then does the required stack manipulation through that pointer.
+        This is necessary as MSVC's optimisations assume they have complete control
+        of the stack, and periodically elide our stack manipulations, or move
+        values in unexpected ways.  MSVC also frequently produces tail calls which may
+        clobber the first argument, so the MSVC path is slightly less efficient due
+        to the need to restore it.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * VM/CTI.cpp:
+        (KJS::):
+        (KJS::CTI::compileOpCall):
+        (KJS::CTI::privateCompileMainPass):
+        (KJS::CTI::privateCompileSlowCases):
+        * VM/CTI.h:
+        * VM/Machine.cpp:
+        * VM/Machine.h:
+        * masm/MacroAssembler.h:
+        (KJS::MacroAssembler::emitConvertToFastCall):
+        * masm/MacroAssemblerIA32GCC.cpp: Removed.
+           For performance reasons we need these no-op functions to be inlined.
+
+        * masm/MacroAssemblerWin.cpp:
+        (KJS::MacroAssembler::emitRestoreArgumentReference):
+        * wtf/Platform.h:
+
+2008-09-05  Geoffrey Garen  <ggaren@apple.com>
+
+        Reviewed by Maciej Stachowiak, or maybe the other way around.
+        
+        Added the ability to coalesce JITCode buffer grow operations by first
+        growing the buffer and then executing unchecked puts to it.
+        
+        About a 2% speedup on date-format-tofte.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::compileOpCall):
+        * masm/IA32MacroAsm.h:
+        (KJS::JITCodeBuffer::ensureSpace):
+        (KJS::JITCodeBuffer::putByteUnchecked):
+        (KJS::JITCodeBuffer::putByte):
+        (KJS::JITCodeBuffer::putShortUnchecked):
+        (KJS::JITCodeBuffer::putShort):
+        (KJS::JITCodeBuffer::putIntUnchecked):
+        (KJS::JITCodeBuffer::putInt):
+        (KJS::IA32MacroAssembler::emitTestl_i32r):
+        (KJS::IA32MacroAssembler::emitMovl_mr):
+        (KJS::IA32MacroAssembler::emitMovl_rm):
+        (KJS::IA32MacroAssembler::emitMovl_i32m):
+        (KJS::IA32MacroAssembler::emitUnlinkedJe):
+        (KJS::IA32MacroAssembler::emitModRm_rr):
+        (KJS::IA32MacroAssembler::emitModRm_rr_Unchecked):
+        (KJS::IA32MacroAssembler::emitModRm_rm_Unchecked):
+        (KJS::IA32MacroAssembler::emitModRm_rm):
+        (KJS::IA32MacroAssembler::emitModRm_opr):
+        (KJS::IA32MacroAssembler::emitModRm_opr_Unchecked):
+        (KJS::IA32MacroAssembler::emitModRm_opm_Unchecked):
+
+2008-09-05  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Disable WREC and CTI on platforms that we have not yet had a chance to test with.
+
+        * wtf/Platform.h:
+
+2008-09-05  Geoffrey Garen  <ggaren@apple.com>
+
+        Reviewed by Sam Weinig.
+        
+        Use jo instead of a mask compare when fetching array.length and
+        string.length. 4% speedup on array.length / string.length torture
+        test.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateArrayLengthTrampoline):
+        (KJS::CTI::privateStringLengthTrampoline):
+
+2008-09-05  Geoffrey Garen  <ggaren@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Removed a CTI compilation pass by recording labels during bytecode
+        generation. This is more to reduce complexity than it is to improve
+        performance.
+
+        SunSpider reports no change.
+
+        CodeBlock now keeps a "labels" set, which holds the offsets of all the
+        instructions that can be jumped to.
+
+        * VM/CTI.cpp: Nixed a pass.
+
+        * VM/CodeBlock.h: Added a "labels" set.
+
+        * VM/LabelID.h: No need for a special LableID for holding jump
+        destinations, since the CodeBlock now knows all jump destinations.
+
+        * wtf/HashTraits.h: New hash traits to accomodate putting offset 0 in
+        the set.
+
+        * kjs/nodes.cpp:
+        (KJS::TryNode::emitCode): Emit a dummy label to record sret targets.
+
+2008-09-05  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Oliver Hunt and Gavin Barraclough.
+
+        Move the JITCodeBuffer onto Machine and remove the static variables.
+
+        * VM/CTI.cpp: Initialize m_jit with the Machine's code buffer.
+        * VM/Machine.cpp:
+        (KJS::Machine::Machine): Allocate a JITCodeBuffer.
+        * VM/Machine.h:
+        * kjs/RegExpConstructor.cpp:
+        (KJS::constructRegExp): Pass the ExecState through.
+        * kjs/RegExpPrototype.cpp:
+        (KJS::regExpProtoFuncCompile): Ditto.
+        * kjs/StringPrototype.cpp:
+        (KJS::stringProtoFuncMatch): Ditto.
+        (KJS::stringProtoFuncSearch): Ditto.
+        * kjs/nodes.cpp:
+        (KJS::RegExpNode::emitCode): Compile the pattern at code generation time
+        so that we have access to an ExecState.
+        * kjs/nodes.h:
+        (KJS::RegExpNode::):
+        * kjs/nodes2string.cpp:
+        * kjs/regexp.cpp:
+        (KJS::RegExp::RegExp): Pass the ExecState through.
+        (KJS::RegExp::create): Ditto.
+        * kjs/regexp.h:
+        * masm/IA32MacroAsm.h:
+        (KJS::IA32MacroAssembler::IA32MacroAssembler): Reset the JITCodeBuffer when we are
+        constructed.
+        * wrec/WREC.cpp:
+        (KJS::WRECompiler::compile): Retrieve the JITCodeBuffer from the Machine.
+        * wrec/WREC.h:
+
+2008-09-05  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Oliver Hunt and Gavin Barraclough.
+
+        Fix the build when CTI is disabled.
+
+        * VM/CodeBlock.cpp:
+        (KJS::CodeBlock::~CodeBlock):
+        * VM/CodeGenerator.cpp:
+        (KJS::prepareJumpTableForStringSwitch):
+        * VM/Machine.cpp:
+        (KJS::Machine::Machine):
+        (KJS::Machine::~Machine):
+
+2008-09-05  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Mark Rowe.
+
+        Fix some windows abi issues.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompileMainPass):
+        (KJS::CTI::privateCompileSlowCases):
+        * VM/CTI.h:
+        (KJS::CallRecord::CallRecord):
+        (KJS::):
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_resolve_func):
+        (KJS::Machine::cti_op_post_inc):
+        (KJS::Machine::cti_op_resolve_with_base):
+        (KJS::Machine::cti_op_post_dec):
+        * VM/Machine.h:
+
+2008-09-05  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Fix ecma/FunctionObjects/15.3.5.3.js after I broke it in r93.
+
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_call_NotJSFunction): Restore m_callFrame to the correct value after making the native call.
+        (KJS::Machine::cti_op_construct_NotJSConstruct): Ditto.
+
+2008-09-04  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Fix fast/dom/Window/console-functions.html.
+
+        The call frame on the ExecState was not being updated on calls into native functions.  This meant that functions
+        such as console.log would use the line number of the last JS function on the call stack.
+
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_call_NotJSFunction): Update the ExecState's call frame before making a native function call,
+        and restore it when the function is done.
+        (KJS::Machine::cti_op_construct_NotJSConstruct): Ditto.
+
+2008-09-05  Oliver Hunt  <oliver@apple.com>
+
+        Start bringing up SFX on windows.
+
+        Reviewed by Mark Rowe and Sam Weinig
+
+        Start doing the work to bring up SFX on windows.  Initially
+        just working on WREC, as it does not make any calls so reduces
+        the amount of code that needs to be corrected.
+        
+        Start abstracting the CTI JIT codegen engine.
+
+        * ChangeLog:
+        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * VM/CTI.cpp:
+        * masm/IA32MacroAsm.h:
+        * masm/MacroAssembler.h: Added.
+        (KJS::MacroAssembler::MacroAssembler):
+        * masm/MacroAssemblerIA32GCC.cpp: Added.
+        (KJS::MacroAssembler::emitConvertToFastCall):
+        * masm/MacroAssemblerWin.cpp: Added.
+        (KJS::MacroAssembler::emitConvertToFastCall):
+        * wrec/WREC.cpp:
+        (KJS::WRECompiler::parseGreedyQuantifier):
+        (KJS::WRECompiler::parseCharacterClass):
+        (KJS::WRECompiler::parseEscape):
+        (KJS::WRECompiler::compilePattern):
+        * wrec/WREC.h:
+
+2008-09-04  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Support for slow scripts (timeout checking).
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompileMainPass):
+        (KJS::CTI::privateCompile):
+        * VM/Machine.cpp:
+        (KJS::slideRegisterWindowForCall):
+        (KJS::Machine::cti_timeout_check):
+        (KJS::Machine::cti_vm_throw):
+
+2008-09-04  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Mark Rowe.
+
+        Third round of style cleanup.
+
+        * VM/CTI.cpp:
+        * VM/CTI.h:
+        * VM/CodeBlock.h:
+        * VM/Machine.cpp:
+        * VM/Machine.h:
+        * kjs/ExecState.h:
+
+2008-09-04  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Jon Honeycutt.
+
+        Second round of style cleanup.
+
+        * VM/CTI.cpp:
+        * VM/CTI.h:
+        * wrec/WREC.h:
+
+2008-09-04  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Mark Rowe.
+
+        First round of style cleanup.
+
+        * VM/CTI.cpp:
+        * VM/CTI.h:
+        * masm/IA32MacroAsm.h:
+        * wrec/WREC.cpp:
+        * wrec/WREC.h:
+
+2008-09-04  Geoffrey Garen  <ggaren@apple.com>
+
+        Reviewed by Mark Rowe.
+        
+        Merged http://trac.webkit.org/changeset/36081 to work with CTI.
+
+        * VM/Machine.cpp:
+        (KJS::Machine::tryCtiCacheGetByID):
+
+2008-09-04  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Enable profiling in CTI.
+
+        * VM/CTI.h:
+        (KJS::):
+        (KJS::CTI::execute):
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_call_JSFunction):
+        (KJS::Machine::cti_op_call_NotJSFunction):
+        (KJS::Machine::cti_op_ret):
+        (KJS::Machine::cti_op_construct_JSConstruct):
+        (KJS::Machine::cti_op_construct_NotJSConstruct):
+
+2008-09-04  Victor Hernandez  <vhernandez@apple.com>
+
+        Reviewed by Geoffrey Garen.
+        
+        Fixed an #if to support using WREC without CTI.
+
+        * kjs/regexp.cpp:
+        (KJS::RegExp::match):
+
+2008-09-04  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        The array/string length trampolines are owned by the Machine, not the codeblock that compiled them.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateArrayLengthTrampoline):
+        (KJS::CTI::privateStringLengthTrampoline):
+        * VM/Machine.cpp:
+        (KJS::Machine::~Machine):
+        * VM/Machine.h:
+
+2008-09-04  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Gavin Barraclough and Sam Weinig.
+
+        Fix a crash on launch of jsc when GuardMalloc is enabled.
+
+        * kjs/ScopeChain.h:
+        (KJS::ScopeChain::ScopeChain): Initialize m_node to 0 when we have no valid scope chain.
+        (KJS::ScopeChain::~ScopeChain): Null-check m_node before calling deref.
+
+2008-09-03  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Gavin Barraclough and Geoff Garen.
+
+        Fix inspector and fast array access so that it bounds
+        checks correctly.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass2_Main):
+        * masm/IA32MacroAsm.h:
+        (KJS::IA32MacroAssembler::):
+        (KJS::IA32MacroAssembler::emitUnlinkedJb):
+        (KJS::IA32MacroAssembler::emitUnlinkedJbe):
+
+2008-09-03  Mark Rowe  <mrowe@apple.com>
+
+        Move the assertion after the InitializeAndReturn block, as
+        that is used even when CTI is enabled.
+
+        * VM/Machine.cpp:
+        (KJS::Machine::privateExecute):
+
+2008-09-03  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Replace calls to exit with ASSERT_WITH_MESSAGE or ASSERT_NOT_REACHED.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::privateCompile_pass2_Main):
+        (KJS::CTI::privateCompile_pass4_SlowCases):
+        * VM/Machine.cpp:
+        (KJS::Machine::privateExecute):
+        (KJS::Machine::cti_vm_throw):
+
+2008-09-03  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Tweak JavaScriptCore to compile on non-x86 platforms.  This is achieved
+        by wrapping more code with ENABLE(CTI), ENABLE(WREC), and PLATFORM(X86)
+        #if's.
+
+        * VM/CTI.cpp:
+        * VM/CTI.h:
+        * VM/CodeBlock.cpp:
+        (KJS::CodeBlock::printStructureIDs): Use %td as the format specifier for
+        printing a ptrdiff_t.
+        * VM/Machine.cpp:
+        * VM/Machine.h:
+        * kjs/regexp.cpp:
+        (KJS::RegExp::RegExp):
+        (KJS::RegExp::~RegExp):
+        (KJS::RegExp::match):
+        * kjs/regexp.h:
+        * masm/IA32MacroAsm.h:
+        * wrec/WREC.cpp:
+        * wrec/WREC.h:
+        * wtf/Platform.h: Only enable CTI and WREC on x86.  Add an extra define to
+        track whether any MASM-using features are enabled.
+
+2008-09-03  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Copy Geoff's array/string length optimization for CTI.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateArrayLengthTrampoline):
+        (KJS::CTI::privateStringLengthTrampoline):
+        * VM/CTI.h:
+        (KJS::CTI::compileArrayLengthTrampoline):
+        (KJS::CTI::compileStringLengthTrampoline):
+        * VM/Machine.cpp:
+        (KJS::Machine::Machine):
+        (KJS::Machine::getCtiArrayLengthTrampoline):
+        (KJS::Machine::getCtiStringLengthTrampoline):
+        (KJS::Machine::tryCtiCacheGetByID):
+        (KJS::Machine::cti_op_get_by_id_second):
+        * VM/Machine.h:
+        * kjs/JSString.h:
+        * kjs/ustring.h:
+
+2008-09-03  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Implement fast array accesses in CTI - 2-3% progression on sunspider.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::emitFastArithIntToImmNoCheck):
+        (KJS::CTI::compileOpCall):
+        (KJS::CTI::privateCompile_pass2_Main):
+        (KJS::CTI::privateCompile_pass4_SlowCases):
+        * VM/CTI.h:
+        * kjs/JSArray.h:
+
+2008-09-02  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Enable fast property access support in CTI.
+
+        * VM/CTI.cpp:
+        (KJS::ctiSetReturnAddress):
+        (KJS::ctiRepatchCallByReturnAddress):
+        (KJS::CTI::privateCompile_pass2_Main):
+        (KJS::CTI::privateCompile):
+        (KJS::CTI::privateCompileGetByIdSelf):
+        (KJS::CTI::privateCompileGetByIdProto):
+        (KJS::CTI::privateCompileGetByIdChain):
+        (KJS::CTI::privateCompilePutByIdReplace):
+        * VM/CTI.h:
+        (KJS::CTI::compileGetByIdSelf):
+        (KJS::CTI::compileGetByIdProto):
+        (KJS::CTI::compileGetByIdChain):
+        (KJS::CTI::compilePutByIdReplace):
+        * VM/CodeBlock.cpp:
+        (KJS::CodeBlock::~CodeBlock):
+        * VM/CodeBlock.h:
+        * VM/Machine.cpp:
+        (KJS::doSetReturnAddressVmThrowTrampoline):
+        (KJS::Machine::tryCtiCachePutByID):
+        (KJS::Machine::tryCtiCacheGetByID):
+        (KJS::Machine::cti_op_put_by_id):
+        (KJS::Machine::cti_op_put_by_id_second):
+        (KJS::Machine::cti_op_put_by_id_generic):
+        (KJS::Machine::cti_op_put_by_id_fail):
+        (KJS::Machine::cti_op_get_by_id):
+        (KJS::Machine::cti_op_get_by_id_second):
+        (KJS::Machine::cti_op_get_by_id_generic):
+        (KJS::Machine::cti_op_get_by_id_fail):
+        (KJS::Machine::cti_op_throw):
+        (KJS::Machine::cti_vm_throw):
+        * VM/Machine.h:
+        * kjs/JSCell.h:
+        * kjs/JSObject.h:
+        * kjs/PropertyMap.h:
+        * kjs/StructureID.cpp:
+        (KJS::StructureIDChain::StructureIDChain):
+        * masm/IA32MacroAsm.h:
+        (KJS::IA32MacroAssembler::emitCmpl_i32m):
+        (KJS::IA32MacroAssembler::emitMovl_mr):
+        (KJS::IA32MacroAssembler::emitMovl_rm):
+
+2008-09-02  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Gavin Barraclough and Mark Rowe.
+
+        A backslash (\) at the of a RegEx should produce an error.
+        Fixes fast/regex/test1.html.
+
+        * wrec/WREC.cpp:
+        (KJS::WRECompiler::parseEscape):
+
+2008-09-02  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Geoff Garen.
+
+        Link jumps for the slow case of op_loop_if_less.  Fixes acid3.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass4_SlowCases):
+
+2008-09-01  Sam Weinig  <sam@webkit.org>
+
+        Rubber-stamped by Maciej Stachowiak.
+
+        Switch WREC on by default.
+
+        * wtf/Platform.h:
+
+2008-09-01  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Mark Rowe.
+
+        Fix two failures in fast/regex/test1.html
+          - \- in a character class should be treated as a literal -
+          - A missing max quantifier needs to be treated differently than
+            a null max quantifier.
+
+        * wrec/WREC.cpp:
+        (KJS::WRECompiler::generateNonGreedyQuantifier):
+        (KJS::WRECompiler::generateGreedyQuantifier):
+        (KJS::WRECompiler::parseCharacterClass):
+        * wrec/WREC.h:
+        (KJS::Quantifier::Quantifier):
+
+2008-09-01  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Mark Rowe.
+
+        Fix crash in fast/js/kde/evil-n.html
+
+        * kjs/regexp.cpp: Always pass a non-null offset vector to the wrec function.
+
+2008-09-01  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Gavin Barraclough and Mark Rowe.
+
+        Add pattern length limit fixing one test in fast/js.
+
+        * wrec/WREC.cpp:
+        (KJS::WRECompiler::compile):
+        * wrec/WREC.h:
+        (KJS::WRECompiler::):
+
+2008-09-01  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Gavin Barraclough and Mark Rowe.
+
+        Make octal escape parsing/back-reference parsing more closely match 
+        prior behavior fixing one test in fast/js.
+
+        * wrec/WREC.cpp:
+        (KJS::WRECompiler::parseCharacterClass): 8 and 9 should be IdentityEscaped
+        (KJS::WRECompiler::parseEscape):
+        * wrec/WREC.h:
+        (KJS::WRECompiler::peekDigit):
+
+2008-09-01  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Gavin Barraclough and Mark Rowe.
+
+        Fix one mozilla test.
+
+        * wrec/WREC.cpp:
+        (KJS::WRECompiler::generateCharacterClassInverted): Fix incorrect not
+        ascii upper check.
+
+2008-09-01  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Gavin Barraclough and Mark Rowe.
+
+        Parse octal escapes in character classes fixing one mozilla test.
+
+        * wrec/WREC.cpp:
+        (KJS::WRECompiler::parseCharacterClass):
+        (KJS::WRECompiler::parseOctalEscape):
+        * wrec/WREC.h:
+        (KJS::WRECompiler::consumeOctal):
+
+2008-09-01  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Oliver Hunt.
+
+        Fixes two mozilla tests with WREC enabled.
+
+        * wrec/WREC.cpp:
+        (KJS::CharacterClassConstructor::append): Keep the character class sorted
+        when appending another character class.
+
+2008-09-01  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Gavin Barraclough and Mark Rowe.
+
+        Fixes two mozilla tests with WREC enabled.
+
+        * wrec/WREC.cpp:
+        (KJS::CharacterClassConstructor::addSortedRange): Insert the range at the correct position
+        instead of appending it to the end.
+
+2008-09-01  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Move cross-compilation unit call into NEVER_INLINE function.
+
+        * VM/Machine.cpp:
+        (KJS::doSetReturnAddressVmThrowTrampoline):
+
+2008-09-01  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Gavin Barraclough and Geoff Garen.
+
+        Fix one test in fast/js.
+
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_construct_NotJSConstruct): Throw a createNotAConstructorError,
+        instead of a createNotAFunctionError.
+
+2008-08-31  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Maciej Stachowiak.
+        
+        Zero-cost exception handling.  This patch takes the exception checking
+        back of the hot path.  When an exception occurs in a Machine::cti*
+        method, the return address to JIT code is recorded, and is then
+        overwritten with a pointer to a trampoline routine.  When the method
+        returns the trampoline will cause the cti_vm_throw method to be invoked.
+
+        cti_vm_throw uses the return address preserved above, to discover the
+        vPC of the bytecode that raised the exception (using a map build during
+        translation).  From the VPC of the faulting bytecode the vPC of a catch
+        routine may be discovered (unwinding the stack where necesary), and then
+        a bytecode address for the catch routine is looked up.  Final cti_vm_throw
+        overwrites its return address to JIT code again, to trampoline directly
+        to the catch routine.
+        
+        cti_op_throw is handled in a similar fashion.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::emitPutCTIParam):
+        (KJS::CTI::emitPutToCallFrameHeader):
+        (KJS::CTI::emitGetFromCallFrameHeader):
+        (KJS::ctiSetReturnAddressForArgs):
+        (KJS::CTI::emitDebugExceptionCheck):
+        (KJS::CTI::printOpcodeOperandTypes):
+        (KJS::CTI::emitCall):
+        (KJS::CTI::compileOpCall):
+        (KJS::CTI::privateCompile_pass2_Main):
+        (KJS::CTI::privateCompile):
+        * VM/CTI.h:
+        (KJS::CallRecord::CallRecord):
+        (KJS::):
+        (KJS::CTI::execute):
+        * VM/CodeBlock.h:
+        * VM/Machine.cpp:
+        (KJS::Machine::privateExecute):
+        (KJS::Machine::cti_op_instanceof):
+        (KJS::Machine::cti_op_call_NotJSFunction):
+        (KJS::Machine::cti_op_resolve):
+        (KJS::Machine::cti_op_resolve_func):
+        (KJS::Machine::cti_op_resolve_skip):
+        (KJS::Machine::cti_op_resolve_with_base):
+        (KJS::Machine::cti_op_throw):
+        (KJS::Machine::cti_op_in):
+        (KJS::Machine::cti_vm_throw):
+        * VM/RegisterFile.h:
+        (KJS::RegisterFile::):
+        * kjs/ExecState.h:
+        (KJS::ExecState::setCtiReturnAddress):
+        (KJS::ExecState::ctiReturnAddress):
+        * masm/IA32MacroAsm.h:
+        (KJS::IA32MacroAssembler::):
+        (KJS::IA32MacroAssembler::emitPushl_m):
+        (KJS::IA32MacroAssembler::emitPopl_m):
+        (KJS::IA32MacroAssembler::getRelocatedAddress):
+
+2008-08-31  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Fall back to PCRE for any regexp containing parentheses until we correctly backtrack within them.
+
+        * wrec/WREC.cpp:
+        (KJS::WRECompiler::parseParentheses):
+        * wrec/WREC.h:
+        (KJS::WRECompiler::):
+
+2008-08-31  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Fix several issues within ecma_3/RegExp/perlstress-001.js with WREC enabled.
+
+        * wrec/WREC.cpp:
+        (KJS::WRECompiler::generateNonGreedyQuantifier): Compare with the maximum quantifier count rather than the minimum.
+        (KJS::WRECompiler::generateAssertionEOL): Do a register-to-register comparison rather than immediate-to-register.
+        (KJS::WRECompiler::parseCharacterClass): Pass through the correct inversion flag.
+
+2008-08-30  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Re-fix the six remaining failures in the Mozilla JavaScript tests in a manner that does not kill performance.
+        This shows up as a 0.6% progression on SunSpider on my machine.
+
+        Grow the JITCodeBuffer's underlying buffer when we run out of space rather than just bailing out.
+
+        * VM/CodeBlock.h:
+        (KJS::CodeBlock::~CodeBlock): Switch to using fastFree now that JITCodeBuffer::copy uses fastMalloc.
+        * kjs/regexp.cpp: Ditto.
+        * masm/IA32MacroAsm.h:
+        (KJS::JITCodeBuffer::growBuffer):
+        (KJS::JITCodeBuffer::JITCodeBuffer):
+        (KJS::JITCodeBuffer::~JITCodeBuffer):
+        (KJS::JITCodeBuffer::putByte):
+        (KJS::JITCodeBuffer::putShort):
+        (KJS::JITCodeBuffer::putInt):
+        (KJS::JITCodeBuffer::reset):
+        (KJS::JITCodeBuffer::copy):
+
+2008-08-29  Oliver Hunt  <oliver@apple.com>
+
+        RS=Maciej
+
+        Roll out previous patch as it causes a 5% performance regression
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * VM/CTI.cpp:
+        (KJS::getJCB):
+        (KJS::CTI::privateCompile):
+        * VM/CodeBlock.h:
+        (KJS::CodeBlock::~CodeBlock):
+        * masm/IA32MacroAsm.h:
+        (KJS::JITCodeBuffer::JITCodeBuffer):
+        (KJS::JITCodeBuffer::putByte):
+        (KJS::JITCodeBuffer::putShort):
+        (KJS::JITCodeBuffer::putInt):
+        (KJS::JITCodeBuffer::getEIP):
+        (KJS::JITCodeBuffer::start):
+        (KJS::JITCodeBuffer::getOffset):
+        (KJS::JITCodeBuffer::reset):
+        (KJS::JITCodeBuffer::copy):
+        (KJS::IA32MacroAssembler::emitModRm_rr):
+        (KJS::IA32MacroAssembler::emitModRm_rm):
+        (KJS::IA32MacroAssembler::emitModRm_rmsib):
+        (KJS::IA32MacroAssembler::IA32MacroAssembler):
+        (KJS::IA32MacroAssembler::emitInt3):
+        (KJS::IA32MacroAssembler::emitPushl_r):
+        (KJS::IA32MacroAssembler::emitPopl_r):
+        (KJS::IA32MacroAssembler::emitMovl_rr):
+        (KJS::IA32MacroAssembler::emitAddl_rr):
+        (KJS::IA32MacroAssembler::emitAddl_i8r):
+        (KJS::IA32MacroAssembler::emitAddl_i32r):
+        (KJS::IA32MacroAssembler::emitAddl_mr):
+        (KJS::IA32MacroAssembler::emitAndl_rr):
+        (KJS::IA32MacroAssembler::emitAndl_i32r):
+        (KJS::IA32MacroAssembler::emitCmpl_i8r):
+        (KJS::IA32MacroAssembler::emitCmpl_rr):
+        (KJS::IA32MacroAssembler::emitCmpl_rm):
+        (KJS::IA32MacroAssembler::emitCmpl_i32r):
+        (KJS::IA32MacroAssembler::emitCmpl_i32m):
+        (KJS::IA32MacroAssembler::emitCmpw_rm):
+        (KJS::IA32MacroAssembler::emitOrl_rr):
+        (KJS::IA32MacroAssembler::emitOrl_i8r):
+        (KJS::IA32MacroAssembler::emitSubl_rr):
+        (KJS::IA32MacroAssembler::emitSubl_i8r):
+        (KJS::IA32MacroAssembler::emitSubl_i32r):
+        (KJS::IA32MacroAssembler::emitSubl_mr):
+        (KJS::IA32MacroAssembler::emitTestl_i32r):
+        (KJS::IA32MacroAssembler::emitTestl_rr):
+        (KJS::IA32MacroAssembler::emitXorl_i8r):
+        (KJS::IA32MacroAssembler::emitXorl_rr):
+        (KJS::IA32MacroAssembler::emitSarl_i8r):
+        (KJS::IA32MacroAssembler::emitSarl_CLr):
+        (KJS::IA32MacroAssembler::emitShl_i8r):
+        (KJS::IA32MacroAssembler::emitShll_CLr):
+        (KJS::IA32MacroAssembler::emitMull_rr):
+        (KJS::IA32MacroAssembler::emitIdivl_r):
+        (KJS::IA32MacroAssembler::emitCdq):
+        (KJS::IA32MacroAssembler::emitMovl_mr):
+        (KJS::IA32MacroAssembler::emitMovzwl_mr):
+        (KJS::IA32MacroAssembler::emitMovl_rm):
+        (KJS::IA32MacroAssembler::emitMovl_i32r):
+        (KJS::IA32MacroAssembler::emitMovl_i32m):
+        (KJS::IA32MacroAssembler::emitLeal_mr):
+        (KJS::IA32MacroAssembler::emitRet):
+        (KJS::IA32MacroAssembler::emitJmpN_r):
+        (KJS::IA32MacroAssembler::emitJmpN_m):
+        (KJS::IA32MacroAssembler::emitCall):
+        (KJS::IA32MacroAssembler::label):
+        (KJS::IA32MacroAssembler::emitUnlinkedJmp):
+        (KJS::IA32MacroAssembler::emitUnlinkedJne):
+        (KJS::IA32MacroAssembler::emitUnlinkedJe):
+        (KJS::IA32MacroAssembler::emitUnlinkedJl):
+        (KJS::IA32MacroAssembler::emitUnlinkedJle):
+        (KJS::IA32MacroAssembler::emitUnlinkedJge):
+        (KJS::IA32MacroAssembler::emitUnlinkedJae):
+        (KJS::IA32MacroAssembler::emitUnlinkedJo):
+        (KJS::IA32MacroAssembler::link):
+        * wrec/WREC.cpp:
+        (KJS::WRECompiler::compilePattern):
+        (KJS::WRECompiler::compile):
+        * wrec/WREC.h:
+
+2008-08-29  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Have JITCodeBuffer manage a Vector containing the generated code so that it can grow
+        as needed when generating code for a large function.  This fixes all six remaining failures
+        in Mozilla tests in both debug and release builds.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile):
+        * VM/CodeBlock.h:
+        (KJS::CodeBlock::~CodeBlock):
+        * masm/IA32MacroAsm.h:
+        (KJS::JITCodeBuffer::putByte):
+        (KJS::JITCodeBuffer::putShort):
+        (KJS::JITCodeBuffer::putInt):
+        (KJS::JITCodeBuffer::getEIP):
+        (KJS::JITCodeBuffer::start):
+        (KJS::JITCodeBuffer::getOffset):
+        (KJS::JITCodeBuffer::getCode):
+        (KJS::IA32MacroAssembler::emitModRm_rr):
+        * wrec/WREC.cpp:
+        (KJS::WRECompiler::compilePattern):
+        * wrec/WREC.h:
+
+2008-08-29  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Implement parsing of octal escapes in regular expressions.  This fixes three Mozilla tests.
+
+        * wrec/WREC.cpp:
+        (KJS::WRECompiler::parseOctalEscape):
+        (KJS::WRECompiler::parseEscape): Parse the escape sequence as an octal escape if it has a leading zero.
+        Add a FIXME about treating invalid backreferences as octal escapes in the future.
+        * wrec/WREC.h:
+        (KJS::WRECompiler::consumeNumber): Multiply by 10 rather than 0 so that we handle numbers with more than
+        one digit.
+        * wtf/ASCIICType.h:
+        (WTF::isASCIIOctalDigit):
+
+2008-08-29  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Mark Rowe.
+
+        Pass vPC to instanceof method.  Fixes 2 mozilla tests in debug.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass2_Main):
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_instanceof):
+
+2008-08-29  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Mark Rowe.
+
+        Pass vPCs to resolve methods for correct exception creation.  Fixes
+        17 mozilla tests in debug.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass2_Main):
+        * VM/CTI.h:
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_resolve):
+        (KJS::Machine::cti_op_resolve_func):
+        (KJS::Machine::cti_op_resolve_skip):
+        (KJS::Machine::cti_op_resolve_with_base):
+
+2008-08-29  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Remembering to actually throw the exception passed to op throw helps.
+        Regressions 19 -> 6.
+
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_throw):
+        (KJS::Machine::cti_vm_throw):
+
+2008-08-29  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Support for exception unwinding the stack.
+        
+        Once upon a time, Sam asked me for a bettr ChangeLog entry.  The return address
+        is now preserved on entry to a JIT code function (if we preserve lazily we need
+        restore the native return address during exception stack unwind).  This takes
+        the number of regressions down from ~150 to 19.
+
+        * VM/CTI.cpp:
+        (KJS::getJCB):
+        (KJS::CTI::emitExceptionCheck):
+        (KJS::CTI::compileOpCall):
+        (KJS::CTI::privateCompile_pass2_Main):
+        (KJS::CTI::privateCompile):
+        * VM/CTI.h:
+        (KJS::):
+        * VM/Machine.cpp:
+        (KJS::Machine::throwException):
+        (KJS::Machine::cti_op_call_JSFunction):
+        (KJS::Machine::cti_op_call_NotJSFunction):
+        (KJS::Machine::cti_op_construct_JSConstruct):
+        (KJS::Machine::cti_op_construct_NotJSConstruct):
+        (KJS::Machine::cti_op_throw):
+        (KJS::Machine::cti_vm_throw):
+
+2008-08-29  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Fix js1_2/regexp/word_boundary.js and four other Mozilla tests with WREC enabled.
+
+        * wrec/WREC.cpp:
+        (KJS::WRECompiler::generateCharacterClassInvertedRange): If none of the exact matches
+        succeeded, jump to failure.
+        (KJS::WRECompiler::compilePattern): Restore and increment the current position stored
+        on the stack to ensure that it will be reset to the correct position after a failed
+        match has consumed input.
+
+2008-08-29  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Fix a hang in ecma_3/RegExp/15.10.2-1.js with WREC enabled.
+        A backreference with a quantifier would get stuck in an infinite
+        loop if the captured range was empty.
+
+        * wrec/WREC.cpp:
+        (KJS::WRECompiler::generateBackreferenceQuantifier): If the captured range
+        was empty, do not attempt to match the backreference.
+        (KJS::WRECompiler::parseBackreferenceQuantifier):
+        * wrec/WREC.h:
+        (KJS::Quantifier::):
+
+2008-08-28  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Oliver Hunt.
+
+        Implement op_debug.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::privateCompile_pass2_Main):
+        * VM/Machine.cpp:
+        (KJS::Machine::debug):
+        (KJS::Machine::privateExecute):
+        (KJS::Machine::cti_op_debug):
+        * VM/Machine.h:
+
+2008-08-28  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Gavin Barraclough and Geoff Garen.
+
+        Implement op_switch_string fixing 1 mozilla test and one test in fast/js.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::privateCompile_pass2_Main):
+        (KJS::CTI::privateCompile):
+        * VM/CTI.h:
+        (KJS::SwitchRecord::):
+        (KJS::SwitchRecord::SwitchRecord):
+        * VM/CodeBlock.cpp:
+        (KJS::CodeBlock::dump):
+        * VM/CodeBlock.h:
+        (KJS::ExpressionRangeInfo::):
+        (KJS::StringJumpTable::offsetForValue):
+        (KJS::StringJumpTable::ctiForValue):
+        (KJS::SimpleJumpTable::add):
+        (KJS::SimpleJumpTable::ctiForValue):
+        * VM/CodeGenerator.cpp:
+        (KJS::prepareJumpTableForStringSwitch):
+        * VM/Machine.cpp:
+        (KJS::Machine::privateExecute):
+        (KJS::Machine::cti_op_switch_string):
+        * VM/Machine.h:
+
+2008-08-28  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Do not recurse on the machine stack when executing op_call.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::emitGetPutArg):
+        (KJS::CTI::emitPutArg):
+        (KJS::CTI::emitPutArgConstant):
+        (KJS::CTI::compileOpCall):
+        (KJS::CTI::privateCompile_pass2_Main):
+        (KJS::CTI::privateCompile):
+        * VM/CTI.h:
+        (KJS::):
+        (KJS::CTI::compile):
+        (KJS::CTI::execute):
+        (KJS::CTI::):
+        * VM/Machine.cpp:
+        (KJS::Machine::Machine):
+        (KJS::Machine::execute):
+        (KJS::Machine::cti_op_call_JSFunction):
+        (KJS::Machine::cti_op_call_NotJSFunction):
+        (KJS::Machine::cti_op_ret):
+        (KJS::Machine::cti_op_construct_JSConstruct):
+        (KJS::Machine::cti_op_construct_NotJSConstruct):
+        (KJS::Machine::cti_op_call_eval):
+        * VM/Machine.h:
+        * VM/Register.h:
+        (KJS::Register::Register):
+        * VM/RegisterFile.h:
+        (KJS::RegisterFile::):
+        * kjs/InternalFunction.h:
+        (KJS::InternalFunction::InternalFunction):
+        * kjs/JSFunction.h:
+        (KJS::JSFunction::JSFunction):
+        * kjs/ScopeChain.h:
+        (KJS::ScopeChain::ScopeChain):
+        * masm/IA32MacroAsm.h:
+        (KJS::IA32MacroAssembler::):
+        (KJS::IA32MacroAssembler::emitModRm_opm):
+        (KJS::IA32MacroAssembler::emitCmpl_i32m):
+        (KJS::IA32MacroAssembler::emitCallN_r):
+
+2008-08-28  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Mark Rowe.
+
+        Exit instead of crashing in ctiUnsupported and ctiTimedOut.
+
+        * VM/Machine.cpp:
+        (KJS::ctiUnsupported):
+        (KJS::ctiTimedOut):
+
+2008-08-28  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Maciej Stachowiak.
+
+        Implement codegen for op_jsr and op_sret.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::privateCompile_pass2_Main):
+        (KJS::CTI::privateCompile):
+        * VM/CTI.h:
+        (KJS::CTI::JSRInfo::JSRInfo):
+        * masm/IA32MacroAsm.h:
+        (KJS::IA32MacroAssembler::emitJmpN_m):
+        (KJS::IA32MacroAssembler::linkAbsoluteAddress):
+
+2008-08-28  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Initial support for exceptions (throw / catch must occur in same CodeBlock).
+
+        * VM/CTI.cpp:
+        (KJS::CTI::emitExceptionCheck):
+        (KJS::CTI::emitCall):
+        (KJS::CTI::privateCompile_pass2_Main):
+        (KJS::CTI::privateCompile_pass4_SlowCases):
+        (KJS::CTI::privateCompile):
+        * VM/CTI.h:
+        * VM/CodeBlock.cpp:
+        (KJS::CodeBlock::nativeExceptionCodeForHandlerVPC):
+        * VM/CodeBlock.h:
+        * VM/CodeGenerator.cpp:
+        (KJS::CodeGenerator::emitCatch):
+        * VM/Machine.cpp:
+        (KJS::Machine::throwException):
+        (KJS::Machine::privateExecute):
+        (KJS::ctiUnsupported):
+        (KJS::ctiTimedOut):
+        (KJS::Machine::cti_op_add):
+        (KJS::Machine::cti_op_pre_inc):
+        (KJS::Machine::cti_timeout_check):
+        (KJS::Machine::cti_op_loop_if_less):
+        (KJS::Machine::cti_op_put_by_id):
+        (KJS::Machine::cti_op_get_by_id):
+        (KJS::Machine::cti_op_instanceof):
+        (KJS::Machine::cti_op_del_by_id):
+        (KJS::Machine::cti_op_mul):
+        (KJS::Machine::cti_op_call):
+        (KJS::Machine::cti_op_resolve):
+        (KJS::Machine::cti_op_construct):
+        (KJS::Machine::cti_op_get_by_val):
+        (KJS::Machine::cti_op_resolve_func):
+        (KJS::Machine::cti_op_sub):
+        (KJS::Machine::cti_op_put_by_val):
+        (KJS::Machine::cti_op_lesseq):
+        (KJS::Machine::cti_op_loop_if_true):
+        (KJS::Machine::cti_op_negate):
+        (KJS::Machine::cti_op_resolve_skip):
+        (KJS::Machine::cti_op_div):
+        (KJS::Machine::cti_op_pre_dec):
+        (KJS::Machine::cti_op_jless):
+        (KJS::Machine::cti_op_not):
+        (KJS::Machine::cti_op_jtrue):
+        (KJS::Machine::cti_op_post_inc):
+        (KJS::Machine::cti_op_eq):
+        (KJS::Machine::cti_op_lshift):
+        (KJS::Machine::cti_op_bitand):
+        (KJS::Machine::cti_op_rshift):
+        (KJS::Machine::cti_op_bitnot):
+        (KJS::Machine::cti_op_resolve_with_base):
+        (KJS::Machine::cti_op_mod):
+        (KJS::Machine::cti_op_less):
+        (KJS::Machine::cti_op_neq):
+        (KJS::Machine::cti_op_post_dec):
+        (KJS::Machine::cti_op_urshift):
+        (KJS::Machine::cti_op_bitxor):
+        (KJS::Machine::cti_op_bitor):
+        (KJS::Machine::cti_op_call_eval):
+        (KJS::Machine::cti_op_throw):
+        (KJS::Machine::cti_op_push_scope):
+        (KJS::Machine::cti_op_stricteq):
+        (KJS::Machine::cti_op_nstricteq):
+        (KJS::Machine::cti_op_to_jsnumber):
+        (KJS::Machine::cti_op_in):
+        (KJS::Machine::cti_op_del_by_val):
+        (KJS::Machine::cti_vm_throw):
+        * VM/Machine.h:
+        * kjs/ExecState.h:
+        * masm/IA32MacroAsm.h:
+        (KJS::IA32MacroAssembler::emitCmpl_i32m):
+
+2008-08-28  Mark Rowe  <mrowe@apple.com>
+
+        Rubber-stamped by Oliver Hunt.
+
+        Print debugging info to stderr so that run-webkit-tests can capture it.
+        This makes it easy to check whether test failures are due to unimplemented
+        op codes, missing support for exceptions, etc.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::printOpcodeOperandTypes):
+        (KJS::CTI::privateCompile_pass2_Main):
+        (KJS::CTI::privateCompile_pass4_SlowCases):
+        (KJS::CTI::privateCompile):
+        * VM/Machine.cpp:
+        (KJS::Machine::privateExecute):
+        (KJS::ctiException):
+        (KJS::ctiUnsupported):
+        (KJS::Machine::cti_op_call):
+        (KJS::Machine::cti_op_resolve):
+        (KJS::Machine::cti_op_construct):
+        (KJS::Machine::cti_op_get_by_val):
+        (KJS::Machine::cti_op_resolve_func):
+        (KJS::Machine::cti_op_resolve_skip):
+        (KJS::Machine::cti_op_resolve_with_base):
+        (KJS::Machine::cti_op_call_eval):
+
+2008-08-27  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Gavin Barraclough and Maciej Stachowiak.
+
+        Fix fast/js/bitwise-and-on-undefined.html.
+
+        A temporary value in the slow path of op_bitand was being stored in edx, but was
+        being clobbered by emitGetPutArg before we used it.  To fix this, emitGetPutArg
+        now takes a third argument that specifies the scratch register to use when loading
+        from memory.  This allows us to avoid clobbering the temporary in op_bitand.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::emitGetPutArg):
+        (KJS::CTI::privateCompile_pass2_Main):
+        (KJS::CTI::privateCompile_pass4_SlowCases):
+        * VM/CTI.h:
+
+2008-08-27  Mark Rowe  <mrowe@apple.com>
+
+        Rubber-stamped by Oliver Hunt.
+
+        Switch CTI on by default.
+
+        * wtf/Platform.h:
+
+2008-08-27  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Fix the build of the full WebKit stack.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj: Mark two new headers as private so they can be pulled in from WebCore.
+        * VM/CTI.h: Fix build issues that show up when compiled with GCC 4.2 as part of WebCore.
+        * wrec/WREC.h: Ditto.
+
+2008-08-27  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Implement op_new_error.  Does not fix any tests as it is always followed by the unimplemented op_throw.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::privateCompile_pass2_Main):
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_new_error):
+        * VM/Machine.h:
+
+2008-08-27  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Gavin Barraclough and Geoff Garen.
+
+        Implement op_put_getter and op_put_setter.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::privateCompile_pass2_Main):
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_put_getter):
+        (KJS::Machine::cti_op_put_setter):
+        * VM/Machine.h:
+
+2008-08-27  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Gavin Barraclough and Geoff Garen.
+
+        Implement op_del_by_val fixing 3 mozilla tests.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::privateCompile_pass2_Main):
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_del_by_val):
+        * VM/Machine.h:
+
+2008-08-27  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Quick & dirty fix to get SamplingTool sampling op_call.
+
+        * VM/SamplingTool.h:
+        (KJS::SamplingTool::callingHostFunction):
+
+2008-08-27  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Gavin Barraclough and Geoff Garen.
+
+        Fix op_put_by_index.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass2_Main): Use emitPutArgConstant instead of emitGetPutArg
+        for the property value.
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_put_by_index): Get the property value from the correct argument.
+
+2008-08-27  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Gavin Barraclough and Geoff Garen.
+
+        Implement op_switch_imm in the CTI fixing 13 mozilla tests.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::privateCompile_pass2_Main):
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_switch_imm):
+        * VM/Machine.h:
+
+2008-08-27  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Implement op_switch_char in CTI.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::emitCall):
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::privateCompile_pass2_Main):
+        (KJS::CTI::privateCompile):
+        * VM/CTI.h:
+        (KJS::CallRecord::CallRecord):
+        (KJS::SwitchRecord::SwitchRecord):
+        * VM/CodeBlock.h:
+        (KJS::SimpleJumpTable::SimpleJumpTable::ctiForValue):
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_switch_char):
+        * VM/Machine.h:
+        * masm/IA32MacroAsm.h:
+        (KJS::IA32MacroAssembler::):
+        (KJS::IA32MacroAssembler::emitJmpN_r):
+        (KJS::IA32MacroAssembler::getRelocatedAddress):
+        * wtf/Platform.h:
+
+2008-08-26  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Mark Rowe.
+
+        Implement op_put_by_index to fix 1 mozilla test.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::privateCompile_pass2_Main):
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_put_by_index):
+        * VM/Machine.h:
+
+2008-08-26  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Geoff Garen.
+
+        More fixes from Geoff's review.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::emitGetArg):
+        (KJS::CTI::emitGetPutArg):
+        (KJS::CTI::emitPutArg):
+        (KJS::CTI::emitPutArgConstant):
+        (KJS::CTI::getConstantImmediateNumericArg):
+        (KJS::CTI::emitGetCTIParam):
+        (KJS::CTI::emitPutResult):
+        (KJS::CTI::emitCall):
+        (KJS::CTI::emitJumpSlowCaseIfNotImm):
+        (KJS::CTI::emitJumpSlowCaseIfNotImms):
+        (KJS::CTI::getDeTaggedConstantImmediate):
+        (KJS::CTI::emitFastArithDeTagImmediate):
+        (KJS::CTI::emitFastArithReTagImmediate):
+        (KJS::CTI::emitFastArithPotentiallyReTagImmediate):
+        (KJS::CTI::emitFastArithImmToInt):
+        (KJS::CTI::emitFastArithIntToImmOrSlowCase):
+        (KJS::CTI::privateCompile_pass2_Main):
+        (KJS::CTI::privateCompile_pass4_SlowCases):
+        (KJS::CTI::privateCompile):
+        * VM/CTI.h:
+
+2008-08-26  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Gavin Barraclough and Geoff Garen.
+
+        Implement op_jmp_scopes to fix 2 Mozilla tests.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::privateCompile_pass2_Main):
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_push_new_scope): Update ExecState::m_scopeChain after calling ARG_setScopeChain.
+        (KJS::Machine::cti_op_jmp_scopes):
+        * VM/Machine.h:
+
+2008-08-26  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        WebKit Regular Expression Compiler. (set ENABLE_WREC = 1 in Platform.h).
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * kjs/regexp.cpp:
+        * kjs/regexp.h:
+        * wrec: Added.
+        * wrec/WREC.cpp: Added.
+        * wrec/WREC.h: Added.
+        * wtf/Platform.h:
+
+2008-08-26  Sam Weinig  <sam@webkit.org>
+
+        Rubber-stamped by Oliver Hunt.
+
+        Remove bogus assertion.
+
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_del_by_id):
+
+2008-08-26  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Implement op_push_new_scope and stub out op_catch.  This fixes 11 Mozilla tests.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::privateCompile_pass2_Main):
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_push_new_scope):
+        (KJS::Machine::cti_op_catch):
+        * VM/Machine.h:
+
+2008-08-26  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Clean up op_resolve_base so that it shares its implementation with the bytecode interpreter.
+
+        * VM/Machine.cpp:
+        (KJS::inlineResolveBase):
+        (KJS::resolveBase):
+
+2008-08-26  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Add codegen support for op_instanceof, fixing 15 mozilla tests.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::privateCompile_pass2_Main):
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_instanceof):
+        (KJS::Machine::cti_op_del_by_id):
+        * VM/Machine.h:
+        * wtf/Platform.h:
+
+2008-08-26  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Geoff Garen.
+
+        Fixes for initial review comments.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::ctiCompileGetArg):
+        (KJS::CTI::ctiCompileGetPutArg):
+        (KJS::CTI::ctiCompilePutResult):
+        (KJS::CTI::ctiCompileCall):
+        (KJS::CTI::CTI):
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::printOpcodeOperandTypes):
+        (KJS::CTI::privateCompile_pass2_Main):
+        (KJS::CTI::privateCompile_pass4_SlowCases):
+        (KJS::CTI::privateCompile):
+        * VM/CTI.h:
+        * VM/Register.h:
+        * kjs/JSValue.h:
+
+2008-08-26  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Gavin Barraclough and Geoff Garen.
+
+        Fix up exception checking code.
+
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_call):
+        (KJS::Machine::cti_op_resolve):
+        (KJS::Machine::cti_op_construct):
+        (KJS::Machine::cti_op_resolve_func):
+        (KJS::Machine::cti_op_resolve_skip):
+        (KJS::Machine::cti_op_resolve_with_base):
+        (KJS::Machine::cti_op_call_eval):
+
+2008-08-26  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Oliver Hunt.
+
+        Fix slowcase for op_post_inc and op_post_dec fixing 2 mozilla tests.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass4_SlowCases):
+
+2008-08-26  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Implement op_in, fixing 8 mozilla tests.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::privateCompile_pass2_Main):
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_in):
+        * VM/Machine.h:
+
+2008-08-26  Mark Rowe  <mrowe@apple.com>
+
+        Rubber-stamped by Oliver Hunt.
+
+        Don't hardcode the size of a Register for op_new_array.  Fixes a crash
+        seen during the Mozilla tests.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass2_Main):
+
+2008-08-26  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Gavin Barraclough and Geoff Garen.
+
+        Add support for op_push_scope and op_pop_scope, fixing 20 mozilla tests.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::privateCompile_pass2_Main):
+        * VM/CTI.h:
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_push_scope):
+        (KJS::Machine::cti_op_pop_scope):
+        * VM/Machine.h:
+
+2008-08-26  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Maciej Stachowiak.
+
+        Add codegen support for op_del_by_id, fixing 49 mozilla tests.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::privateCompile_pass2_Main):
+        * VM/Machine.cpp:
+        (KJS::Machine::cti_op_del_by_id):
+        * VM/Machine.h:
+
+2008-08-26  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Gavin Barraclough and Geoff Garen.
+
+        Don't hardcode the size of a Register for op_get_scoped_var and op_put_scoped_var 
+        fixing 513 mozilla tests in debug build.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass2_Main):
+
+2008-08-26  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Maciej Stachowiak.
+        
+        Added code generator support for op_loop, fixing around 60 mozilla tests.
+
+        * VM/CTI.cpp:
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::privateCompile_pass2_Main):
+
+2008-08-26  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Set -fomit-frame-pointer in the correct location.
+
+        * Configurations/JavaScriptCore.xcconfig:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2008-08-26  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Geoff Garen.
+        
+        Inital cut of CTI, Geoff's review fixes to follow.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * VM/CTI.cpp: Added.
+        (KJS::getJCB):
+        (KJS::CTI::ctiCompileGetArg):
+        (KJS::CTI::ctiCompileGetPutArg):
+        (KJS::CTI::ctiCompilePutArg):
+        (KJS::CTI::ctiCompilePutArgImm):
+        (KJS::CTI::ctiImmediateNumericArg):
+        (KJS::CTI::ctiCompileGetCTIParam):
+        (KJS::CTI::ctiCompilePutResult):
+        (KJS::CTI::ctiCompileCall):
+        (KJS::CTI::slowCaseIfNotImm):
+        (KJS::CTI::slowCaseIfNotImms):
+        (KJS::CTI::ctiFastArithDeTagConstImmediate):
+        (KJS::CTI::ctiFastArithDeTagImmediate):
+        (KJS::CTI::ctiFastArithReTagImmediate):
+        (KJS::CTI::ctiFastArithPotentiallyReTagImmediate):
+        (KJS::CTI::ctiFastArithImmToInt):
+        (KJS::CTI::ctiFastArithIntToImmOrSlowCase):
+        (KJS::CTI::CTI):
+        (KJS::CTI::privateCompile_pass1_Scan):
+        (KJS::CTI::ctiCompileAdd):
+        (KJS::CTI::ctiCompileAddImm):
+        (KJS::CTI::ctiCompileAddImmNotInt):
+        (KJS::CTI::TEMP_HACK_PRINT_TYPES):
+        (KJS::CTI::privateCompile_pass2_Main):
+        (KJS::CTI::privateCompile_pass3_Link):
+        (KJS::CTI::privateCompile_pass4_SlowCases):
+        (KJS::CTI::privateCompile):
+        * VM/CTI.h: Added.
+        (KJS::CTI2Result::CTI2Result):
+        (KJS::CallRecord::CallRecord):
+        (KJS::JmpTable::JmpTable):
+        (KJS::SlowCaseEntry::SlowCaseEntry):
+        (KJS::CTI::compile):
+        (KJS::CTI::LabelInfo::LabelInfo):
+        * VM/CodeBlock.h:
+        (KJS::CodeBlock::CodeBlock):
+        (KJS::CodeBlock::~CodeBlock):
+        * VM/Machine.cpp:
+        (KJS::Machine::execute):
+        (KJS::Machine::privateExecute):
+        (KJS::ctiException):
+        (KJS::ctiUnsupported):
+        (KJS::ctiTimedOut):
+        (KJS::Machine::cti_op_end):
+        (KJS::Machine::cti_op_add):
+        (KJS::Machine::cti_op_pre_inc):
+        (KJS::Machine::cti_timeout_check):
+        (KJS::Machine::cti_op_loop_if_less):
+        (KJS::Machine::cti_op_new_object):
+        (KJS::Machine::cti_op_put_by_id):
+        (KJS::Machine::cti_op_get_by_id):
+        (KJS::Machine::cti_op_mul):
+        (KJS::Machine::cti_op_new_func):
+        (KJS::Machine::cti_op_call):
+        (KJS::Machine::cti_op_ret):
+        (KJS::Machine::cti_op_new_array):
+        (KJS::Machine::cti_op_resolve):
+        (KJS::Machine::cti_op_construct):
+        (KJS::Machine::cti_op_get_by_val):
+        (KJS::Machine::cti_op_resolve_func):
+        (KJS::Machine::cti_op_sub):
+        (KJS::Machine::cti_op_put_by_val):
+        (KJS::Machine::cti_op_lesseq):
+        (KJS::Machine::cti_op_loop_if_true):
+        (KJS::Machine::cti_op_negate):
+        (KJS::Machine::cti_op_resolve_base):
+        (KJS::Machine::cti_op_resolve_skip):
+        (KJS::Machine::cti_op_div):
+        (KJS::Machine::cti_op_pre_dec):
+        (KJS::Machine::cti_op_jless):
+        (KJS::Machine::cti_op_not):
+        (KJS::Machine::cti_op_jtrue):
+        (KJS::Machine::cti_op_post_inc):
+        (KJS::Machine::cti_op_eq):
+        (KJS::Machine::cti_op_lshift):
+        (KJS::Machine::cti_op_bitand):
+        (KJS::Machine::cti_op_rshift):
+        (KJS::Machine::cti_op_bitnot):
+        (KJS::Machine::cti_op_resolve_with_base):
+        (KJS::Machine::cti_op_new_func_exp):
+        (KJS::Machine::cti_op_mod):
+        (KJS::Machine::cti_op_less):
+        (KJS::Machine::cti_op_neq):
+        (KJS::Machine::cti_op_post_dec):
+        (KJS::Machine::cti_op_urshift):
+        (KJS::Machine::cti_op_bitxor):
+        (KJS::Machine::cti_op_new_regexp):
+        (KJS::Machine::cti_op_bitor):
+        (KJS::Machine::cti_op_call_eval):
+        (KJS::Machine::cti_op_throw):
+        (KJS::Machine::cti_op_get_pnames):
+        (KJS::Machine::cti_op_next_pname):
+        (KJS::Machine::cti_op_typeof):
+        (KJS::Machine::cti_op_stricteq):
+        (KJS::Machine::cti_op_nstricteq):
+        (KJS::Machine::cti_op_to_jsnumber):
+        * VM/Machine.h:
+        * VM/Register.h:
+        (KJS::Register::jsValue):
+        (KJS::Register::getJSValue):
+        (KJS::Register::codeBlock):
+        (KJS::Register::scopeChain):
+        (KJS::Register::i):
+        (KJS::Register::r):
+        (KJS::Register::vPC):
+        (KJS::Register::jsPropertyNameIterator):
+        * VM/SamplingTool.cpp:
+        (KJS::):
+        (KJS::SamplingTool::run):
+        (KJS::SamplingTool::dump):
+        * VM/SamplingTool.h:
+        * kjs/JSImmediate.h:
+        (KJS::JSImmediate::zeroImmediate):
+        (KJS::JSImmediate::oneImmediate):
+        * kjs/JSValue.h:
+        * kjs/JSVariableObject.h:
+        (KJS::JSVariableObject::JSVariableObjectData::offsetOf_registers):
+        (KJS::JSVariableObject::offsetOf_d):
+        (KJS::JSVariableObject::offsetOf_Data_registers):
+        * masm: Added.
+        * masm/IA32MacroAsm.h: Added.
+        (KJS::JITCodeBuffer::JITCodeBuffer):
+        (KJS::JITCodeBuffer::putByte):
+        (KJS::JITCodeBuffer::putShort):
+        (KJS::JITCodeBuffer::putInt):
+        (KJS::JITCodeBuffer::getEIP):
+        (KJS::JITCodeBuffer::start):
+        (KJS::JITCodeBuffer::getOffset):
+        (KJS::JITCodeBuffer::reset):
+        (KJS::JITCodeBuffer::copy):
+        (KJS::IA32MacroAssembler::):
+        (KJS::IA32MacroAssembler::emitModRm_rr):
+        (KJS::IA32MacroAssembler::emitModRm_rm):
+        (KJS::IA32MacroAssembler::emitModRm_rmsib):
+        (KJS::IA32MacroAssembler::emitModRm_opr):
+        (KJS::IA32MacroAssembler::emitModRm_opm):
+        (KJS::IA32MacroAssembler::IA32MacroAssembler):
+        (KJS::IA32MacroAssembler::emitInt3):
+        (KJS::IA32MacroAssembler::emitPushl_r):
+        (KJS::IA32MacroAssembler::emitPopl_r):
+        (KJS::IA32MacroAssembler::emitMovl_rr):
+        (KJS::IA32MacroAssembler::emitAddl_rr):
+        (KJS::IA32MacroAssembler::emitAddl_i8r):
+        (KJS::IA32MacroAssembler::emitAddl_i32r):
+        (KJS::IA32MacroAssembler::emitAddl_mr):
+        (KJS::IA32MacroAssembler::emitAndl_rr):
+        (KJS::IA32MacroAssembler::emitAndl_i32r):
+        (KJS::IA32MacroAssembler::emitCmpl_i8r):
+        (KJS::IA32MacroAssembler::emitCmpl_rr):
+        (KJS::IA32MacroAssembler::emitCmpl_rm):
+        (KJS::IA32MacroAssembler::emitCmpl_i32r):
+        (KJS::IA32MacroAssembler::emitCmpw_rm):
+        (KJS::IA32MacroAssembler::emitOrl_rr):
+        (KJS::IA32MacroAssembler::emitOrl_i8r):
+        (KJS::IA32MacroAssembler::emitSubl_rr):
+        (KJS::IA32MacroAssembler::emitSubl_i8r):
+        (KJS::IA32MacroAssembler::emitSubl_i32r):
+        (KJS::IA32MacroAssembler::emitSubl_mr):
+        (KJS::IA32MacroAssembler::emitTestl_i32r):
+        (KJS::IA32MacroAssembler::emitTestl_rr):
+        (KJS::IA32MacroAssembler::emitXorl_i8r):
+        (KJS::IA32MacroAssembler::emitXorl_rr):
+        (KJS::IA32MacroAssembler::emitSarl_i8r):
+        (KJS::IA32MacroAssembler::emitSarl_CLr):
+        (KJS::IA32MacroAssembler::emitShl_i8r):
+        (KJS::IA32MacroAssembler::emitShll_CLr):
+        (KJS::IA32MacroAssembler::emitMull_rr):
+        (KJS::IA32MacroAssembler::emitIdivl_r):
+        (KJS::IA32MacroAssembler::emitCdq):
+        (KJS::IA32MacroAssembler::emitMovl_mr):
+        (KJS::IA32MacroAssembler::emitMovzwl_mr):
+        (KJS::IA32MacroAssembler::emitMovl_rm):
+        (KJS::IA32MacroAssembler::emitMovl_i32r):
+        (KJS::IA32MacroAssembler::emitMovl_i32m):
+        (KJS::IA32MacroAssembler::emitLeal_mr):
+        (KJS::IA32MacroAssembler::emitRet):
+        (KJS::IA32MacroAssembler::JmpSrc::JmpSrc):
+        (KJS::IA32MacroAssembler::JmpDst::JmpDst):
+        (KJS::IA32MacroAssembler::emitCall):
+        (KJS::IA32MacroAssembler::label):
+        (KJS::IA32MacroAssembler::emitUnlinkedJmp):
+        (KJS::IA32MacroAssembler::emitUnlinkedJne):
+        (KJS::IA32MacroAssembler::emitUnlinkedJe):
+        (KJS::IA32MacroAssembler::emitUnlinkedJl):
+        (KJS::IA32MacroAssembler::emitUnlinkedJle):
+        (KJS::IA32MacroAssembler::emitUnlinkedJge):
+        (KJS::IA32MacroAssembler::emitUnlinkedJae):
+        (KJS::IA32MacroAssembler::emitUnlinkedJo):
+        (KJS::IA32MacroAssembler::emitPredictionNotTaken):
+        (KJS::IA32MacroAssembler::link):
+        (KJS::IA32MacroAssembler::copy):
+        * wtf/Platform.h:
+
+2008-08-26  Oliver Hunt  <oliver@apple.com>
+
+        RS=Maciej.
+
+        Enabled -fomit-frame-pointer on Release and Production builds, add additional Profiling build config for shark, etc.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+
+=== Start merge of squirrelfish-extreme ===
+
 2008-09-06  Cameron Zwarich  <cwzwarich@uwaterloo.ca>
 
         Reviewed by Maciej Stachowiak.
index e210db1..84dce84 100644 (file)
@@ -14,3 +14,7 @@ PRODUCT_NAME = JavaScriptCore;
 
 // This needs to be kept sorted, and in sync with FEATURE_DEFINES in WebCore.xcconfig, WebKit.xcconfig and the default settings of build-webkit.
 FEATURE_DEFINES = ENABLE_CROSS_DOCUMENT_MESSAGING ENABLE_DATABASE ENABLE_DOM_STORAGE ENABLE_ICONDATABASE ENABLE_OFFLINE_WEB_APPLICATIONS ENABLE_SVG ENABLE_SVG_ANIMATION ENABLE_SVG_AS_IMAGE ENABLE_SVG_FONTS ENABLE_SVG_FOREIGN_OBJECT ENABLE_SVG_USE ENABLE_VIDEO ENABLE_XPATH ENABLE_XSLT;
+
+OTHER_CFLAGS = $(OTHER_CFLAGS_$(CONFIGURATION)_$(CURRENT_VARIANT));
+OTHER_CFLAGS_Release_normal = -fomit-frame-pointer;
+OTHER_CFLAGS_Production_normal = -fomit-frame-pointer;
index a0a0271..e080f39 100644 (file)
@@ -42,7 +42,7 @@
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               AdditionalIncludeDirectories="&quot;$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\&quot;;../../;../../API/;../../pcre/;../../kjs/;../../VM/;../../wtf/;../../profiler;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\icu&quot;;../../../icu/include;&quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility&quot;"\r
+                               AdditionalIncludeDirectories="&quot;$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\&quot;;../../;../../API/;../../pcre/;../../kjs/;../../VM/;../../wtf/;../../profiler;../../masm/;../../wrec/;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\icu&quot;;../../../icu/include;&quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility&quot;"\r
                                PreprocessorDefinitions="__STD_C"\r
                                ForcedIncludeFiles=""\r
                        />\r
@@ -73,7 +73,7 @@
                        />\r
                        <Tool\r
                                Name="VCPostBuildEventTool"\r
-                               CommandLine="mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\unicode\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\unicode\icu\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\kjs\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\VM\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\profiler\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\kjs\create_hash_table&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\pcre\pcre.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;&#x0D;&#x0A;if exist &quot;$(WebKitOutputDir)\buildfailed&quot; del &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;"\r
+                               CommandLine="mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\unicode\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\unicode\icu\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\kjs\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\VM\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\masm\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wrec\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\profiler\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\kjs\create_hash_table&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\pcre\pcre.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;&#x0D;&#x0A;if exist &quot;$(WebKitOutputDir)\buildfailed&quot; del &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;"\r
                        />\r
                </Configuration>\r
                <Configuration\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               AdditionalIncludeDirectories="&quot;$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\&quot;;../../;../../API/;../../pcre/;../../kjs/;../../VM/;../../wtf/;../../profiler;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\icu&quot;;../../../icu/include;&quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility&quot;"\r
+                               AdditionalIncludeDirectories="&quot;$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\&quot;;../../;../../API/;../../pcre/;../../kjs/;../../VM/;../../wtf/;../../profiler;../../masm/;../../wrec/;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\icu&quot;;../../../icu/include;&quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility&quot;"\r
                                PreprocessorDefinitions="__STD_C"\r
                                ForcedIncludeFiles=""\r
                        />\r
                        />\r
                        <Tool\r
                                Name="VCPostBuildEventTool"\r
-                               CommandLine="mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\unicode\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\unicode\icu\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\kjs\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\VM\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\profiler\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\kjs\create_hash_table&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\pcre\pcre.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;&#x0D;&#x0A;if exist &quot;$(WebKitOutputDir)\buildfailed&quot; del &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;"\r
+                               CommandLine="mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\unicode\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\unicode\icu\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\kjs\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\VM\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\masm\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wrec\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\profiler\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\kjs\create_hash_table&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\pcre\pcre.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;&#x0D;&#x0A;if exist &quot;$(WebKitOutputDir)\buildfailed&quot; del &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;"\r
                        />\r
                </Configuration>\r
                <Configuration\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               AdditionalIncludeDirectories="&quot;$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\&quot;;../../;../../API/;../../pcre/;../../kjs/;../../VM/;../../wtf/;../../profiler;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\icu&quot;;../../../icu/include;&quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility&quot;"\r
+                               AdditionalIncludeDirectories="&quot;$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\&quot;;../../;../../API/;../../pcre/;../../kjs/;../../VM/;../../wtf/;../../profiler;../../masm/;../../wrec/;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\icu&quot;;../../../icu/include;&quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility&quot;"\r
                                PreprocessorDefinitions="__STD_C"\r
                                ForcedIncludeFiles=""\r
                        />\r
                        />\r
                        <Tool\r
                                Name="VCPostBuildEventTool"\r
-                               CommandLine="mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\unicode\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\unicode\icu\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\kjs\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\VM\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\profiler\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\kjs\create_hash_table&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\pcre\pcre.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;&#x0D;&#x0A;if exist &quot;$(WebKitOutputDir)\buildfailed&quot; del &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;"\r
+                               CommandLine="mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\unicode\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\unicode\icu\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\kjs\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\VM\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\masm\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wrec\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\profiler\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\kjs\create_hash_table&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\pcre\pcre.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;&#x0D;&#x0A;if exist &quot;$(WebKitOutputDir)\buildfailed&quot; del &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;"\r
                        />\r
                </Configuration>\r
                <Configuration\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               AdditionalIncludeDirectories="&quot;$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\&quot;;../../;../../API/;../../pcre/;../../kjs/;../../VM/;../../wtf/;../../profiler;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\icu&quot;;../../../icu/include;&quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility&quot;"\r
+                               AdditionalIncludeDirectories="&quot;$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\&quot;;../../;../../API/;../../pcre/;../../kjs/;../../VM/;../../wtf/;../../profiler;../../masm/;../../wrec/;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\icu&quot;;../../../icu/include;&quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility&quot;"\r
                                PreprocessorDefinitions="__STD_C"\r
                                ForcedIncludeFiles=""\r
                        />\r
                        />\r
                        <Tool\r
                                Name="VCPostBuildEventTool"\r
-                               CommandLine="mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\unicode\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\unicode\icu\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\kjs\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\VM\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\profiler\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\kjs\create_hash_table&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\pcre\pcre.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;&#x0D;&#x0A;if exist &quot;$(WebKitOutputDir)\buildfailed&quot; del &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;"\r
+                               CommandLine="mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\unicode\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wtf\unicode\icu\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\kjs\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\VM\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\masm\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\wrec\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\profiler\*.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\kjs\create_hash_table&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\..\pcre\pcre.h&quot; &quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;&#x0D;&#x0A;&#x0D;&#x0A;if exist &quot;$(WebKitOutputDir)\buildfailed&quot; del &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;"\r
                        />\r
                </Configuration>\r
        </Configurations>\r
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath="..\..\VM\CTI.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\VM\CTI.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath="..\..\VM\ExceptionHelpers.cpp"\r
                                >\r
                        </File>\r
                                >\r
                        </File>\r
                </Filter>\r
+               <Filter\r
+                       Name="masm"\r
+                       >\r
+                       <File\r
+                               RelativePath="..\..\masm\IA32MacroAsm.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\masm\MacroAssembler.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\masm\MacroAssemblerWin.cpp"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="wrec"\r
+                       >\r
+                       <File\r
+                               RelativePath="..\..\wrec\WREC.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\wrec\WREC.h"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
        </Files>\r
        <Globals>\r
        </Globals>\r
index 516804b..ef2746a 100644 (file)
                65FDE49C0BDD1D4A00E80111 /* Assertions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65E217B808E7EECC0023E5F6 /* Assertions.cpp */; };
                8613F45A0E3A433E00C948FD /* SamplingTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8613F4580E3A433E00C948FD /* SamplingTool.cpp */; };
                8613F45B0E3A433E00C948FD /* SamplingTool.h in Headers */ = {isa = PBXBuildFile; fileRef = 8613F4590E3A433E00C948FD /* SamplingTool.h */; };
+               8683B02E0E636482004C19EE /* CTI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8683B02B0E636482004C19EE /* CTI.cpp */; };
+               8683B02F0E636482004C19EE /* CTI.h in Headers */ = {isa = PBXBuildFile; fileRef = 8683B02C0E636482004C19EE /* CTI.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               869081410E640C89000D36ED /* IA32MacroAsm.h in Headers */ = {isa = PBXBuildFile; fileRef = 869081400E640C89000D36ED /* IA32MacroAsm.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               869083150E6518D7000D36ED /* WREC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 869083130E6518D7000D36ED /* WREC.cpp */; };
+               869083160E6518D7000D36ED /* WREC.h in Headers */ = {isa = PBXBuildFile; fileRef = 869083140E6518D7000D36ED /* WREC.h */; settings = {ATTRIBUTES = (Private, ); }; };
                905B02AE0E28640F006DF882 /* RefCountedLeakCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 905B02AD0E28640F006DF882 /* RefCountedLeakCounter.cpp */; };
                90D3469C0E285280009492EE /* RefCountedLeakCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 90D3469B0E285280009492EE /* RefCountedLeakCounter.h */; settings = {ATTRIBUTES = (Private, ); }; };
                930754C108B0F68000AB3056 /* pcre_compile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 930754BF08B0F68000AB3056 /* pcre_compile.cpp */; };
                A72701B60DADE94900E548D7 /* ExceptionHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A72701B40DADE94900E548D7 /* ExceptionHelpers.cpp */; };
                A72701B90DADE94900E548D7 /* ExceptionHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = A72701B30DADE94900E548D7 /* ExceptionHelpers.h */; };
                A727FF6B0DA3092200E548D7 /* JSPropertyNameIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */; };
+               A763F79D0E70E0FE00BC151E /* MacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = A763F79C0E70E0FE00BC151E /* MacroAssembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A7C31DAA0DBEBA4300FDF8EB /* SegmentedVector.h in Headers */ = {isa = PBXBuildFile; fileRef = A7C31DA80DBEBA4300FDF8EB /* SegmentedVector.h */; };
                BC02E90D0E1839DB000F9297 /* ErrorConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9050E1839DB000F9297 /* ErrorConstructor.h */; };
                BC02E90F0E1839DB000F9297 /* ErrorPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9070E1839DB000F9297 /* ErrorPrototype.h */; };
                7E6D517E0E729AF400778C37 /* JavaScriptCore.Debug.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = JavaScriptCore.Debug.exp; sourceTree = "<group>"; };
                8613F4580E3A433E00C948FD /* SamplingTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SamplingTool.cpp; path = VM/SamplingTool.cpp; sourceTree = "<group>"; };
                8613F4590E3A433E00C948FD /* SamplingTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SamplingTool.h; path = VM/SamplingTool.h; sourceTree = "<group>"; };
+               8683B02B0E636482004C19EE /* CTI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CTI.cpp; path = VM/CTI.cpp; sourceTree = "<group>"; };
+               8683B02C0E636482004C19EE /* CTI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CTI.h; path = VM/CTI.h; sourceTree = "<group>"; };
+               869081400E640C89000D36ED /* IA32MacroAsm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IA32MacroAsm.h; sourceTree = "<group>"; };
+               869083130E6518D7000D36ED /* WREC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WREC.cpp; sourceTree = "<group>"; };
+               869083140E6518D7000D36ED /* WREC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WREC.h; sourceTree = "<group>"; };
                905B02AD0E28640F006DF882 /* RefCountedLeakCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RefCountedLeakCounter.cpp; sourceTree = "<group>"; };
                90D3469B0E285280009492EE /* RefCountedLeakCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RefCountedLeakCounter.h; sourceTree = "<group>"; };
                9303F567099118FA00AD71B8 /* OwnPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OwnPtr.h; sourceTree = "<group>"; };
                A72701B40DADE94900E548D7 /* ExceptionHelpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ExceptionHelpers.cpp; path = VM/ExceptionHelpers.cpp; sourceTree = "<group>"; };
                A727FF650DA3053B00E548D7 /* JSPropertyNameIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSPropertyNameIterator.h; path = VM/JSPropertyNameIterator.h; sourceTree = "<group>"; };
                A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSPropertyNameIterator.cpp; path = VM/JSPropertyNameIterator.cpp; sourceTree = "<group>"; };
+               A763F79C0E70E0FE00BC151E /* MacroAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssembler.h; sourceTree = "<group>"; };
                A7C31DA80DBEBA4300FDF8EB /* SegmentedVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SegmentedVector.h; path = VM/SegmentedVector.h; sourceTree = "<group>"; };
                A7E42C180E3938830065A544 /* JSStaticScopeObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStaticScopeObject.h; sourceTree = "<group>"; };
                A7E42C190E3938830065A544 /* JSStaticScopeObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStaticScopeObject.cpp; sourceTree = "<group>"; };
                                7E6D517E0E729AF400778C37 /* JavaScriptCore.Debug.exp */,
                                F5C290E60284F98E018635CA /* JavaScriptCorePrefix.h */,
                                1432EBD70A34CAD400717B9F /* API */,
-                               65162EF108E6A21C007556CD /* wtf */,
-                               65417203039E01F90058BFEB /* pcre */,
-                               65417200039E01BA0058BFEB /* kjs */,
                                149B15DF0D81F887009CB8C7 /* compiler */,
-                               149B15E00D81F88D009CB8C7 /* vm */,
                                1480DB9A0DDC2231003CFDF2 /* debugger */,
+                               65417200039E01BA0058BFEB /* kjs */,
+                               8690813F0E640C89000D36ED /* masm */,
+                               65417203039E01F90058BFEB /* pcre */,
                                95AB831A0DA42C6900BC83F3 /* profiler */,
+                               141211000A48772600480255 /* tests */,
+                               149B15E00D81F88D009CB8C7 /* vm */,
+                               869083120E6518D7000D36ED /* wrec */,
+                               65162EF108E6A21C007556CD /* wtf */,
+                               1C90513E0BA9E8830081E9D0 /* Configurations */,
                                650FDF8D09D0FCA700769E54 /* Derived Sources */,
+                               0867D69AFE84028FC02AAC07 /* Frameworks */,
                                034768DFFF38A50411DB9C8B /* Products */,
                                932FC3C20824BB70005B3C75 /* Resources */,
-                               0867D69AFE84028FC02AAC07 /* Frameworks */,
-                               1C90513E0BA9E8830081E9D0 /* Configurations */,
-                               141211000A48772600480255 /* tests */,
                        );
                        name = JavaScriptCore;
                        sourceTree = "<group>";
                149B15E00D81F88D009CB8C7 /* vm */ = {
                        isa = PBXGroup;
                        children = (
+                               8683B02B0E636482004C19EE /* CTI.cpp */,
+                               8683B02C0E636482004C19EE /* CTI.h */,
                                8613F4580E3A433E00C948FD /* SamplingTool.cpp */,
                                8613F4590E3A433E00C948FD /* SamplingTool.h */,
                                149B1A9E0D86ED73009CB8C7 /* CodeBlock.cpp */,
                        tabWidth = 4;
                        usesTabs = 0;
                };
+               8690813F0E640C89000D36ED /* masm */ = {
+                       isa = PBXGroup;
+                       children = (
+                               A763F79C0E70E0FE00BC151E /* MacroAssembler.h */,
+                               869081400E640C89000D36ED /* IA32MacroAsm.h */,
+                       );
+                       path = masm;
+                       sourceTree = "<group>";
+               };
+               869083120E6518D7000D36ED /* wrec */ = {
+                       isa = PBXGroup;
+                       children = (
+                               869083130E6518D7000D36ED /* WREC.cpp */,
+                               869083140E6518D7000D36ED /* WREC.h */,
+                       );
+                       path = wrec;
+                       sourceTree = "<group>";
+               };
                932FC3C20824BB70005B3C75 /* Resources */ = {
                        isa = PBXGroup;
                        children = (
                                C0A272630E50A06300E96E15 /* NotFound.h in Headers */,
                                E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */,
                                9534AAFB0E5B7A9600B8A45B /* JSProfilerPrivate.h in Headers */,
+                               8683B02F0E636482004C19EE /* CTI.h in Headers */,
+                               869081410E640C89000D36ED /* IA32MacroAsm.h in Headers */,
+                               869083160E6518D7000D36ED /* WREC.h in Headers */,
                                933040040E6A749400786E6A /* SmallStrings.h in Headers */,
                                BCDE3AB80E6C82F5001453A7 /* StructureID.h in Headers */,
+                               A763F79D0E70E0FE00BC151E /* MacroAssembler.h in Headers */,
                                147B83AC0E6DB8C9004775A4 /* BatchedTransitionOptimizer.h in Headers */,
                                147B84630E6DE6B1004775A4 /* PutPropertySlot.h in Headers */,
                        );
                                8613F45A0E3A433E00C948FD /* SamplingTool.cpp in Sources */,
                                E124A8F80E555775003091F1 /* OpaqueJSString.cpp in Sources */,
                                95F6E6950E5B5F970091E860 /* JSProfilerPrivate.cpp in Sources */,
+                               8683B02E0E636482004C19EE /* CTI.cpp in Sources */,
+                               869083150E6518D7000D36ED /* WREC.cpp in Sources */,
                                9330402C0E6A764000786E6A /* SmallStrings.cpp in Sources */,
                                BCDE3B430E6C832D001453A7 /* StructureID.cpp in Sources */,
                        );
                        };
                        name = Production;
                };
+               A761483D0E6402F700E357FA /* Profiling */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 1C9051440BA9E8A70081E9D0 /* DebugRelease.xcconfig */;
+                       buildSettings = {
+                               STRIP_INSTALLED_PRODUCT = NO;
+                       };
+                       name = Profiling;
+               };
+               A761483E0E6402F700E357FA /* Profiling */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = All;
+                       };
+                       name = Profiling;
+               };
+               A761483F0E6402F700E357FA /* Profiling */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 1C9051430BA9E8A70081E9D0 /* JavaScriptCore.xcconfig */;
+                       buildSettings = {
+                               INSTALL_PATH = "$(BUILT_PRODUCTS_DIR)";
+                       };
+                       name = Profiling;
+               };
+               A76148400E6402F700E357FA /* Profiling */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "Generate Derived Sources";
+                       };
+                       name = Profiling;
+               };
+               A76148410E6402F700E357FA /* Profiling */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = minidom;
+                       };
+                       name = Profiling;
+               };
+               A76148420E6402F700E357FA /* Profiling */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = testapi;
+                       };
+                       name = Profiling;
+               };
+               A76148430E6402F700E357FA /* Profiling */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = jsc;
+                       };
+                       name = Profiling;
+               };
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
                        buildConfigurations = (
                                1412113A0A48798400480255 /* Debug */,
                                1412113B0A48798400480255 /* Release */,
+                               A76148410E6402F700E357FA /* Profiling */,
                                1412113C0A48798400480255 /* Production */,
                        );
                        defaultConfigurationIsVisible = 0;
                        buildConfigurations = (
                                149C275E08902AFE008A9EFC /* Debug */,
                                149C275F08902AFE008A9EFC /* Release */,
+                               A761483F0E6402F700E357FA /* Profiling */,
                                149C276108902AFE008A9EFC /* Production */,
                        );
                        defaultConfigurationIsVisible = 0;
                        buildConfigurations = (
                                149C276808902AFE008A9EFC /* Debug */,
                                149C276908902AFE008A9EFC /* Release */,
+                               A76148430E6402F700E357FA /* Profiling */,
                                149C276B08902AFE008A9EFC /* Production */,
                        );
                        defaultConfigurationIsVisible = 0;
                        buildConfigurations = (
                                149C276D08902AFE008A9EFC /* Debug */,
                                149C276E08902AFE008A9EFC /* Release */,
+                               A761483E0E6402F700E357FA /* Profiling */,
                                149C277008902AFE008A9EFC /* Production */,
                        );
                        defaultConfigurationIsVisible = 0;
                        buildConfigurations = (
                                149C277208902AFE008A9EFC /* Debug */,
                                149C277308902AFE008A9EFC /* Release */,
+                               A761483D0E6402F700E357FA /* Profiling */,
                                149C277508902AFE008A9EFC /* Production */,
                        );
                        defaultConfigurationIsVisible = 0;
                        buildConfigurations = (
                                14BD59D70A3E8FC900BAF59C /* Debug */,
                                14BD59D80A3E8FC900BAF59C /* Release */,
+                               A76148420E6402F700E357FA /* Profiling */,
                                14BD59D90A3E8FC900BAF59C /* Production */,
                        );
                        defaultConfigurationIsVisible = 0;
                        buildConfigurations = (
                                65FB3F7809D11EBD00F49DEB /* Debug */,
                                65FB3F7909D11EBD00F49DEB /* Release */,
+                               A76148400E6402F700E357FA /* Profiling */,
                                65FB3F7A09D11EBD00F49DEB /* Production */,
                        );
                        defaultConfigurationIsVisible = 0;
diff --git a/JavaScriptCore/VM/CTI.cpp b/JavaScriptCore/VM/CTI.cpp
new file mode 100644 (file)
index 0000000..5dd5eca
--- /dev/null
@@ -0,0 +1,1931 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "CTI.h"
+
+#if ENABLE(CTI)
+
+#include "CodeBlock.h"
+#include "JSArray.h"
+#include "Machine.h"
+#include "wrec/WREC.h"
+
+using namespace std;
+
+namespace KJS {
+
+#if COMPILER(GCC) && PLATFORM(X86)
+asm(
+".globl _ctiTrampoline" "\n"
+"_ctiTrampoline:" "\n"
+    "pushl %esi" "\n"
+    "pushl %edi" "\n"
+    "subl $0x24, %esp" "\n"
+    "movl $512, %esi" "\n"
+    "call *0x30(%esp)" "\n" //Ox30 = 0x0C * 4, 0x0C = CTI_ARGS_code
+    "addl $0x24, %esp" "\n"
+    "popl %edi" "\n"
+    "popl %esi" "\n"
+    "ret" "\n"
+);
+
+asm(
+".globl _ctiVMThrowTrampoline" "\n"
+"_ctiVMThrowTrampoline:" "\n"
+#ifndef NDEBUG
+    "movl 0x34(%esp), %ecx" "\n" //Ox34 = 0x0D * 4, 0x0D = CTI_ARGS_exec
+    "cmpl $0, 8(%ecx)" "\n"
+    "jne 1f" "\n"
+    "int3" "\n"
+    "1:" "\n"
+#endif
+    "call __ZN3KJS7Machine12cti_vm_throwEPv" "\n"
+    "addl $0x24, %esp" "\n"
+    "popl %edi" "\n"
+    "popl %esi" "\n"
+    "ret" "\n"
+);
+    
+#elif COMPILER(MSVC)
+extern "C"
+{
+    
+    __declspec(naked) JSValue* ctiTrampoline(void* code, ExecState* exec, RegisterFile* registerFile, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue** exception, Profiler**)
+    {
+        __asm {
+            push esi;
+            push edi;
+            sub esp, 0x24;
+            mov esi, 512;
+            mov [esp], esp;
+            call [esp + 0x30];
+            add esp, 0x24;
+            pop edi;
+            pop esi;
+            ret;
+        }
+    }
+    
+    __declspec(naked) void ctiVMThrowTrampoline()
+    {
+        __asm {
+           mov [esp], esp;
+            call KJS::Machine::cti_vm_throw;
+            add esp, 0x24;
+            pop edi;
+            pop esi;
+            ret;
+        }
+    }
+    
+}
+
+#endif
+
+
+// get arg puts an arg from the SF register array into a h/w register
+ALWAYS_INLINE void CTI::emitGetArg(unsigned src, MacroAssembler::RegisterID dst)
+{
+    // TODO: we want to reuse values that are already in registers if we can - add a register allocator!
+    if (src < m_codeBlock->constantRegisters.size()) {
+        JSValue* js = m_codeBlock->constantRegisters[src].jsValue(m_exec);
+        m_jit.emitMovl_i32r((unsigned)js, dst);
+    } else
+        m_jit.emitMovl_mr(src * sizeof(Register), MacroAssembler::edi, dst);
+}
+
+// get arg puts an arg from the SF register array onto the stack, as an arg to a context threaded function.
+ALWAYS_INLINE void CTI::emitGetPutArg(unsigned src, unsigned offset, MacroAssembler::RegisterID scratch)
+{
+    if (src < m_codeBlock->constantRegisters.size()) {
+        JSValue* js = m_codeBlock->constantRegisters[src].jsValue(m_exec);
+        m_jit.emitMovl_i32m((unsigned)js, offset + sizeof(void*), MacroAssembler::esp);
+    } else {
+        m_jit.emitMovl_mr(src * sizeof(Register), MacroAssembler::edi, scratch);
+        m_jit.emitMovl_rm(scratch, offset + sizeof(void*), MacroAssembler::esp);
+    }
+}
+
+// puts an arg onto the stack, as an arg to a context threaded function.
+ALWAYS_INLINE void CTI::emitPutArg(MacroAssembler::RegisterID src, unsigned offset)
+{
+    m_jit.emitMovl_rm(src, offset + sizeof(void*), MacroAssembler::esp);
+}
+
+ALWAYS_INLINE void CTI::emitPutArgConstant(unsigned value, unsigned offset)
+{
+    m_jit.emitMovl_i32m(value, offset + sizeof(void*), MacroAssembler::esp);
+}
+
+ALWAYS_INLINE JSValue* CTI::getConstantImmediateNumericArg(unsigned src)
+{
+    if (src < m_codeBlock->constantRegisters.size()) {
+        JSValue* js = m_codeBlock->constantRegisters[src].jsValue(m_exec);
+        return JSImmediate::isNumber(js) ? js : 0;
+    }
+    return 0;
+}
+
+ALWAYS_INLINE void CTI::emitPutCTIParam(MacroAssembler::RegisterID from, unsigned name)
+{
+    m_jit.emitMovl_rm(from, name * sizeof(void*), MacroAssembler::esp);
+}
+
+ALWAYS_INLINE void CTI::emitGetCTIParam(unsigned name, MacroAssembler::RegisterID to)
+{
+    m_jit.emitMovl_mr(name * sizeof(void*), MacroAssembler::esp, to);
+}
+
+ALWAYS_INLINE void CTI::emitPutToCallFrameHeader(MacroAssembler::RegisterID from, RegisterFile::CallFrameHeaderEntry entry)
+{
+    m_jit.emitMovl_rm(from, -((m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) - entry) * sizeof(Register), MacroAssembler::edi);
+}
+
+ALWAYS_INLINE void CTI::emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, MacroAssembler::RegisterID to)
+{
+    m_jit.emitMovl_mr(-((m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) - entry) * sizeof(Register), MacroAssembler::edi, to);
+}
+
+ALWAYS_INLINE void CTI::emitPutResult(unsigned dst, MacroAssembler::RegisterID from)
+{
+    m_jit.emitMovl_rm(from, dst * sizeof(Register), MacroAssembler::edi);
+    // FIXME: #ifndef NDEBUG, Write the correct m_type to the register.
+}
+
+#if ENABLE(SAMPLING_TOOL)
+unsigned incall = 0;
+#endif
+
+void ctiSetReturnAddress(void** where, void* what)
+{
+    *where = what;
+}
+
+void ctiRepatchCallByReturnAddress(void* where, void* what)
+{
+    ((void**)where)[-1] = (void*)((uintptr_t)what - (uintptr_t)where);
+}
+
+#ifdef NDEBUG
+
+ALWAYS_INLINE void CTI::emitDebugExceptionCheck()
+{
+}
+
+#else
+
+ALWAYS_INLINE void CTI::emitDebugExceptionCheck()
+{
+    emitGetCTIParam(CTI_ARGS_exec, MacroAssembler::ecx);
+    m_jit.emitCmpl_i32m(0, OBJECT_OFFSET(ExecState, m_exception), MacroAssembler::ecx);
+    MacroAssembler::JmpSrc noException = m_jit.emitUnlinkedJe();
+    m_jit.emitInt3();
+    m_jit.link(noException, m_jit.label());
+}
+
+void CTI::printOpcodeOperandTypes(unsigned src1, unsigned src2)
+{
+    char which1 = '*';
+    if (src1 < m_codeBlock->constantRegisters.size()) {
+        JSValue* js = m_codeBlock->constantRegisters[src1].jsValue(m_exec);
+        which1 = 
+            JSImmediate::isImmediate(js) ?
+                (JSImmediate::isNumber(js) ? 'i' :
+                JSImmediate::isBoolean(js) ? 'b' :
+                js->isUndefined() ? 'u' :
+                js->isNull() ? 'n' : '?')
+                :
+            (js->isString() ? 's' :
+            js->isObject() ? 'o' :
+            'k');
+    }
+    char which2 = '*';
+    if (src2 < m_codeBlock->constantRegisters.size()) {
+        JSValue* js = m_codeBlock->constantRegisters[src2].jsValue(m_exec);
+        which2 = 
+            JSImmediate::isImmediate(js) ?
+                (JSImmediate::isNumber(js) ? 'i' :
+                JSImmediate::isBoolean(js) ? 'b' :
+                js->isUndefined() ? 'u' :
+                js->isNull() ? 'n' : '?')
+                :
+            (js->isString() ? 's' :
+            js->isObject() ? 'o' :
+            'k');
+    }
+    if ((which1 != '*') | (which2 != '*'))
+        fprintf(stderr, "Types %c %c\n", which1, which2);
+}
+
+#endif
+
+ALWAYS_INLINE void CTI::emitCall(unsigned opcodeIndex, CTIHelper_j helper)
+{
+#if ENABLE(SAMPLING_TOOL)
+    m_jit.emitMovl_i32m(1, &incall);
+#endif
+    m_calls.append(CallRecord(m_jit.emitCall(), helper, opcodeIndex));
+    emitDebugExceptionCheck();
+#if ENABLE(SAMPLING_TOOL)
+    m_jit.emitMovl_i32m(0, &incall);
+#endif
+}
+
+ALWAYS_INLINE void CTI::emitCall(unsigned opcodeIndex, CTIHelper_p helper)
+{
+#if ENABLE(SAMPLING_TOOL)
+    m_jit.emitMovl_i32m(1, &incall);
+#endif
+    m_calls.append(CallRecord(m_jit.emitCall(), helper, opcodeIndex));
+    emitDebugExceptionCheck();
+#if ENABLE(SAMPLING_TOOL)
+    m_jit.emitMovl_i32m(0, &incall);
+#endif
+}
+
+ALWAYS_INLINE void CTI::emitCall(unsigned opcodeIndex, CTIHelper_b helper)
+{
+#if ENABLE(SAMPLING_TOOL)
+    m_jit.emitMovl_i32m(1, &incall);
+#endif
+    m_calls.append(CallRecord(m_jit.emitCall(), helper, opcodeIndex));
+    emitDebugExceptionCheck();
+#if ENABLE(SAMPLING_TOOL)
+    m_jit.emitMovl_i32m(0, &incall);
+#endif
+}
+
+ALWAYS_INLINE void CTI::emitCall(unsigned opcodeIndex, CTIHelper_v helper)
+{
+#if ENABLE(SAMPLING_TOOL)
+    m_jit.emitMovl_i32m(1, &incall);
+#endif
+    m_calls.append(CallRecord(m_jit.emitCall(), helper, opcodeIndex));
+    emitDebugExceptionCheck();
+#if ENABLE(SAMPLING_TOOL)
+    m_jit.emitMovl_i32m(0, &incall);
+#endif
+}
+
+ALWAYS_INLINE void CTI::emitCall(unsigned opcodeIndex, CTIHelper_s helper)
+{
+#if ENABLE(SAMPLING_TOOL)
+    m_jit.emitMovl_i32m(1, &incall);
+#endif
+    m_calls.append(CallRecord(m_jit.emitCall(), helper, opcodeIndex));
+    emitDebugExceptionCheck();
+#if ENABLE(SAMPLING_TOOL)
+    m_jit.emitMovl_i32m(0, &incall);
+#endif
+}
+
+ALWAYS_INLINE void CTI::emitJumpSlowCaseIfNotImm(MacroAssembler::RegisterID reg, unsigned opcodeIndex)
+{
+    m_jit.emitTestl_i32r(JSImmediate::TagBitTypeInteger, reg);
+    m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJe(), opcodeIndex));
+}
+
+ALWAYS_INLINE void CTI::emitJumpSlowCaseIfNotImms(MacroAssembler::RegisterID reg1, MacroAssembler::RegisterID reg2, unsigned opcodeIndex)
+{
+    m_jit.emitMovl_rr(reg1, MacroAssembler::ecx);
+    m_jit.emitAndl_rr(reg2, MacroAssembler::ecx);
+    emitJumpSlowCaseIfNotImm(MacroAssembler::ecx, opcodeIndex);
+}
+
+ALWAYS_INLINE unsigned CTI::getDeTaggedConstantImmediate(JSValue* imm)
+{
+    ASSERT(JSImmediate::isNumber(imm));
+    return reinterpret_cast<unsigned>(imm) & ~JSImmediate::TagBitTypeInteger;
+}
+
+ALWAYS_INLINE void CTI::emitFastArithDeTagImmediate(MacroAssembler::RegisterID reg)
+{
+    // op_mod relies on this being a sub - setting zf if result is 0.
+    m_jit.emitSubl_i8r(JSImmediate::TagBitTypeInteger, reg);
+}
+
+ALWAYS_INLINE void CTI::emitFastArithReTagImmediate(MacroAssembler::RegisterID reg)
+{
+    m_jit.emitAddl_i8r(JSImmediate::TagBitTypeInteger, reg);
+}
+
+ALWAYS_INLINE void CTI::emitFastArithPotentiallyReTagImmediate(MacroAssembler::RegisterID reg)
+{
+    m_jit.emitOrl_i8r(JSImmediate::TagBitTypeInteger, reg);
+}
+
+ALWAYS_INLINE void CTI::emitFastArithImmToInt(MacroAssembler::RegisterID reg)
+{
+    m_jit.emitSarl_i8r(1, reg);
+}
+
+ALWAYS_INLINE void CTI::emitFastArithIntToImmOrSlowCase(MacroAssembler::RegisterID reg, unsigned opcodeIndex)
+{
+    m_jit.emitAddl_rr(reg, reg);
+    m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), opcodeIndex));
+    emitFastArithReTagImmediate(reg);
+}
+
+ALWAYS_INLINE void CTI::emitFastArithIntToImmNoCheck(MacroAssembler::RegisterID reg)
+{
+    m_jit.emitAddl_rr(reg, reg);
+    emitFastArithReTagImmediate(reg);
+}
+
+CTI::CTI(Machine* machine, ExecState* exec, CodeBlock* codeBlock)
+    : m_jit(machine->jitCodeBuffer())
+    , m_machine(machine)
+    , m_exec(exec)
+    , m_codeBlock(codeBlock)
+    , m_labels(codeBlock ? codeBlock->instructions.size() : 0)
+{
+}
+
+#define CTI_COMPILE_BINARY_OP(name) \
+    case name: { \
+        emitGetPutArg(instruction[i + 2].u.operand, 0, MacroAssembler::ecx); \
+        emitGetPutArg(instruction[i + 3].u.operand, 4, MacroAssembler::ecx); \
+        emitCall(i, Machine::cti_##name); \
+        emitPutResult(instruction[i + 1].u.operand); \
+        i += 4; \
+        break; \
+    }
+
+#if ENABLE(SAMPLING_TOOL)
+OpcodeID what = (OpcodeID)-1;
+#endif
+
+void CTI::compileOpCall(Instruction* instruction, unsigned i, CompileOpCallType type)
+{
+    if (type == OpConstruct) {
+        emitPutArgConstant(reinterpret_cast<unsigned>(instruction + i), 12);
+        emitPutArgConstant(instruction[i + 4].u.operand, 8);
+        emitPutArgConstant(instruction[i + 3].u.operand, 4);
+    } else {
+        emitPutArgConstant(reinterpret_cast<unsigned>(instruction + i), 16);
+        emitPutArgConstant(instruction[i + 5].u.operand, 12);
+        emitPutArgConstant(instruction[i + 4].u.operand, 8);
+        // FIXME: should this be loaded dynamically off m_exec?
+        int thisVal = instruction[i + 3].u.operand;
+        if (thisVal == missingThisObjectMarker()) {
+            emitPutArgConstant((unsigned)(m_exec->globalThisValue()), 4);
+        } else
+            emitGetPutArg(thisVal, 4, MacroAssembler::ecx);
+    }
+
+    MacroAssembler::JmpSrc wasEval;
+    if (type == OpCallEval) {
+        emitGetPutArg(instruction[i + 2].u.operand, 0, MacroAssembler::ecx);
+        emitCall(i, Machine::cti_op_call_eval);
+        m_jit.emitRestoreArgumentReference();
+
+       emitGetCTIParam(CTI_ARGS_r, MacroAssembler::edi); // edi := r
+
+        m_jit.emitCmpl_i32r(reinterpret_cast<unsigned>(JSImmediate::impossibleValue()), MacroAssembler::eax);
+        wasEval = m_jit.emitUnlinkedJne();
+    
+        // this reloads the first arg into ecx (checked just below).
+        emitGetArg(instruction[i + 2].u.operand, MacroAssembler::ecx);
+    } else {
+        // this sets up the first arg, and explicitly leaves the value in ecx (checked just below).
+        emitGetArg(instruction[i + 2].u.operand, MacroAssembler::ecx);
+        emitPutArg(MacroAssembler::ecx, 0);
+    }
+
+    // Fast check for JS function.
+    m_jit.emitTestl_i32r(JSImmediate::TagMask, MacroAssembler::ecx);
+    MacroAssembler::JmpSrc isNotObject = m_jit.emitUnlinkedJne();
+    m_jit.emitCmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsFunctionVptr), MacroAssembler::ecx);
+    MacroAssembler::JmpSrc isJSFunction = m_jit.emitUnlinkedJe();
+    m_jit.link(isNotObject, m_jit.label());
+
+    // This handles host functions
+    emitCall(i, ((type == OpConstruct) ? Machine::cti_op_construct_NotJSConstruct : Machine::cti_op_call_NotJSFunction));
+    emitGetCTIParam(CTI_ARGS_r, MacroAssembler::edi); // edi := r
+    
+    MacroAssembler::JmpSrc wasNotJSFunction = m_jit.emitUnlinkedJmp();
+    m_jit.link(isJSFunction, m_jit.label());
+
+    // This handles JSFunctions
+    emitCall(i, ((type == OpConstruct) ? Machine::cti_op_construct_JSConstruct : Machine::cti_op_call_JSFunction));
+    m_jit.emitCallN_r(MacroAssembler::eax);
+    emitGetCTIParam(CTI_ARGS_r, MacroAssembler::edi); // edi := r
+
+    MacroAssembler::JmpDst end = m_jit.label();
+    m_jit.link(wasNotJSFunction, end);
+    if (type == OpCallEval)
+        m_jit.link(wasEval, end);
+
+    emitPutResult(instruction[i + 1].u.operand);
+}
+
+void CTI::privateCompileMainPass()
+{
+    Instruction* instruction = m_codeBlock->instructions.begin();
+    unsigned instructionCount = m_codeBlock->instructions.size();
+
+    for (unsigned i = 0; i < instructionCount; ) {
+        m_labels[i] = m_jit.label();
+
+#if ENABLE(SAMPLING_TOOL)
+        m_jit.emitMovl_i32m(m_machine->getOpcodeID(instruction[i].u.opcode), &what);
+#endif
+
+        ASSERT_WITH_MESSAGE(m_machine->isOpcode(instruction[i].u.opcode), "privateCompileMainPass gone bad @ %d", i);
+        m_jit.emitRestoreArgumentReference();
+        switch (m_machine->getOpcodeID(instruction[i].u.opcode)) {
+        case op_mov: {
+            unsigned src = instruction[i + 2].u.operand;
+            if (src < m_codeBlock->constantRegisters.size())
+                m_jit.emitMovl_i32r((unsigned)(m_codeBlock->constantRegisters[src].jsValue(m_exec)), MacroAssembler::edx);
+            else
+                emitGetArg(src, MacroAssembler::edx);
+            emitPutResult(instruction[i + 1].u.operand, MacroAssembler::edx);
+            i += 3;
+            break;
+        }
+        case op_add: {
+            unsigned dst = instruction[i + 1].u.operand;
+            unsigned src1 = instruction[i + 2].u.operand;
+            unsigned src2 = instruction[i + 3].u.operand;
+            if (src2 < m_codeBlock->constantRegisters.size()) {
+                JSValue* value = m_codeBlock->constantRegisters[src2].jsValue(m_exec);
+                if (JSImmediate::isNumber(value)) {
+                    emitGetArg(src1, MacroAssembler::eax);
+                    emitJumpSlowCaseIfNotImm(MacroAssembler::eax, i);
+                    m_jit.emitAddl_i32r(getDeTaggedConstantImmediate(value), MacroAssembler::eax);
+                    m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
+                    emitPutResult(dst);
+                    i += 4;
+                    break;
+                }
+            } else if (!(src1 < m_codeBlock->constantRegisters.size())) {
+                emitGetArg(src1, MacroAssembler::eax);
+                emitGetArg(src2, MacroAssembler::edx);
+                emitJumpSlowCaseIfNotImms(MacroAssembler::eax, MacroAssembler::edx, i);
+                emitFastArithDeTagImmediate(MacroAssembler::eax);
+                m_jit.emitAddl_rr(MacroAssembler::edx, MacroAssembler::eax);
+                m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
+                emitPutResult(dst);
+                i += 4;
+                break;
+            }
+            emitGetPutArg(instruction[i + 2].u.operand, 0, MacroAssembler::ecx);
+            emitGetPutArg(instruction[i + 3].u.operand, 4, MacroAssembler::ecx);
+            emitCall(i, Machine::cti_op_add);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_end: {
+            if (m_codeBlock->needsFullScopeChain)
+                emitCall(i, Machine::cti_op_end);
+            emitGetArg(instruction[i + 1].u.operand, MacroAssembler::eax);
+#if ENABLE(SAMPLING_TOOL)
+            m_jit.emitMovl_i32m(-1, &what);
+#endif
+            m_jit.emitPushl_m(-((m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) - RegisterFile::CTIReturnEIP) * sizeof(Register), MacroAssembler::edi);
+            m_jit.emitRet();
+            i += 2;
+            break;
+        }
+        case op_jmp: {
+            unsigned target = instruction[i + 1].u.operand;
+            m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 1 + target));
+            i += 2;
+            break;
+        }
+        case op_pre_inc: {
+            int srcDst = instruction[i + 1].u.operand;
+            emitGetArg(srcDst, MacroAssembler::eax);
+            emitJumpSlowCaseIfNotImm(MacroAssembler::eax, i);
+            m_jit.emitAddl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), MacroAssembler::eax);
+            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
+            emitPutResult(srcDst, MacroAssembler::eax);
+            i += 2;
+            break;
+        }
+        case op_loop: {
+            m_jit.emitSubl_i8r(1, MacroAssembler::esi);
+            MacroAssembler::JmpSrc skipTimeout = m_jit.emitUnlinkedJne();
+            emitCall(i, Machine::cti_timeout_check);
+
+            emitGetCTIParam(CTI_ARGS_exec, MacroAssembler::ecx);
+            m_jit.emitMovl_mr(OBJECT_OFFSET(ExecState, m_globalData) + OBJECT_OFFSET(JSGlobalData, machine), MacroAssembler::ecx, MacroAssembler::ecx);
+            m_jit.emitMovl_mr(OBJECT_OFFSET(Machine, m_ticksUntilNextTimeoutCheck), MacroAssembler::ecx, MacroAssembler::esi);
+            m_jit.link(skipTimeout, m_jit.label());
+
+            unsigned target = instruction[i + 1].u.operand;
+            m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 1 + target));
+            i += 2;
+            break;
+        }
+        case op_loop_if_less: {
+            m_jit.emitSubl_i8r(1, MacroAssembler::esi);
+            MacroAssembler::JmpSrc skipTimeout = m_jit.emitUnlinkedJne();
+            emitCall(i, Machine::cti_timeout_check);
+
+            emitGetCTIParam(CTI_ARGS_exec, MacroAssembler::ecx);
+            m_jit.emitMovl_mr(OBJECT_OFFSET(ExecState, m_globalData) + OBJECT_OFFSET(JSGlobalData, machine), MacroAssembler::ecx, MacroAssembler::ecx);
+            m_jit.emitMovl_mr(OBJECT_OFFSET(Machine, m_ticksUntilNextTimeoutCheck), MacroAssembler::ecx, MacroAssembler::esi);
+            m_jit.link(skipTimeout, m_jit.label());
+
+            unsigned target = instruction[i + 3].u.operand;
+            JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
+            if (src2imm) {
+                emitGetArg(instruction[i + 1].u.operand, MacroAssembler::edx);
+                emitJumpSlowCaseIfNotImm(MacroAssembler::edx, i);
+                m_jit.emitCmpl_i32r((unsigned)src2imm, MacroAssembler::edx);
+                m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJl(), i + 3 + target));
+            } else {
+                emitGetArg(instruction[i + 1].u.operand, MacroAssembler::eax);
+                emitGetArg(instruction[i + 2].u.operand, MacroAssembler::edx);
+                emitJumpSlowCaseIfNotImm(MacroAssembler::eax, i);
+                emitJumpSlowCaseIfNotImm(MacroAssembler::edx, i);
+                m_jit.emitCmpl_rr(MacroAssembler::edx, MacroAssembler::eax);
+                m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJl(), i + 3 + target));
+            }
+            i += 4;
+            break;
+        }
+        case op_new_object: {
+            emitCall(i, Machine::cti_op_new_object);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 2;
+            break;
+        }
+        case op_put_by_id: {
+            Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
+            emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4);
+            emitGetArg(instruction[i + 1].u.operand, MacroAssembler::eax);
+            emitGetArg(instruction[i + 3].u.operand, MacroAssembler::edx);
+            emitPutArg(MacroAssembler::eax, 0); // leave the base in eax
+            emitPutArg(MacroAssembler::edx, 8); // leave the base in edx
+            emitCall(i, Machine::cti_op_put_by_id);
+            i += 6;
+            break;
+        }
+        case op_get_by_id: {
+            Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
+            emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4);
+            emitGetArg(instruction[i + 2].u.operand, MacroAssembler::eax);
+            emitPutArg(MacroAssembler::eax, 0); // leave the base in eax
+            emitCall(i, Machine::cti_op_get_by_id);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 8;
+            break;
+        }
+        case op_instanceof: {
+            emitGetPutArg(instruction[i + 2].u.operand, 0, MacroAssembler::ecx);
+            emitGetPutArg(instruction[i + 3].u.operand, 4, MacroAssembler::ecx);
+            emitCall(i, Machine::cti_op_instanceof);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_del_by_id: {
+            emitGetPutArg(instruction[i + 2].u.operand, 0, MacroAssembler::ecx);
+            Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
+            emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4);
+            emitCall(i, Machine::cti_op_del_by_id);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        CTI_COMPILE_BINARY_OP(op_mul);
+        case op_new_func: {
+            FuncDeclNode* func = (m_codeBlock->functions[instruction[i + 2].u.operand]).get();
+            emitPutArgConstant(reinterpret_cast<unsigned>(func), 0);
+            emitCall(i, Machine::cti_op_new_func);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 3;
+            break;
+        }
+        case op_call: {
+            compileOpCall(instruction, i);
+            i += 6;
+            break;
+        }
+        case op_get_scoped_var: {
+            int skip = instruction[i + 3].u.operand + m_codeBlock->needsFullScopeChain;
+
+            emitGetCTIParam(CTI_ARGS_scopeChain, MacroAssembler::eax);
+            while (skip--)
+                m_jit.emitMovl_mr(OBJECT_OFFSET(ScopeChainNode, next), MacroAssembler::eax, MacroAssembler::eax);
+
+            m_jit.emitMovl_mr(OBJECT_OFFSET(ScopeChainNode, object), MacroAssembler::eax, MacroAssembler::eax);
+            m_jit.emitMovl_mr(JSVariableObject::offsetOf_d(), MacroAssembler::eax, MacroAssembler::eax);
+            m_jit.emitMovl_mr(JSVariableObject::offsetOf_Data_registers(), MacroAssembler::eax, MacroAssembler::eax);
+            m_jit.emitMovl_mr((instruction[i + 2].u.operand) * sizeof(Register), MacroAssembler::eax, MacroAssembler::eax);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_put_scoped_var: {
+            int skip = instruction[i + 2].u.operand + m_codeBlock->needsFullScopeChain;
+
+            emitGetCTIParam(CTI_ARGS_scopeChain, MacroAssembler::edx);
+            emitGetArg(instruction[i + 3].u.operand, MacroAssembler::eax);
+            while (skip--)
+                m_jit.emitMovl_mr(OBJECT_OFFSET(ScopeChainNode, next), MacroAssembler::edx, MacroAssembler::edx);
+
+            m_jit.emitMovl_mr(OBJECT_OFFSET(ScopeChainNode, object), MacroAssembler::edx, MacroAssembler::edx);
+            m_jit.emitMovl_mr(JSVariableObject::offsetOf_d(), MacroAssembler::edx, MacroAssembler::edx);
+            m_jit.emitMovl_mr(JSVariableObject::offsetOf_Data_registers(), MacroAssembler::edx, MacroAssembler::edx);
+            m_jit.emitMovl_rm(MacroAssembler::eax, (instruction[i + 1].u.operand) * sizeof(Register), MacroAssembler::edx);
+            i += 4;
+            break;
+        }
+        case op_ret: {
+            emitGetPutArg(instruction[i + 1].u.operand, 0, MacroAssembler::ecx);
+            emitCall(i, Machine::cti_op_ret);
+
+            m_jit.emitPushl_m(-((m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) - RegisterFile::CTIReturnEIP) * sizeof(Register), MacroAssembler::edi);
+            m_jit.emitRet();
+            i += 2;
+            break;
+        }
+        case op_new_array: {
+            m_jit.emitLeal_mr(sizeof(Register) * instruction[i + 2].u.operand, MacroAssembler::edi, MacroAssembler::edx);
+            emitPutArg(MacroAssembler::edx, 0);
+            emitPutArgConstant(instruction[i + 3].u.operand, 4);
+            emitCall(i, Machine::cti_op_new_array);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_resolve: {
+            Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
+            emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
+            emitCall(i, Machine::cti_op_resolve);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 3;
+            break;
+        }
+        case op_construct: {
+            compileOpCall(instruction, i, OpConstruct);
+            i += 5;
+            break;
+        }
+        case op_get_by_val: {
+            emitGetArg(instruction[i + 2].u.operand, MacroAssembler::eax);
+            emitGetArg(instruction[i + 3].u.operand, MacroAssembler::edx);
+            emitJumpSlowCaseIfNotImm(MacroAssembler::edx, i);
+            emitFastArithImmToInt(MacroAssembler::edx);
+            m_jit.emitTestl_i32r(JSImmediate::TagMask, MacroAssembler::eax);
+            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
+            m_jit.emitCmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsArrayVptr), MacroAssembler::eax);
+            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
+            m_jit.emitCmpl_rm(MacroAssembler::edx, OBJECT_OFFSET(JSArray, m_fastAccessCutoff), MacroAssembler::eax);
+            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJbe(), i));
+
+            m_jit.emitMovl_mr(OBJECT_OFFSET(JSArray, m_storage), MacroAssembler::eax, MacroAssembler::eax);
+            m_jit.emitMovl_mr(OBJECT_OFFSET(ArrayStorage, m_vector[0]), MacroAssembler::eax, MacroAssembler::edx, sizeof(JSValue*), MacroAssembler::eax);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_resolve_func: {
+            Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
+            emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
+            emitCall(i, Machine::cti_op_resolve_func);
+            emitPutResult(instruction[i + 1].u.operand);
+            emitGetCTIParam(CTI_ARGS_2ndResult, MacroAssembler::eax);
+            emitPutResult(instruction[i + 2].u.operand);
+            i += 4;
+            break;
+        }
+        case op_sub: {
+            emitGetArg(instruction[i + 2].u.operand, MacroAssembler::eax);
+            emitGetArg(instruction[i + 3].u.operand, MacroAssembler::edx);
+            emitJumpSlowCaseIfNotImms(MacroAssembler::eax, MacroAssembler::edx, i);
+            m_jit.emitSubl_rr(MacroAssembler::edx, MacroAssembler::eax);
+            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
+            emitFastArithReTagImmediate(MacroAssembler::eax);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_put_by_val: {
+            emitGetArg(instruction[i + 1].u.operand, MacroAssembler::eax);
+            emitGetArg(instruction[i + 2].u.operand, MacroAssembler::edx);
+            emitGetArg(instruction[i + 3].u.operand, MacroAssembler::ecx);
+            emitJumpSlowCaseIfNotImm(MacroAssembler::edx, i);
+            emitFastArithImmToInt(MacroAssembler::edx);
+            m_jit.emitTestl_i32r(JSImmediate::TagMask, MacroAssembler::eax);
+            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
+            m_jit.emitCmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsArrayVptr), MacroAssembler::eax);
+            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
+            m_jit.emitCmpl_rm(MacroAssembler::edx, OBJECT_OFFSET(JSArray, m_fastAccessCutoff), MacroAssembler::eax);
+            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJbe(), i));
+
+            m_jit.emitMovl_mr(OBJECT_OFFSET(JSArray, m_storage), MacroAssembler::eax, MacroAssembler::eax);
+            m_jit.emitMovl_rm(MacroAssembler::ecx, OBJECT_OFFSET(ArrayStorage, m_vector[0]), MacroAssembler::eax, MacroAssembler::edx, sizeof(JSValue*));
+            i += 4;
+            break;
+        }
+        CTI_COMPILE_BINARY_OP(op_lesseq)
+        case op_loop_if_true: {
+            m_jit.emitSubl_i8r(1, MacroAssembler::esi);
+            MacroAssembler::JmpSrc skipTimeout = m_jit.emitUnlinkedJne();
+            emitCall(i, Machine::cti_timeout_check);
+
+            emitGetCTIParam(CTI_ARGS_exec, MacroAssembler::ecx);
+            m_jit.emitMovl_mr(OBJECT_OFFSET(ExecState, m_globalData) + OBJECT_OFFSET(JSGlobalData, machine), MacroAssembler::ecx, MacroAssembler::ecx);
+            m_jit.emitMovl_mr(OBJECT_OFFSET(Machine, m_ticksUntilNextTimeoutCheck), MacroAssembler::ecx, MacroAssembler::esi);
+            m_jit.link(skipTimeout, m_jit.label());
+
+            unsigned target = instruction[i + 2].u.operand;
+            emitGetArg(instruction[i + 1].u.operand, MacroAssembler::eax);
+
+            m_jit.emitCmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::zeroImmediate()), MacroAssembler::eax);
+            MacroAssembler::JmpSrc isZero = m_jit.emitUnlinkedJe();
+            m_jit.emitTestl_i32r(JSImmediate::TagBitTypeInteger, MacroAssembler::eax);
+            m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJne(), i + 2 + target));
+
+            m_jit.emitCmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::trueImmediate()), MacroAssembler::eax);
+            m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target));
+            m_jit.emitCmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::falseImmediate()), MacroAssembler::eax);
+            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
+
+            m_jit.link(isZero, m_jit.label());
+            i += 3;
+            break;
+        };
+        case op_resolve_base: {
+            Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
+            emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
+            emitCall(i, Machine::cti_op_resolve_base);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 3;
+            break;
+        }
+        case op_negate: {
+            emitGetPutArg(instruction[i + 2].u.operand, 0, MacroAssembler::ecx);
+            emitCall(i, Machine::cti_op_negate);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 3;
+            break;
+        }
+        case op_resolve_skip: {
+            Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
+            emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
+            emitPutArgConstant(instruction[i + 3].u.operand + m_codeBlock->needsFullScopeChain, 4);
+            emitCall(i, Machine::cti_op_resolve_skip);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        CTI_COMPILE_BINARY_OP(op_div)
+        case op_pre_dec: {
+            int srcDst = instruction[i + 1].u.operand;
+            emitGetArg(srcDst, MacroAssembler::eax);
+            emitJumpSlowCaseIfNotImm(MacroAssembler::eax, i);
+            m_jit.emitSubl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), MacroAssembler::eax);
+            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
+            emitPutResult(srcDst, MacroAssembler::eax);
+            i += 2;
+            break;
+        }
+        case op_jnless: {
+            unsigned target = instruction[i + 3].u.operand;
+            JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
+            if (src2imm) {
+                emitGetArg(instruction[i + 1].u.operand, MacroAssembler::edx);
+                emitJumpSlowCaseIfNotImm(MacroAssembler::edx, i);
+                m_jit.emitCmpl_i32r((unsigned)src2imm, MacroAssembler::edx);
+                m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJge(), i + 3 + target));
+            } else {
+                emitGetArg(instruction[i + 1].u.operand, MacroAssembler::eax);
+                emitGetArg(instruction[i + 2].u.operand, MacroAssembler::edx);
+                emitJumpSlowCaseIfNotImm(MacroAssembler::eax, i);
+                emitJumpSlowCaseIfNotImm(MacroAssembler::edx, i);
+                m_jit.emitCmpl_rr(MacroAssembler::edx, MacroAssembler::eax);
+                m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJge(), i + 3 + target));
+            }
+            i += 4;
+            break;
+        }
+        case op_not: {
+            emitGetArg(instruction[i + 2].u.operand, MacroAssembler::eax);
+            m_jit.emitXorl_i8r(JSImmediate::FullTagTypeBool, MacroAssembler::eax);
+            m_jit.emitTestl_i32r(JSImmediate::FullTagTypeMask, MacroAssembler::eax); // i8?
+            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
+            m_jit.emitXorl_i8r((JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue), MacroAssembler::eax);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 3;
+            break;
+        }
+        case op_jfalse: {
+            unsigned target = instruction[i + 2].u.operand;
+            emitGetArg(instruction[i + 1].u.operand, MacroAssembler::eax);
+
+            m_jit.emitCmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::zeroImmediate()), MacroAssembler::eax);
+            m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target));
+            m_jit.emitTestl_i32r(JSImmediate::TagBitTypeInteger, MacroAssembler::eax);
+            MacroAssembler::JmpSrc isNonZero = m_jit.emitUnlinkedJne();
+
+            m_jit.emitCmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::falseImmediate()), MacroAssembler::eax);
+            m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target));
+            m_jit.emitCmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::trueImmediate()), MacroAssembler::eax);
+            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
+
+            m_jit.link(isNonZero, m_jit.label());
+            i += 3;
+            break;
+        };
+        case op_post_inc: {
+            int srcDst = instruction[i + 2].u.operand;
+            emitGetArg(srcDst, MacroAssembler::eax);
+            m_jit.emitMovl_rr(MacroAssembler::eax, MacroAssembler::edx);
+            emitJumpSlowCaseIfNotImm(MacroAssembler::eax, i);
+            m_jit.emitAddl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), MacroAssembler::edx);
+            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
+            emitPutResult(srcDst, MacroAssembler::edx);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 3;
+            break;
+        }
+        case op_unexpected_load: {
+            JSValue* v = m_codeBlock->unexpectedConstants[instruction[i + 2].u.operand];
+            m_jit.emitMovl_i32r((unsigned)v, MacroAssembler::eax);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 3;
+            break;
+        }
+        case op_jsr: {
+            int retAddrDst = instruction[i + 1].u.operand;
+            int target = instruction[i + 2].u.operand;
+            m_jit.emitMovl_i32m(0, sizeof(Register) * retAddrDst, MacroAssembler::edi);
+            MacroAssembler::JmpDst addrPosition = m_jit.label();
+            m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 2 + target));
+            MacroAssembler::JmpDst sretTarget = m_jit.label();
+            m_jsrSites.append(JSRInfo(addrPosition, sretTarget));
+            i += 3;
+            break;
+        }
+        case op_sret: {
+            m_jit.emitJmpN_m(sizeof(Register) * instruction[i + 1].u.operand, MacroAssembler::edi);
+            i += 2;
+            break;
+        }
+        CTI_COMPILE_BINARY_OP(op_eq)
+        case op_lshift: {
+            emitGetArg(instruction[i + 2].u.operand, MacroAssembler::eax);
+            emitGetArg(instruction[i + 3].u.operand, MacroAssembler::ecx);
+            emitJumpSlowCaseIfNotImm(MacroAssembler::eax, i);
+            emitJumpSlowCaseIfNotImm(MacroAssembler::ecx, i);
+            emitFastArithImmToInt(MacroAssembler::eax);
+            emitFastArithImmToInt(MacroAssembler::ecx);
+            m_jit.emitShll_CLr(MacroAssembler::eax);
+            emitFastArithIntToImmOrSlowCase(MacroAssembler::eax, i);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_bitand: {
+            unsigned src1 = instruction[i + 2].u.operand;
+            unsigned src2 = instruction[i + 3].u.operand;
+            unsigned dst = instruction[i + 1].u.operand;
+            if (JSValue* value = getConstantImmediateNumericArg(src1)) {
+                emitGetArg(src2, MacroAssembler::eax);
+                emitJumpSlowCaseIfNotImm(MacroAssembler::eax, i);
+                m_jit.emitAndl_i32r((unsigned)value, MacroAssembler::eax); // FIXME: make it more obvious this is relying on the format of JSImmediate
+                emitPutResult(dst);
+            } else if (JSValue* value = getConstantImmediateNumericArg(src2)) {
+                emitGetArg(src1, MacroAssembler::eax);
+                emitJumpSlowCaseIfNotImm(MacroAssembler::eax, i);
+                m_jit.emitAndl_i32r((unsigned)value, MacroAssembler::eax);
+                emitPutResult(dst);
+            } else {
+                emitGetArg(src1, MacroAssembler::eax);
+                emitGetArg(src2, MacroAssembler::edx);
+                m_jit.emitAndl_rr(MacroAssembler::edx, MacroAssembler::eax);
+                emitJumpSlowCaseIfNotImm(MacroAssembler::eax, i);
+                emitPutResult(dst);
+            }
+            i += 4;
+            break;
+        }
+        case op_rshift: {
+            emitGetArg(instruction[i + 2].u.operand, MacroAssembler::eax);
+            emitGetArg(instruction[i + 3].u.operand, MacroAssembler::ecx);
+            emitJumpSlowCaseIfNotImm(MacroAssembler::eax, i);
+            emitJumpSlowCaseIfNotImm(MacroAssembler::ecx, i);
+            emitFastArithImmToInt(MacroAssembler::ecx);
+            m_jit.emitSarl_CLr(MacroAssembler::eax);
+            emitFastArithPotentiallyReTagImmediate(MacroAssembler::eax);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_bitnot: {
+            emitGetArg(instruction[i + 2].u.operand, MacroAssembler::eax);
+            emitJumpSlowCaseIfNotImm(MacroAssembler::eax, i);
+            m_jit.emitXorl_i8r(~JSImmediate::TagBitTypeInteger, MacroAssembler::eax);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 3;
+            break;
+        }
+        case op_resolve_with_base: {
+            Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
+            emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
+            emitCall(i, Machine::cti_op_resolve_with_base);
+            emitPutResult(instruction[i + 1].u.operand);
+            emitGetCTIParam(CTI_ARGS_2ndResult, MacroAssembler::eax);
+            emitPutResult(instruction[i + 2].u.operand);
+            i += 4;
+            break;
+        }
+        case op_new_func_exp: {
+            FuncExprNode* func = (m_codeBlock->functionExpressions[instruction[i + 2].u.operand]).get();
+            emitPutArgConstant(reinterpret_cast<unsigned>(func), 0);
+            emitCall(i, Machine::cti_op_new_func_exp);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 3;
+            break;
+        }
+        case op_mod: {
+            emitGetArg(instruction[i + 2].u.operand, MacroAssembler::eax);
+            emitGetArg(instruction[i + 3].u.operand, MacroAssembler::ecx);
+            emitJumpSlowCaseIfNotImm(MacroAssembler::eax, i);
+            emitJumpSlowCaseIfNotImm(MacroAssembler::ecx, i);
+            emitFastArithDeTagImmediate(MacroAssembler::eax);
+            emitFastArithDeTagImmediate(MacroAssembler::ecx);
+            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJe(), i)); // This is checking if the last detag resulted in a value 0.
+            m_jit.emitCdq();
+            m_jit.emitIdivl_r(MacroAssembler::ecx);
+            emitFastArithReTagImmediate(MacroAssembler::edx);
+            m_jit.emitMovl_rr(MacroAssembler::edx, MacroAssembler::eax);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_jtrue: {
+            unsigned target = instruction[i + 2].u.operand;
+            emitGetArg(instruction[i + 1].u.operand, MacroAssembler::eax);
+
+            m_jit.emitCmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::zeroImmediate()), MacroAssembler::eax);
+            MacroAssembler::JmpSrc isZero = m_jit.emitUnlinkedJe();
+            m_jit.emitTestl_i32r(JSImmediate::TagBitTypeInteger, MacroAssembler::eax);
+            m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJne(), i + 2 + target));
+
+            m_jit.emitCmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::trueImmediate()), MacroAssembler::eax);
+            m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target));
+            m_jit.emitCmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::falseImmediate()), MacroAssembler::eax);
+            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
+
+            m_jit.link(isZero, m_jit.label());
+            i += 3;
+            break;
+        }
+        CTI_COMPILE_BINARY_OP(op_less)
+        CTI_COMPILE_BINARY_OP(op_neq)
+        case op_post_dec: {
+            int srcDst = instruction[i + 2].u.operand;
+            emitGetArg(srcDst, MacroAssembler::eax);
+            m_jit.emitMovl_rr(MacroAssembler::eax, MacroAssembler::edx);
+            emitJumpSlowCaseIfNotImm(MacroAssembler::eax, i);
+            m_jit.emitSubl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), MacroAssembler::edx);
+            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
+            emitPutResult(srcDst, MacroAssembler::edx);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 3;
+            break;
+        }
+        CTI_COMPILE_BINARY_OP(op_urshift)
+        case op_bitxor: {
+            emitGetArg(instruction[i + 2].u.operand, MacroAssembler::eax);
+            emitGetArg(instruction[i + 3].u.operand, MacroAssembler::edx);
+            emitJumpSlowCaseIfNotImms(MacroAssembler::eax, MacroAssembler::edx, i);
+            m_jit.emitXorl_rr(MacroAssembler::edx, MacroAssembler::eax);
+            emitFastArithReTagImmediate(MacroAssembler::eax);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_new_regexp: {
+            RegExp* regExp = m_codeBlock->regexps[instruction[i + 2].u.operand].get();
+            emitPutArgConstant(reinterpret_cast<unsigned>(regExp), 0);
+            emitCall(i, Machine::cti_op_new_regexp);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 3;
+            break;
+        }
+        case op_bitor: {
+            emitGetArg(instruction[i + 2].u.operand, MacroAssembler::eax);
+            emitGetArg(instruction[i + 3].u.operand, MacroAssembler::edx);
+            emitJumpSlowCaseIfNotImms(MacroAssembler::eax, MacroAssembler::edx, i);
+            m_jit.emitOrl_rr(MacroAssembler::edx, MacroAssembler::eax);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_call_eval: {
+            compileOpCall(instruction, i, OpCallEval);
+            i += 6;
+            break;
+        }
+        case op_throw: {
+            emitGetPutArg(instruction[i + 1].u.operand, 0, MacroAssembler::ecx);
+            emitCall(i, Machine::cti_op_throw);
+            m_jit.emitAddl_i8r(0x24, MacroAssembler::esp);
+            m_jit.emitPopl_r(MacroAssembler::edi);
+            m_jit.emitPopl_r(MacroAssembler::esi);
+            m_jit.emitRet();
+            i += 2;
+            break;
+        }
+        case op_get_pnames: {
+            emitGetPutArg(instruction[i + 2].u.operand, 0, MacroAssembler::ecx);
+            emitCall(i, Machine::cti_op_get_pnames);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 3;
+            break;
+        }
+        case op_next_pname: {
+            emitGetPutArg(instruction[i + 2].u.operand, 0, MacroAssembler::ecx);
+            unsigned target = instruction[i + 3].u.operand;
+            emitCall(i, Machine::cti_op_next_pname);
+            m_jit.emitTestl_rr(MacroAssembler::eax, MacroAssembler::eax);
+            MacroAssembler::JmpSrc endOfIter = m_jit.emitUnlinkedJe();
+            emitPutResult(instruction[i + 1].u.operand);
+            m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 3 + target));
+            m_jit.link(endOfIter, m_jit.label());
+            i += 4;
+            break;
+        }
+        case op_push_scope: {
+            emitGetPutArg(instruction[i + 1].u.operand, 0, MacroAssembler::ecx);
+            emitCall(i, Machine::cti_op_push_scope);
+            i += 2;
+            break;
+        }
+        case op_pop_scope: {
+            emitCall(i, Machine::cti_op_pop_scope);
+            i += 1;
+            break;
+        }
+        case op_typeof: {
+            emitGetPutArg(instruction[i + 2].u.operand, 0, MacroAssembler::ecx);
+            emitCall(i, Machine::cti_op_typeof);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 3;
+            break;
+        }
+        CTI_COMPILE_BINARY_OP(op_stricteq)
+        CTI_COMPILE_BINARY_OP(op_nstricteq)
+        case op_to_jsnumber: {
+            emitGetPutArg(instruction[i + 2].u.operand, 0, MacroAssembler::ecx);
+            emitCall(i, Machine::cti_op_to_jsnumber);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 3;
+            break;
+        }
+        case op_in: {
+            emitGetPutArg(instruction[i + 2].u.operand, 0, MacroAssembler::ecx);
+            emitGetPutArg(instruction[i + 3].u.operand, 4, MacroAssembler::ecx);
+            emitCall(i, Machine::cti_op_in);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_push_new_scope: {
+            Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
+            emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
+            emitGetPutArg(instruction[i + 3].u.operand, 4, MacroAssembler::ecx);
+            emitCall(i, Machine::cti_op_push_new_scope);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_catch: {
+            emitGetCTIParam(CTI_ARGS_r, MacroAssembler::edi); // edi := r
+            emitGetCTIParam(CTI_ARGS_exec, MacroAssembler::ecx);
+            m_jit.emitMovl_mr(OBJECT_OFFSET(ExecState, m_exception), MacroAssembler::ecx, MacroAssembler::eax);
+            m_jit.emitMovl_i32m(0, OBJECT_OFFSET(ExecState, m_exception), MacroAssembler::ecx);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 2;
+            break;
+        }
+        case op_jmp_scopes: {
+            unsigned count = instruction[i + 1].u.operand;
+            emitPutArgConstant(count, 0);
+            emitCall(i, Machine::cti_op_jmp_scopes);
+            unsigned target = instruction[i + 2].u.operand;
+            m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 2 + target));
+            i += 3;
+            break;
+        }
+        case op_put_by_index: {
+            emitGetPutArg(instruction[i + 1].u.operand, 0, MacroAssembler::ecx);
+            emitPutArgConstant(instruction[i + 2].u.operand, 4);
+            emitGetPutArg(instruction[i + 3].u.operand, 8, MacroAssembler::ecx);
+            emitCall(i, Machine::cti_op_put_by_index);
+            i += 4;
+            break;
+        }
+        case op_switch_imm: {
+            unsigned tableIndex = instruction[i + 1].u.operand;
+            unsigned defaultOffset = instruction[i + 2].u.operand;
+            unsigned scrutinee = instruction[i + 3].u.operand;
+
+            // create jump table for switch destinations, track this switch statement.
+            SimpleJumpTable* jumpTable = &m_codeBlock->immediateSwitchJumpTables[tableIndex];
+            m_switches.append(SwitchRecord(jumpTable, i, defaultOffset, SwitchRecord::Immediate));
+            jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
+
+            emitGetPutArg(scrutinee, 0, MacroAssembler::ecx);
+            emitPutArgConstant(tableIndex, 4);
+            emitCall(i, Machine::cti_op_switch_imm);
+            m_jit.emitJmpN_r(MacroAssembler::eax);
+            i += 4;
+            break;
+        }
+        case op_switch_char: {
+            unsigned tableIndex = instruction[i + 1].u.operand;
+            unsigned defaultOffset = instruction[i + 2].u.operand;
+            unsigned scrutinee = instruction[i + 3].u.operand;
+
+            // create jump table for switch destinations, track this switch statement.
+            SimpleJumpTable* jumpTable = &m_codeBlock->characterSwitchJumpTables[tableIndex];
+            m_switches.append(SwitchRecord(jumpTable, i, defaultOffset, SwitchRecord::Character));
+            jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
+
+            emitGetPutArg(scrutinee, 0, MacroAssembler::ecx);
+            emitPutArgConstant(tableIndex, 4);
+            emitCall(i, Machine::cti_op_switch_char);
+            m_jit.emitJmpN_r(MacroAssembler::eax);
+            i += 4;
+            break;
+        }
+        case op_switch_string: {
+            unsigned tableIndex = instruction[i + 1].u.operand;
+            unsigned defaultOffset = instruction[i + 2].u.operand;
+            unsigned scrutinee = instruction[i + 3].u.operand;
+
+            // create jump table for switch destinations, track this switch statement.
+            StringJumpTable* jumpTable = &m_codeBlock->stringSwitchJumpTables[tableIndex];
+            m_switches.append(SwitchRecord(jumpTable, i, defaultOffset));
+
+            emitGetPutArg(scrutinee, 0, MacroAssembler::ecx);
+            emitPutArgConstant(tableIndex, 4);
+            emitCall(i, Machine::cti_op_switch_string);
+            m_jit.emitJmpN_r(MacroAssembler::eax);
+            i += 4;
+            break;
+        }
+        case op_del_by_val: {
+            emitGetPutArg(instruction[i + 2].u.operand, 0, MacroAssembler::ecx);
+            emitGetPutArg(instruction[i + 3].u.operand, 4, MacroAssembler::ecx);
+            emitCall(i, Machine::cti_op_del_by_val);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_put_getter: {
+            emitGetPutArg(instruction[i + 1].u.operand, 0, MacroAssembler::ecx);
+            Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
+            emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4);
+            emitGetPutArg(instruction[i + 3].u.operand, 8, MacroAssembler::ecx);
+            emitCall(i, Machine::cti_op_put_getter);
+            i += 4;
+            break;
+        }
+        case op_put_setter: {
+            emitGetPutArg(instruction[i + 1].u.operand, 0, MacroAssembler::ecx);
+            Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
+            emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4);
+            emitGetPutArg(instruction[i + 3].u.operand, 8, MacroAssembler::ecx);
+            emitCall(i, Machine::cti_op_put_setter);
+            i += 4;
+            break;
+        }
+        case op_new_error: {
+            JSValue* message = m_codeBlock->unexpectedConstants[instruction[i + 3].u.operand];
+            emitPutArgConstant(instruction[i + 2].u.operand, 0);
+            emitPutArgConstant(reinterpret_cast<unsigned>(message), 4);
+            emitPutArgConstant(m_codeBlock->lineNumberForVPC(&instruction[i]), 8);
+            emitCall(i, Machine::cti_op_new_error);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_debug: {
+            emitPutArgConstant(instruction[i + 1].u.operand, 0);
+            emitPutArgConstant(instruction[i + 2].u.operand, 4);
+            emitPutArgConstant(instruction[i + 3].u.operand, 8);
+            emitCall(i, Machine::cti_op_debug);
+            i += 4;
+            break;
+        }
+        case op_eq_null: {
+            emitGetPutArg(instruction[i + 2].u.operand, 0, MacroAssembler::ecx);
+            emitCall(i, Machine::cti_op_eq_null);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 3;
+            break;
+        }
+        case op_neq_null: {
+            emitGetPutArg(instruction[i + 2].u.operand, 0, MacroAssembler::ecx);
+            emitCall(i, Machine::cti_op_neq_null);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 3;
+            break;
+        }
+        case op_get_array_length:
+        case op_get_by_id_chain:
+        case op_get_by_id_generic:
+        case op_get_by_id_proto:
+        case op_get_by_id_self:
+        case op_get_string_length:
+        case op_put_by_id_generic:
+        case op_put_by_id_replace:
+            ASSERT_NOT_REACHED();
+        }
+    }
+}
+
+
+void CTI::privateCompileLinkPass()
+{
+    unsigned jmpTableCount = m_jmpTable.size();
+    for (unsigned i = 0; i < jmpTableCount; ++i)
+        m_jit.link(m_jmpTable[i].from, m_labels[m_jmpTable[i].to]);
+    m_jmpTable.clear();
+}
+
+void CTI::privateCompileSlowCases()
+{
+    Instruction* instruction = m_codeBlock->instructions.begin();
+    for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end(); ++iter) {
+        int i = iter->to;
+       m_jit.emitRestoreArgumentReference();
+        switch (m_machine->getOpcodeID(instruction[i].u.opcode)) {
+        case op_add: {
+            unsigned dst = instruction[i + 1].u.operand;
+            unsigned src2 = instruction[i + 3].u.operand;
+            if (src2 < m_codeBlock->constantRegisters.size()) {
+                JSValue* value = m_codeBlock->constantRegisters[src2].jsValue(m_exec);
+                if (JSImmediate::isNumber(value)) {
+                    MacroAssembler::JmpSrc notImm = iter->from;
+                    m_jit.link((++iter)->from, m_jit.label());
+                    m_jit.emitSubl_i32r(getDeTaggedConstantImmediate(value), MacroAssembler::eax);
+                    m_jit.link(notImm, m_jit.label());
+                    emitPutArg(MacroAssembler::eax, 0);
+                    emitGetPutArg(src2, 4, MacroAssembler::ecx);
+                    emitCall(i, Machine::cti_op_add);
+                    emitPutResult(dst);
+                    i += 4;
+                    break;
+                }
+            }
+
+            ASSERT(!(static_cast<unsigned>(instruction[i + 2].u.operand) < m_codeBlock->constantRegisters.size()));
+
+            MacroAssembler::JmpSrc notImm = iter->from;
+            m_jit.link((++iter)->from, m_jit.label());
+            m_jit.emitSubl_rr(MacroAssembler::edx, MacroAssembler::eax);
+            emitFastArithReTagImmediate(MacroAssembler::eax);
+            m_jit.link(notImm, m_jit.label());
+            emitPutArg(MacroAssembler::eax, 0);
+            emitPutArg(MacroAssembler::edx, 4);
+            emitCall(i, Machine::cti_op_add);
+            emitPutResult(dst);
+            i += 4;
+            break;
+        }
+        case op_get_by_val: {
+            MacroAssembler::JmpSrc notImm = iter->from;
+            m_jit.link((++iter)->from, m_jit.label());
+            m_jit.link((++iter)->from, m_jit.label());
+            m_jit.link((++iter)->from, m_jit.label());
+            emitFastArithIntToImmNoCheck(MacroAssembler::edx);
+            m_jit.link(notImm, m_jit.label());
+            emitPutArg(MacroAssembler::eax, 0);
+            emitPutArg(MacroAssembler::edx, 4);
+            emitCall(i, Machine::cti_op_get_by_val);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_sub: {
+            MacroAssembler::JmpSrc notImm = iter->from;
+            m_jit.link((++iter)->from, m_jit.label());
+            m_jit.emitAddl_rr(MacroAssembler::edx, MacroAssembler::eax);
+            m_jit.link(notImm, m_jit.label());
+            emitPutArg(MacroAssembler::eax, 0);
+            emitPutArg(MacroAssembler::edx, 4);
+            emitCall(i, Machine::cti_op_sub);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_rshift: {
+            m_jit.link(iter->from, m_jit.label());
+            m_jit.link((++iter)->from, m_jit.label());
+            emitPutArg(MacroAssembler::eax, 0);
+            emitPutArg(MacroAssembler::ecx, 4);
+            emitCall(i, Machine::cti_op_rshift);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_lshift: {
+            MacroAssembler::JmpSrc notImm1 = iter->from;
+            MacroAssembler::JmpSrc notImm2 = (++iter)->from;
+            m_jit.link((++iter)->from, m_jit.label());
+            emitGetArg(instruction[i + 2].u.operand, MacroAssembler::eax);
+            emitGetArg(instruction[i + 3].u.operand, MacroAssembler::ecx);
+            m_jit.link(notImm1, m_jit.label());
+            m_jit.link(notImm2, m_jit.label());
+            emitPutArg(MacroAssembler::eax, 0);
+            emitPutArg(MacroAssembler::ecx, 4);
+            emitCall(i, Machine::cti_op_lshift);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_loop_if_less: {
+            unsigned target = instruction[i + 3].u.operand;
+            JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
+            if (src2imm) {
+                m_jit.link(iter->from, m_jit.label());
+                emitPutArg(MacroAssembler::edx, 0);
+                emitGetPutArg(instruction[i + 2].u.operand, 4, MacroAssembler::ecx);
+                emitCall(i, Machine::cti_op_loop_if_less);
+                m_jit.emitTestl_rr(MacroAssembler::eax, MacroAssembler::eax);
+                m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 3 + target]);
+            } else {
+                m_jit.link(iter->from, m_jit.label());
+                m_jit.link((++iter)->from, m_jit.label());
+                emitPutArg(MacroAssembler::eax, 0);
+                emitPutArg(MacroAssembler::edx, 4);
+                emitCall(i, Machine::cti_op_loop_if_less);
+                m_jit.emitTestl_rr(MacroAssembler::eax, MacroAssembler::eax);
+                m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 3 + target]);
+            }
+            i += 4;
+            break;
+        }
+        case op_pre_inc: {
+            unsigned srcDst = instruction[i + 1].u.operand;
+            MacroAssembler::JmpSrc notImm = iter->from;
+            m_jit.link((++iter)->from, m_jit.label());
+            m_jit.emitSubl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), MacroAssembler::eax);
+            m_jit.link(notImm, m_jit.label());
+            emitPutArg(MacroAssembler::eax, 0);
+            emitCall(i, Machine::cti_op_pre_inc);
+            emitPutResult(srcDst);
+            i += 2;
+            break;
+        }
+        case op_put_by_val: {
+            MacroAssembler::JmpSrc notImm = iter->from;
+            m_jit.link((++iter)->from, m_jit.label());
+            m_jit.link((++iter)->from, m_jit.label());
+            m_jit.link((++iter)->from, m_jit.label());
+            emitFastArithIntToImmNoCheck(MacroAssembler::edx);
+            m_jit.link(notImm, m_jit.label());
+            emitPutArg(MacroAssembler::eax, 0);
+            emitPutArg(MacroAssembler::edx, 4);
+            emitPutArg(MacroAssembler::ecx, 8);
+            emitCall(i, Machine::cti_op_put_by_val);
+            i += 4;
+            break;
+        }
+        case op_loop_if_true: {
+            m_jit.link(iter->from, m_jit.label());
+            emitPutArg(MacroAssembler::eax, 0);
+            emitCall(i, Machine::cti_op_jtrue);
+            m_jit.emitTestl_rr(MacroAssembler::eax, MacroAssembler::eax);
+            unsigned target = instruction[i + 2].u.operand;
+            m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 2 + target]);
+            i += 3;
+            break;
+        }
+        case op_pre_dec: {
+            unsigned srcDst = instruction[i + 1].u.operand;
+            MacroAssembler::JmpSrc notImm = iter->from;
+            m_jit.link((++iter)->from, m_jit.label());
+            m_jit.emitAddl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), MacroAssembler::eax);
+            m_jit.link(notImm, m_jit.label());
+            emitPutArg(MacroAssembler::eax, 0);
+            emitCall(i, Machine::cti_op_pre_dec);
+            emitPutResult(srcDst);
+            i += 2;
+            break;
+        }
+        case op_jnless: {
+            unsigned target = instruction[i + 3].u.operand;
+            JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
+            if (src2imm) {
+                m_jit.link(iter->from, m_jit.label());
+                emitPutArg(MacroAssembler::edx, 0);
+                emitGetPutArg(instruction[i + 2].u.operand, 4, MacroAssembler::ecx);
+                emitCall(i, Machine::cti_op_jless);
+                m_jit.emitTestl_rr(MacroAssembler::eax, MacroAssembler::eax);
+                m_jit.link(m_jit.emitUnlinkedJe(), m_labels[i + 3 + target]);
+            } else {
+                m_jit.link(iter->from, m_jit.label());
+                m_jit.link((++iter)->from, m_jit.label());
+                emitPutArg(MacroAssembler::eax, 0);
+                emitPutArg(MacroAssembler::edx, 4);
+                emitCall(i, Machine::cti_op_jless);
+                m_jit.emitTestl_rr(MacroAssembler::eax, MacroAssembler::eax);
+                m_jit.link(m_jit.emitUnlinkedJe(), m_labels[i + 3 + target]);
+            }
+            i += 4;
+            break;
+        }
+        case op_not: {
+            m_jit.link(iter->from, m_jit.label());
+            m_jit.emitXorl_i8r(JSImmediate::FullTagTypeBool, MacroAssembler::eax);
+            emitPutArg(MacroAssembler::eax, 0);
+            emitCall(i, Machine::cti_op_not);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 3;
+            break;
+        }
+        case op_jfalse: {
+            m_jit.link(iter->from, m_jit.label());
+            emitPutArg(MacroAssembler::eax, 0);
+            emitCall(i, Machine::cti_op_jtrue);
+            m_jit.emitTestl_rr(MacroAssembler::eax, MacroAssembler::eax);
+            unsigned target = instruction[i + 2].u.operand;
+            m_jit.link(m_jit.emitUnlinkedJe(), m_labels[i + 2 + target]); // inverted!
+            i += 3;
+            break;
+        }
+        case op_post_inc: {
+            unsigned srcDst = instruction[i + 2].u.operand;
+            m_jit.link(iter->from, m_jit.label());
+            m_jit.link((++iter)->from, m_jit.label());
+            emitPutArg(MacroAssembler::eax, 0);
+            emitCall(i, Machine::cti_op_post_inc);
+            emitPutResult(instruction[i + 1].u.operand);
+            emitGetCTIParam(CTI_ARGS_2ndResult, MacroAssembler::eax);
+            emitPutResult(srcDst);
+            i += 3;
+            break;
+        }
+        case op_bitnot: {
+            m_jit.link(iter->from, m_jit.label());
+            emitPutArg(MacroAssembler::eax, 0);
+            emitCall(i, Machine::cti_op_bitnot);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 3;
+            break;
+        }
+        case op_bitand: {
+            unsigned src1 = instruction[i + 2].u.operand;
+            unsigned src2 = instruction[i + 3].u.operand;
+            unsigned dst = instruction[i + 1].u.operand;
+            if (getConstantImmediateNumericArg(src1)) {
+                m_jit.link(iter->from, m_jit.label());
+                emitGetPutArg(src1, 0, MacroAssembler::ecx);
+                emitPutArg(MacroAssembler::eax, 4);
+                emitCall(i, Machine::cti_op_bitand);
+                emitPutResult(dst);
+            } else if (getConstantImmediateNumericArg(src2)) {
+                m_jit.link(iter->from, m_jit.label());
+                emitPutArg(MacroAssembler::eax, 0);
+                emitGetPutArg(src2, 4, MacroAssembler::ecx);
+                emitCall(i, Machine::cti_op_bitand);
+                emitPutResult(dst);
+            } else {
+                m_jit.link(iter->from, m_jit.label());
+                emitGetPutArg(src1, 0, MacroAssembler::ecx);
+                emitPutArg(MacroAssembler::edx, 4);
+                emitCall(i, Machine::cti_op_bitand);
+                emitPutResult(dst);
+            }
+            i += 4;
+            break;
+        }
+        case op_jtrue: {
+            m_jit.link(iter->from, m_jit.label());
+            emitPutArg(MacroAssembler::eax, 0);
+            emitCall(i, Machine::cti_op_jtrue);
+            m_jit.emitTestl_rr(MacroAssembler::eax, MacroAssembler::eax);
+            unsigned target = instruction[i + 2].u.operand;
+            m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 2 + target]);
+            i += 3;
+            break;
+        }
+        case op_post_dec: {
+            unsigned srcDst = instruction[i + 2].u.operand;
+            m_jit.link(iter->from, m_jit.label());
+            m_jit.link((++iter)->from, m_jit.label());
+            emitPutArg(MacroAssembler::eax, 0);
+            emitCall(i, Machine::cti_op_post_dec);
+            emitPutResult(instruction[i + 1].u.operand);
+            emitGetCTIParam(CTI_ARGS_2ndResult, MacroAssembler::eax);
+            emitPutResult(srcDst);
+            i += 3;
+            break;
+        }
+        case op_bitxor: {
+            m_jit.link(iter->from, m_jit.label());
+            emitPutArg(MacroAssembler::eax, 0);
+            emitPutArg(MacroAssembler::edx, 4);
+            emitCall(i, Machine::cti_op_bitxor);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_bitor: {
+            m_jit.link(iter->from, m_jit.label());
+            emitPutArg(MacroAssembler::eax, 0);
+            emitPutArg(MacroAssembler::edx, 4);
+            emitCall(i, Machine::cti_op_bitor);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        case op_mod: {
+            MacroAssembler::JmpSrc notImm1 = iter->from;
+            MacroAssembler::JmpSrc notImm2 = (++iter)->from;
+            m_jit.link((++iter)->from, m_jit.label());
+            emitFastArithReTagImmediate(MacroAssembler::eax);
+            emitFastArithReTagImmediate(MacroAssembler::ecx);
+            m_jit.link(notImm1, m_jit.label());
+            m_jit.link(notImm2, m_jit.label());
+            emitPutArg(MacroAssembler::eax, 0);
+            emitPutArg(MacroAssembler::ecx, 4);
+            emitCall(i, Machine::cti_op_mod);
+            emitPutResult(instruction[i + 1].u.operand);
+            i += 4;
+            break;
+        }
+        default:
+            ASSERT_NOT_REACHED();
+            break;
+        }
+
+        m_jit.link(m_jit.emitUnlinkedJmp(), m_labels[i]);
+    }
+}
+
+void CTI::privateCompile()
+{
+    // Could use a emitPopl_m, but would need to offset the following instruction if so.
+    m_jit.emitPopl_r(MacroAssembler::ecx);
+    emitGetCTIParam(CTI_ARGS_r, MacroAssembler::edi); // edi := r
+    emitPutToCallFrameHeader(MacroAssembler::ecx, RegisterFile::CTIReturnEIP);
+
+    privateCompileMainPass();
+    privateCompileLinkPass();
+    privateCompileSlowCases();
+
+    ASSERT(m_jmpTable.isEmpty());
+
+    void* code = m_jit.copy();
+    ASSERT(code);
+
+    // Translate vPC offsets into addresses in JIT generated code, for switch tables.
+    for (unsigned i = 0; i < m_switches.size(); ++i) {
+        SwitchRecord record = m_switches[i];
+        unsigned opcodeIndex = record.m_opcodeIndex;
+
+        if (record.m_type != SwitchRecord::String) {
+            ASSERT(record.m_type == SwitchRecord::Immediate || record.m_type == SwitchRecord::Character); 
+            ASSERT(record.m_jumpTable.m_simpleJumpTable->branchOffsets.size() == record.m_jumpTable.m_simpleJumpTable->ctiOffsets.size());
+
+            record.m_jumpTable.m_simpleJumpTable->ctiDefault = m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + record.m_defaultOffset]);
+
+            for (unsigned j = 0; j < record.m_jumpTable.m_simpleJumpTable->branchOffsets.size(); ++j) {
+                unsigned offset = record.m_jumpTable.m_simpleJumpTable->branchOffsets[j];
+                record.m_jumpTable.m_simpleJumpTable->ctiOffsets[j] = offset ? m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + offset]) : record.m_jumpTable.m_simpleJumpTable->ctiDefault;
+            }
+        } else {
+            ASSERT(record.m_type == SwitchRecord::String);
+
+            record.m_jumpTable.m_stringJumpTable->ctiDefault = m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + record.m_defaultOffset]);
+
+            StringJumpTable::StringOffsetTable::iterator end = record.m_jumpTable.m_stringJumpTable->offsetTable.end();            
+            for (StringJumpTable::StringOffsetTable::iterator it = record.m_jumpTable.m_stringJumpTable->offsetTable.begin(); it != end; ++it) {
+                unsigned offset = it->second.branchOffset;
+                it->second.ctiOffset = offset ? m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + offset]) : record.m_jumpTable.m_stringJumpTable->ctiDefault;
+            }
+        }
+    }
+
+    for (Vector<HandlerInfo>::iterator iter = m_codeBlock->exceptionHandlers.begin(); iter != m_codeBlock->exceptionHandlers.end(); ++iter)
+         iter->nativeCode = m_jit.getRelocatedAddress(code, m_labels[iter->target]);
+
+    // FIXME: There doesn't seem to be a way to hint to a hashmap that it should make a certain capacity available;
+    // could be faster if we could do something like this:
+    // m_codeBlock->ctiReturnAddressVPCMap.grow(m_calls.size());
+    for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
+        MacroAssembler::link(code, iter->from, iter->to);
+        m_codeBlock->ctiReturnAddressVPCMap.add(m_jit.getRelocatedAddress(code, iter->from), iter->opcodeIndex);
+    }
+
+    // Link absolute addresses for jsr
+    for (Vector<JSRInfo>::iterator iter = m_jsrSites.begin(); iter != m_jsrSites.end(); ++iter)
+        MacroAssembler::linkAbsoluteAddress(code, iter->addrPosition, iter->target);
+
+    m_codeBlock->ctiCode = code;
+}
+
+void* CTI::privateCompileGetByIdSelf(StructureID* structureID, size_t cachedOffset)
+{
+    // Check eax is an object of the right StructureID.
+    m_jit.emitTestl_i32r(JSImmediate::TagMask, MacroAssembler::eax);
+    MacroAssembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
+    m_jit.emitCmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), MacroAssembler::eax);
+    MacroAssembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
+
+    // Checks out okay! - getDirectOffset
+    m_jit.emitMovl_mr(OBJECT_OFFSET(JSObject, m_propertyMap) + OBJECT_OFFSET(PropertyMap, m_u.table), MacroAssembler::eax, MacroAssembler::eax);
+    m_jit.emitMovl_mr(OBJECT_OFFSET(PropertyMapHashTable, entryIndices[0]) + (cachedOffset * sizeof(JSValue*)), MacroAssembler::eax, MacroAssembler::eax);
+    m_jit.emitRet();
+
+    void* code = m_jit.copy();
+    ASSERT(code);
+
+    MacroAssembler::link(code, failureCases1, (void*)Machine::cti_op_get_by_id_fail);
+    MacroAssembler::link(code, failureCases2, (void*)Machine::cti_op_get_by_id_fail);
+    
+    m_codeBlock->structureIDAccessStubs.append(code);
+    
+    return code;
+}
+
+void* CTI::privateCompileGetByIdProto(StructureID* structureID, StructureID* prototypeStructureID, size_t cachedOffset)
+{
+    // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a StructureID that is
+    // referencing the prototype object - let's speculatively load it's table nice and early!)
+    JSObject* protoObject = static_cast<JSObject*>(structureID->prototype());
+    PropertyMapHashTable** protoTableAddress = &(protoObject->m_propertyMap.m_u.table);
+    m_jit.emitMovl_mr((void*)protoTableAddress, MacroAssembler::edx);
+
+    // check eax is an object of the right StructureID.
+    m_jit.emitTestl_i32r(JSImmediate::TagMask, MacroAssembler::eax);
+    MacroAssembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
+    m_jit.emitCmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), MacroAssembler::eax);
+    MacroAssembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
+
+    // Check the prototype object's StructureID had not changed.
+    StructureID** protoStructureIDAddress = &(protoObject->m_structureID);
+    m_jit.emitCmpl_i32m(reinterpret_cast<uint32_t>(prototypeStructureID), (void*)protoStructureIDAddress);
+    MacroAssembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJne();
+
+    // Checks out okay! - getDirectOffset
+
+    m_jit.emitMovl_mr(OBJECT_OFFSET(PropertyMapHashTable, entryIndices[0]) + (cachedOffset * sizeof(JSValue*)), MacroAssembler::edx, MacroAssembler::eax);
+
+    m_jit.emitRet();
+
+    void* code = m_jit.copy();
+    ASSERT(code);
+
+    MacroAssembler::link(code, failureCases1, (void*)Machine::cti_op_get_by_id_fail);
+    MacroAssembler::link(code, failureCases2, (void*)Machine::cti_op_get_by_id_fail);
+    MacroAssembler::link(code, failureCases3, (void*)Machine::cti_op_get_by_id_fail);
+
+    m_codeBlock->structureIDAccessStubs.append(code);
+
+    return code;
+}
+
+void* CTI::privateCompileGetByIdChain(StructureID* structureID, StructureIDChain* chain, size_t count, size_t cachedOffset)
+{
+    ASSERT(count);
+    
+    Vector<MacroAssembler::JmpSrc> bucketsOfFail;
+
+    // Check eax is an object of the right StructureID.
+    m_jit.emitTestl_i32r(JSImmediate::TagMask, MacroAssembler::eax);
+    bucketsOfFail.append(m_jit.emitUnlinkedJne());
+    m_jit.emitCmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), MacroAssembler::eax);
+    bucketsOfFail.append(m_jit.emitUnlinkedJne());
+
+    StructureID* currStructureID = structureID;
+    RefPtr<StructureID>* chainEntries = chain->head();
+    JSCell* protoObject = 0;
+    for (unsigned i = 0; i<count; ++i) {
+        protoObject = static_cast<JSCell*>(currStructureID->prototype());
+        currStructureID = chainEntries[i].get();
+
+        // Check the prototype object's StructureID had not changed.
+        StructureID** protoStructureIDAddress = &(protoObject->m_structureID);
+        m_jit.emitCmpl_i32m(reinterpret_cast<uint32_t>(currStructureID), (void*)protoStructureIDAddress);
+        bucketsOfFail.append(m_jit.emitUnlinkedJne());
+    }
+    ASSERT(protoObject);
+    PropertyMapHashTable** protoTableAddress = &(reinterpret_cast<JSObject*>(protoObject)->m_propertyMap.m_u.table);
+    m_jit.emitMovl_mr((void*)protoTableAddress, MacroAssembler::edx);
+    m_jit.emitMovl_mr(OBJECT_OFFSET(PropertyMapHashTable, entryIndices[0]) + (cachedOffset * sizeof(JSValue*)), MacroAssembler::edx, MacroAssembler::eax);
+    m_jit.emitRet();
+
+    bucketsOfFail.append(m_jit.emitUnlinkedJmp());
+
+    void* code = m_jit.copy();
+    ASSERT(code);
+
+    for (unsigned i = 0; i < bucketsOfFail.size(); ++i)
+        MacroAssembler::link(code, bucketsOfFail[i], (void*)Machine::cti_op_get_by_id_fail);
+    m_codeBlock->structureIDAccessStubs.append(code);
+    return code;
+}
+
+void* CTI::privateCompilePutByIdReplace(StructureID* structureID, size_t cachedOffset)
+{
+    // check eax is an object of the right StructureID.
+    m_jit.emitTestl_i32r(JSImmediate::TagMask, MacroAssembler::eax);
+    MacroAssembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
+    m_jit.emitCmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), MacroAssembler::eax);
+    MacroAssembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
+
+    // checks out okay! - putDirectOffset
+    m_jit.emitMovl_mr(OBJECT_OFFSET(JSObject, m_propertyMap) + OBJECT_OFFSET(PropertyMap, m_u.table), MacroAssembler::eax, MacroAssembler::eax);
+    m_jit.emitMovl_rm(MacroAssembler::edx, OBJECT_OFFSET(PropertyMapHashTable, entryIndices[0]) + (cachedOffset * sizeof(JSValue*)), MacroAssembler::eax);
+    m_jit.emitRet();
+
+    void* code = m_jit.copy();
+    ASSERT(code);
+    
+    MacroAssembler::link(code, failureCases1, (void*)Machine::cti_op_put_by_id_fail);
+    MacroAssembler::link(code, failureCases2, (void*)Machine::cti_op_put_by_id_fail);
+
+    m_codeBlock->structureIDAccessStubs.append(code);
+    
+    return code;
+}
+
+void* CTI::privateArrayLengthTrampoline()
+{
+    // Check eax is an array
+    m_jit.emitTestl_i32r(JSImmediate::TagMask, MacroAssembler::eax);
+    MacroAssembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
+    m_jit.emitCmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsArrayVptr), MacroAssembler::eax);
+    MacroAssembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
+
+    // Checks out okay! - get the length from the storage
+    m_jit.emitMovl_mr(OBJECT_OFFSET(JSArray, m_storage), MacroAssembler::eax, MacroAssembler::eax);
+    m_jit.emitMovl_mr(OBJECT_OFFSET(ArrayStorage, m_length), MacroAssembler::eax, MacroAssembler::eax);
+
+    m_jit.emitAddl_rr(MacroAssembler::eax, MacroAssembler::eax);
+    MacroAssembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJo();
+    m_jit.emitAddl_i8r(1, MacroAssembler::eax);
+    
+    m_jit.emitRet();
+
+    void* code = m_jit.copy();
+    ASSERT(code);
+
+    MacroAssembler::link(code, failureCases1, (void*)Machine::cti_op_get_by_id_fail);
+    MacroAssembler::link(code, failureCases2, (void*)Machine::cti_op_get_by_id_fail);
+    MacroAssembler::link(code, failureCases3, (void*)Machine::cti_op_get_by_id_fail);
+    
+    return code;
+}
+
+void* CTI::privateStringLengthTrampoline()
+{
+    // Check eax is a string
+    m_jit.emitTestl_i32r(JSImmediate::TagMask, MacroAssembler::eax);
+    MacroAssembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
+    m_jit.emitCmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsStringVptr), MacroAssembler::eax);
+    MacroAssembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
+
+    // Checks out okay! - get the length from the Ustring.
+    m_jit.emitMovl_mr(OBJECT_OFFSET(JSString, m_value) + OBJECT_OFFSET(UString, m_rep), MacroAssembler::eax, MacroAssembler::eax);
+    m_jit.emitMovl_mr(OBJECT_OFFSET(UString::Rep, len), MacroAssembler::eax, MacroAssembler::eax);
+
+    m_jit.emitAddl_rr(MacroAssembler::eax, MacroAssembler::eax);
+    MacroAssembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJo();
+    m_jit.emitAddl_i8r(1, MacroAssembler::eax);
+    
+    m_jit.emitRet();
+
+    void* code = m_jit.copy();
+    ASSERT(code);
+
+    MacroAssembler::link(code, failureCases1, (void*)Machine::cti_op_get_by_id_fail);
+    MacroAssembler::link(code, failureCases2, (void*)Machine::cti_op_get_by_id_fail);
+    MacroAssembler::link(code, failureCases3, (void*)Machine::cti_op_get_by_id_fail);
+
+    return code;
+}
+
+void* CTI::compileRegExp(ExecState* exec, const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, bool ignoreCase, bool multiline)
+{
+    // TODO: better error messages
+    if (pattern.size() > MaxPatternSize) {
+        *error_ptr = "regular expression too large";
+        return 0;
+    }
+
+    MacroAssembler jit(exec->machine()->jitCodeBuffer());
+    WRECParser parser(pattern, ignoreCase, multiline, jit);
+    
+    jit.emitConvertToFastCall();
+    // (0) Setup:
+    //     Preserve regs & initialize OUTPUT_REG.
+    jit.emitPushl_r(WRECGenerator::OUTPUT_REG);
+    jit.emitPushl_r(WRECGenerator::CURR_VAL_REG);
+    // push pos onto the stack, both to preserve and as a parameter available to parseDisjunction
+    jit.emitPushl_r(WRECGenerator::CURR_POS_REG);
+    // load output pointer
+    jit.emitMovl_mr(16
+#if COMPILER(MSVC)
+                    + 3 * sizeof(void*)
+#endif
+                    , MacroAssembler::esp, WRECGenerator::OUTPUT_REG);
+    
+    // restart point on match fail.
+    WRECGenerator::JmpDst nextLabel = jit.label();
+
+    // (1) Parse Disjunction:
+    
+    //     Parsing the disjunction should fully consume the pattern.
+    JmpSrcVector failures;
+    parser.parseDisjunction(failures);
+    if (parser.isEndOfPattern()) {
+        parser.m_err = WRECParser::Error_malformedPattern;
+    }
+    if (parser.m_err) {
+        // TODO: better error messages
+        *error_ptr = "TODO: better error messages";
+        return 0;
+    }
+
+    // (2) Success:
+    //     Set return value & pop registers from the stack.
+
+    jit.emitTestl_rr(WRECGenerator::OUTPUT_REG, WRECGenerator::OUTPUT_REG);
+    WRECGenerator::JmpSrc noOutput = jit.emitUnlinkedJe();
+
+    jit.emitMovl_rm(WRECGenerator::CURR_POS_REG, 4, WRECGenerator::OUTPUT_REG);
+    jit.emitPopl_r(MacroAssembler::eax);
+    jit.emitMovl_rm(MacroAssembler::eax, WRECGenerator::OUTPUT_REG);
+    jit.emitPopl_r(WRECGenerator::CURR_VAL_REG);
+    jit.emitPopl_r(WRECGenerator::OUTPUT_REG);
+    jit.emitRet();
+    
+    jit.link(noOutput, jit.label());
+    
+    jit.emitPopl_r(MacroAssembler::eax);
+    jit.emitMovl_rm(MacroAssembler::eax, WRECGenerator::OUTPUT_REG);
+    jit.emitPopl_r(WRECGenerator::CURR_VAL_REG);
+    jit.emitPopl_r(WRECGenerator::OUTPUT_REG);
+    jit.emitRet();
+
+    // (3) Failure:
+    //     All fails link to here.  Progress the start point & if it is within scope, loop.
+    //     Otherwise, return fail value.
+    WRECGenerator::JmpDst here = jit.label();
+    for (unsigned i = 0; i < failures.size(); ++i)
+        jit.link(failures[i], here);
+    failures.clear();
+
+    jit.emitMovl_mr(MacroAssembler::esp, WRECGenerator::CURR_POS_REG);
+    jit.emitAddl_i8r(1, WRECGenerator::CURR_POS_REG);
+    jit.emitMovl_rm(WRECGenerator::CURR_POS_REG, MacroAssembler::esp);
+    jit.emitCmpl_rr(WRECGenerator::LENGTH_REG, WRECGenerator::CURR_POS_REG);
+    jit.link(jit.emitUnlinkedJle(), nextLabel);
+
+    jit.emitAddl_i8r(4, MacroAssembler::esp);
+
+    jit.emitMovl_i32r(-1, MacroAssembler::eax);
+    jit.emitPopl_r(WRECGenerator::CURR_VAL_REG);
+    jit.emitPopl_r(WRECGenerator::OUTPUT_REG);
+    jit.emitRet();
+
+    *numSubpatterns_ptr = parser.m_numSubpatterns;
+
+    void* code = jit.copy();
+    ASSERT(code);
+    return code;
+}
+
+} // namespace KJS
+
+#endif // ENABLE(CTI)
diff --git a/JavaScriptCore/VM/CTI.h b/JavaScriptCore/VM/CTI.h
new file mode 100644 (file)
index 0000000..009751c
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef CTI_h
+#define CTI_h
+
+#if ENABLE(CTI)
+
+#include "Opcode.h"
+#include "Opcode.h"
+#include "RegisterFile.h"
+#include "RegisterFile.h"
+#include <masm/MacroAssembler.h>
+#include <profiler/Profiler.h>
+#include <wtf/AlwaysInline.h>
+#include <wtf/Vector.h>
+
+#if COMPILER(MSVC)
+#define CTI_ARGS void** args
+#define ARGS (args)
+#else
+#define CTI_ARGS void* args
+#define ARGS (&args)
+#endif
+
+#define CTI_ARGS_2ndResult 0x08
+
+#define CTI_ARGS_code 0x0C
+#define CTI_ARGS_exec 0x0D
+#define CTI_ARGS_registerFile 0x0E
+#define CTI_ARGS_r 0x0F
+#define CTI_ARGS_scopeChain 0x10
+#define CTI_ARGS_codeBlock 0x11
+#define CTI_ARGS_exception 0x12
+#define CTI_ARGS_profilerReference 0x13
+#define ARG_exec ((ExecState*)(ARGS)[CTI_ARGS_exec])
+#define ARG_registerFile ((RegisterFile*)(ARGS)[CTI_ARGS_registerFile])
+#define ARG_r ((Register*)(ARGS)[CTI_ARGS_r])
+#define ARG_scopeChain ((ScopeChainNode*)(ARGS)[CTI_ARGS_scopeChain])
+#define ARG_codeBlock ((CodeBlock*)(ARGS)[CTI_ARGS_codeBlock])
+#define ARG_exception ((JSValue**)(ARGS)[CTI_ARGS_exception])
+#define ARG_profilerReference ((Profiler**)(ARGS)[CTI_ARGS_profilerReference])
+
+#define ARG_setScopeChain(newScopeChain) (*(volatile ScopeChainNode**)&(ARGS)[CTI_ARGS_scopeChain] = newScopeChain)
+#define ARG_setCodeBlock(newCodeBlock) (*(volatile CodeBlock**)&(ARGS)[CTI_ARGS_codeBlock] = newCodeBlock)
+#define ARG_setR(newR) (*(volatile Register**)&(ARGS)[CTI_ARGS_r] = newR)
+#define ARG_set2ndResult(new2ndResult) (*(volatile JSValue**)&(ARGS)[CTI_ARGS_2ndResult] = new2ndResult)
+
+#define ARG_src1 ((JSValue*)((ARGS)[1]))
+#define ARG_src2 ((JSValue*)((ARGS)[2]))
+#define ARG_src3 ((JSValue*)((ARGS)[3]))
+#define ARG_src4 ((JSValue*)((ARGS)[4]))
+#define ARG_id1 ((Identifier*)((ARGS)[1]))
+#define ARG_id2 ((Identifier*)((ARGS)[2]))
+#define ARG_id3 ((Identifier*)((ARGS)[3]))
+#define ARG_id4 ((Identifier*)((ARGS)[4]))
+#define ARG_int1 ((int)((ARGS)[1]))
+#define ARG_int2 ((int)((ARGS)[2]))
+#define ARG_int3 ((int)((ARGS)[3]))
+#define ARG_int4 ((int)((ARGS)[4]))
+#define ARG_func1 ((FuncDeclNode*)((ARGS)[1]))
+#define ARG_funcexp1 ((FuncExprNode*)((ARGS)[1]))
+#define ARG_registers1 ((Register*)((ARGS)[1]))
+#define ARG_regexp1 ((RegExp*)((ARGS)[1]))
+#define ARG_pni1 ((JSPropertyNameIterator*)((ARGS)[1]))
+#define ARG_instr4 ((Instruction*)((ARGS)[4]))
+#define ARG_instr5 ((Instruction*)((ARGS)[5]))
+
+#define CTI_RETURN_ADDRESS ((ARGS)[-1])
+
+namespace KJS {
+
+    class CodeBlock;
+    class ExecState;
+    class JSPropertyNameIterator;
+    class JSValue;
+    class Machine;
+    class Register;
+    class RegisterFile;
+    class ScopeChainNode;
+    class SimpleJumpTable;
+    class StringJumpTable;
+    class StructureIDChain;
+    struct Instruction;
+
+    typedef JSValue* (*CTIHelper_j)(CTI_ARGS);
+    typedef JSPropertyNameIterator* (*CTIHelper_p)(CTI_ARGS);
+    typedef void (*CTIHelper_v)(CTI_ARGS);
+    typedef void* (*CTIHelper_s)(CTI_ARGS);
+    typedef int (*CTIHelper_b)(CTI_ARGS);
+
+    extern OpcodeID what;
+
+    struct CallRecord {
+        MacroAssembler::JmpSrc from;
+        void* to;
+        unsigned opcodeIndex;
+
+        CallRecord()
+        {
+        }
+
+        CallRecord(MacroAssembler::JmpSrc f, CTIHelper_j t, unsigned i)
+            : from(f)
+            , to((void*)t)
+            , opcodeIndex(i)
+        {
+        }
+
+        CallRecord(MacroAssembler::JmpSrc f, CTIHelper_p t, unsigned i)
+            : from(f)
+            , to((void*)t)
+            , opcodeIndex(i)
+        {
+        }
+        
+        CallRecord(MacroAssembler::JmpSrc f, CTIHelper_v t, unsigned i)
+            : from(f)
+            , to((void*)t)
+            , opcodeIndex(i)
+        {
+        }
+        
+        CallRecord(MacroAssembler::JmpSrc f, CTIHelper_s t, unsigned i)
+            : from(f)
+            , to((void*)t)
+            , opcodeIndex(i)
+        {
+        }
+        
+        CallRecord(MacroAssembler::JmpSrc f, CTIHelper_b t, unsigned i)
+            : from(f)
+            , to((void*)t)
+            , opcodeIndex(i)
+        {
+        }
+    };
+
+    struct JmpTable {
+        MacroAssembler::JmpSrc from;
+        unsigned to;
+        
+        JmpTable(MacroAssembler::JmpSrc f, unsigned t)
+            : from(f)
+            , to(t)
+        {
+        }
+    };
+
+    struct SlowCaseEntry {
+        MacroAssembler::JmpSrc from;
+        unsigned to;
+        unsigned hint;
+        
+        SlowCaseEntry(MacroAssembler::JmpSrc f, unsigned t, unsigned h = 0)
+            : from(f)
+            , to(t)
+            , hint(h)
+        {
+        }
+    };
+
+    struct SwitchRecord {
+        enum Type {
+            Immediate,
+            Character,
+            String
+        };
+
+        Type m_type;
+
+        union {
+            SimpleJumpTable* m_simpleJumpTable;
+            StringJumpTable* m_stringJumpTable;
+        } m_jumpTable;
+
+        unsigned m_opcodeIndex;
+        unsigned m_defaultOffset;
+
+        SwitchRecord(SimpleJumpTable* jumpTable, unsigned opcodeIndex, unsigned defaultOffset, Type type)
+            : m_type(type)
+            , m_opcodeIndex(opcodeIndex)
+            , m_defaultOffset(defaultOffset)
+        {
+            m_jumpTable.m_simpleJumpTable = jumpTable;
+        }
+
+        SwitchRecord(StringJumpTable* jumpTable, unsigned opcodeIndex, unsigned defaultOffset)
+            : m_type(String)
+            , m_opcodeIndex(opcodeIndex)
+            , m_defaultOffset(defaultOffset)
+        {
+            m_jumpTable.m_stringJumpTable = jumpTable;
+        }
+    };
+
+    extern "C" {
+        JSValue* ctiTrampoline(void* code, ExecState* exec, RegisterFile* registerFile, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue** exception, Profiler**);
+        void ctiVMThrowTrampoline();
+    };
+
+    void ctiSetReturnAddress(void** where, void* what);
+    void ctiRepatchCallByReturnAddress(void* where, void* what);
+
+    class CTI {
+    public:
+        static void compile(Machine* machine, ExecState* exec, CodeBlock* codeBlock)
+        {
+            CTI cti(machine, exec, codeBlock);
+            cti.privateCompile();
+        }
+
+        static void* compileRegExp(ExecState* exec, const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, bool ignoreCase = false, bool multiline = false);
+
+        static void* compileGetByIdSelf(Machine* machine, ExecState* exec, CodeBlock* codeBlock, StructureID* structureID, size_t cachedOffset)
+        {
+            CTI cti(machine, exec, codeBlock);
+            return cti.privateCompileGetByIdSelf(structureID, cachedOffset);
+        }
+
+        static void* compileGetByIdProto(Machine* machine, ExecState* exec, CodeBlock* codeBlock, StructureID* structureID, StructureID* prototypeStructureID, size_t cachedOffset)
+        {
+            CTI cti(machine, exec, codeBlock);
+            return cti.privateCompileGetByIdProto(structureID, prototypeStructureID, cachedOffset);
+        }
+
+        static void* compileGetByIdChain(Machine* machine, ExecState* exec, CodeBlock* codeBlock, StructureID* structureID, StructureIDChain* chain, size_t count, size_t cachedOffset)
+        {
+            CTI cti(machine, exec, codeBlock);
+            return cti.privateCompileGetByIdChain(structureID, chain, count, cachedOffset);
+        }
+
+        static void* compilePutByIdReplace(Machine* machine, ExecState* exec, CodeBlock* codeBlock, StructureID* structureID, size_t cachedOffset)
+        {
+            CTI cti(machine, exec, codeBlock);
+            return cti.privateCompilePutByIdReplace(structureID, cachedOffset);
+        }
+
+        static void* compileArrayLengthTrampoline(Machine* machine, ExecState* exec, CodeBlock* codeBlock)
+        {
+            CTI cti(machine, exec, codeBlock);
+            return cti.privateArrayLengthTrampoline();
+        }
+
+        static void* compileStringLengthTrampoline(Machine* machine, ExecState* exec, CodeBlock* codeBlock)
+        {
+            CTI cti(machine, exec, codeBlock);
+            return cti.privateStringLengthTrampoline();
+        }
+
+        inline static JSValue* execute(void* code, ExecState* exec, RegisterFile* registerFile, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue** exception)
+        {
+            JSValue* value = ctiTrampoline(code, exec, registerFile, r, scopeChain, codeBlock, exception, Profiler::enabledProfilerReference());
+#if ENABLE(SAMPLING_TOOL)
+            what = static_cast<OpcodeID>(-1);
+#endif
+            return value;
+        }
+
+    private:
+        CTI(Machine*, ExecState*, CodeBlock*);
+        void privateCompileMainPass();
+        void privateCompileLinkPass();
+        void privateCompileSlowCases();
+        void privateCompile();
+        void* privateCompileGetByIdSelf(StructureID*, size_t cachedOffset);
+        void* privateCompileGetByIdProto(StructureID*, StructureID* prototypeStructureID, size_t cachedOffset);
+        void* privateCompileGetByIdChain(StructureID*, StructureIDChain*, size_t count, size_t cachedOffset);
+        void* privateCompilePutByIdReplace(StructureID*, size_t cachedOffset);
+        void* privateArrayLengthTrampoline();
+        void* privateStringLengthTrampoline();
+
+        enum CompileOpCallType { OpCallNormal, OpCallEval, OpConstruct };
+        void compileOpCall(Instruction* instruction, unsigned i, CompileOpCallType type = OpCallNormal);
+
+        void emitGetArg(unsigned src, MacroAssembler::RegisterID dst);
+        void emitGetPutArg(unsigned src, unsigned offset, MacroAssembler::RegisterID scratch);
+        void emitPutArg(MacroAssembler::RegisterID src, unsigned offset);
+        void emitPutArgConstant(unsigned value, unsigned offset);
+        void emitPutResult(unsigned dst, MacroAssembler::RegisterID from = MacroAssembler::eax);
+
+        void emitPutCTIParam(MacroAssembler::RegisterID from, unsigned name);
+        void emitGetCTIParam(unsigned name, MacroAssembler::RegisterID to);
+
+        void emitPutToCallFrameHeader(MacroAssembler::RegisterID from, RegisterFile::CallFrameHeaderEntry entry);
+        void emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, MacroAssembler::RegisterID to);
+
+        JSValue* getConstantImmediateNumericArg(unsigned src);
+        unsigned getDeTaggedConstantImmediate(JSValue* imm);
+
+        void emitJumpSlowCaseIfNotImm(MacroAssembler::RegisterID, unsigned opcodeIndex);
+        void emitJumpSlowCaseIfNotImms(MacroAssembler::RegisterID, MacroAssembler::RegisterID, unsigned opcodeIndex);
+
+        void emitFastArithDeTagImmediate(MacroAssembler::RegisterID);
+        void emitFastArithReTagImmediate(MacroAssembler::RegisterID);
+        void emitFastArithPotentiallyReTagImmediate(MacroAssembler::RegisterID);
+        void emitFastArithImmToInt(MacroAssembler::RegisterID);
+        void emitFastArithIntToImmOrSlowCase(MacroAssembler::RegisterID, unsigned opcodeIndex);
+        void emitFastArithIntToImmNoCheck(MacroAssembler::RegisterID);
+
+        void emitDebugExceptionCheck();
+
+        void emitCall(unsigned opcodeIndex, CTIHelper_j);
+        void emitCall(unsigned opcodeIndex, CTIHelper_p);
+        void emitCall(unsigned opcodeIndex, CTIHelper_b);
+        void emitCall(unsigned opcodeIndex, CTIHelper_v);
+        void emitCall(unsigned opcodeIndex, CTIHelper_s);
+
+#ifndef NDEBUG
+        void printOpcodeOperandTypes(unsigned src1, unsigned src2);
+#endif
+
+        MacroAssembler m_jit;
+        Machine* m_machine;
+        ExecState* m_exec;
+        CodeBlock* m_codeBlock;
+
+        Vector<CallRecord> m_calls;
+        Vector<MacroAssembler::JmpDst> m_labels;
+        Vector<JmpTable> m_jmpTable;
+
+        struct JSRInfo {
+            MacroAssembler::JmpDst addrPosition;
+            MacroAssembler::JmpDst target;
+
+            JSRInfo(const MacroAssembler::JmpDst& storeLocation, const MacroAssembler::JmpDst& targetLocation)
+                : addrPosition(storeLocation)
+                , target(targetLocation)
+            {
+            }
+        };
+
+        Vector<JSRInfo> m_jsrSites;
+        Vector<SlowCaseEntry> m_slowCases;
+        Vector<SwitchRecord> m_switches;
+
+        // This limit comes from the limit set in PCRE
+        static const int MaxPatternSize = (1 << 16);
+
+    };
+}
+
+#endif // ENABLE(CTI)
+
+#endif // CTI_h
index cb1b40b..ad8b062 100644 (file)
@@ -273,11 +273,11 @@ void CodeBlock::dump(ExecState* exec) const
         printf("\nStructureIDs:\n");
         size_t i = 0;
         do {
-            printStructureIDs(&instructions[structureIDInstructions[i]]);
-            ++i;
+             printStructureIDs(&instructions[structureIDInstructions[i]]);
+             ++i;
         } while (i < structureIDInstructions.size());
     }
-
     if (exceptionHandlers.size()) {
         printf("\nException Handlers:\n");
         unsigned i = 0;
@@ -317,7 +317,7 @@ void CodeBlock::dump(ExecState* exec) const
                 ASSERT(!((i + characterSwitchJumpTables[i].min) & ~0xFFFF));
                 UChar ch = static_cast<UChar>(entry + characterSwitchJumpTables[i].min);
                 printf("\t\t\"%s\" => %04d\n", UString(&ch, 1).ascii(), *iter);
-            }
+        }
             printf("      }\n");
             ++i;
         } while (i < characterSwitchJumpTables.size());
@@ -328,9 +328,9 @@ void CodeBlock::dump(ExecState* exec) const
         unsigned i = 0;
         do {
             printf("  %1d = {\n", i);
-            StringJumpTable::const_iterator end = stringSwitchJumpTables[i].end();
-            for (StringJumpTable::const_iterator iter = stringSwitchJumpTables[i].begin(); iter != end; ++iter)
-                printf("\t\t\"%s\" => %04d\n", UString(iter->first).ascii(), iter->second);
+            StringJumpTable::StringOffsetTable::const_iterator end = stringSwitchJumpTables[i].offsetTable.end();
+            for (StringJumpTable::StringOffsetTable::const_iterator iter = stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter)
+                printf("\t\t\"%s\" => %04d\n", UString(iter->first).ascii(), iter->second.branchOffset);
             printf("      }\n");
             ++i;
         } while (i < stringSwitchJumpTables.size());
@@ -820,6 +820,15 @@ CodeBlock::~CodeBlock()
     size_t size = structureIDInstructions.size();
     for (size_t i = 0; i < size; ++i)
         derefStructureIDs(&instructions[structureIDInstructions[i]]);
+
+    size = structureIDAccessStubs.size();
+    for (size_t i = 0; i < size; ++i)
+        fastFree(structureIDAccessStubs[i]);
+
+#if ENABLE(CTI)
+    if (ctiCode)
+        fastFree(ctiCode);
+#endif
 }
 
 void CodeBlock::derefStructureIDs(Instruction* vPC) const
@@ -912,6 +921,20 @@ bool CodeBlock::getHandlerForVPC(const Instruction* vPC, Instruction*& target, i
     return false;
 }
 
+void* CodeBlock::nativeExceptionCodeForHandlerVPC(const Instruction* handlerVPC)
+{
+    Vector<HandlerInfo>::iterator ptr = exceptionHandlers.begin(); 
+    Vector<HandlerInfo>::iterator end = exceptionHandlers.end();
+    
+    for (; ptr != end; ++ptr) {
+        Instruction*target = instructions.begin() + ptr->target;
+        if (handlerVPC == target)
+            return ptr->nativeCode;
+    }
+
+    return 0;
+}
+
 int CodeBlock::lineNumberForVPC(const Instruction* vPC)
 {
     ASSERT(lineInfo.size());    
index df29930..6952e79 100644 (file)
@@ -49,11 +49,13 @@ namespace KJS {
         uint32_t end;
         uint32_t target;
         uint32_t scopeDepth;
+        void* nativeCode;
     };
 
     struct ExpressionRangeInfo {
-        enum { MaxOffset = (1 << 7) - 1, 
-               MaxDivot = (1 << 25) - 1
+        enum {
+            MaxOffset = (1 << 7) - 1, 
+            MaxDivot = (1 << 25) - 1
         };
         uint32_t instructionOffset : 25;
         uint32_t divotPoint : 25;
@@ -66,21 +68,74 @@ namespace KJS {
         int32_t lineNumber;
     };
 
-    typedef HashMap<RefPtr<UString::Rep>, int32_t> StringJumpTable;
+    struct OffsetLocation {
+        int32_t branchOffset;
+#if ENABLE(CTI)
+        void* ctiOffset;
+#endif
+    };
+
+    struct StringJumpTable {
+        typedef HashMap<RefPtr<UString::Rep>, OffsetLocation> StringOffsetTable;
+        StringOffsetTable offsetTable;
+#if ENABLE(CTI)
+        void* ctiDefault; // FIXME: it should not be necessary to store this.
+#endif
+
+        inline int32_t offsetForValue(UString::Rep* value, int32_t defaultOffset)
+        {
+            StringOffsetTable::const_iterator end = offsetTable.end();
+            StringOffsetTable::const_iterator loc = offsetTable.find(value);
+            if (loc == end)
+                return defaultOffset;
+            return loc->second.branchOffset;
+        }
+
+#if ENABLE(CTI)
+        inline void* ctiForValue(UString::Rep* value)
+        {
+            StringOffsetTable::const_iterator end = offsetTable.end();
+            StringOffsetTable::const_iterator loc = offsetTable.find(value);
+            if (loc == end)
+                return ctiDefault;
+            return loc->second.ctiOffset;
+        }
+#endif
+    };
+
     struct SimpleJumpTable {
+        // FIXME: The two Vectors can be combind into one Vector<OffsetLocation>
         Vector<int32_t> branchOffsets;
         int32_t min;
+#if ENABLE(CTI)
+        Vector<void*> ctiOffsets;
+        void* ctiDefault;
+#endif
+
         int32_t offsetForValue(int32_t value, int32_t defaultOffset);
-        void add(int32_t key, int32_t offset) {
+        void add(int32_t key, int32_t offset)
+        {
             if (!branchOffsets[key])
                 branchOffsets[key] = offset;
         }
+
+#if ENABLE(CTI)
+        inline void* ctiForValue(int32_t value)
+        {
+            if (value >= min && static_cast<uint32_t>(value - min) < ctiOffsets.size())
+                return ctiOffsets[value - min];
+            return ctiDefault;
+        }
+#endif
     };
 
     struct CodeBlock {
         CodeBlock(ScopeNode* ownerNode_, CodeType codeType_, PassRefPtr<SourceProvider> source_, unsigned sourceOffset_)
             : ownerNode(ownerNode_)
             , globalData(0)
+#if ENABLE(CTI)
+            , ctiCode(0)
+#endif
             , numTemporaries(0)
             , numVars(0)
             , numParameters(0)
@@ -92,10 +147,10 @@ namespace KJS {
             , sourceOffset(sourceOffset_)
         {
         }
-        
+
         ~CodeBlock();
 
-#if !defined(NDEBUG) || ENABLE(SAMPLING_TOOL)
+#if !defined(NDEBUG) || ENABLE_SAMPLING_TOOL
         void dump(ExecState*) const;
         void printStructureIDs(const Instruction*) const;
         void printStructureID(const char* name, const Instruction*, int operand) const;
@@ -103,6 +158,7 @@ namespace KJS {
         int expressionRangeForVPC(const Instruction*, int& divot, int& startOffset, int& endOffset);
         int lineNumberForVPC(const Instruction* vPC);
         bool getHandlerForVPC(const Instruction* vPC, Instruction*& target, int& scopeDepth);
+        void* nativeExceptionCodeForHandlerVPC(const Instruction* handlerVPC);
 
         void mark();
         void refStructureIDs(Instruction* vPC) const;
@@ -110,6 +166,9 @@ namespace KJS {
 
         ScopeNode* ownerNode;
         JSGlobalData* globalData;
+#if ENABLE(CTI)
+        void* ctiCode;
+#endif
 
         int numConstants;
         int numTemporaries;
@@ -125,6 +184,7 @@ namespace KJS {
 
         Vector<Instruction> instructions;
         Vector<size_t> structureIDInstructions;
+        Vector<void*> structureIDAccessStubs;
 
         // Constant pool
         Vector<Identifier> identifiers;
@@ -140,6 +200,12 @@ namespace KJS {
         Vector<SimpleJumpTable> immediateSwitchJumpTables;
         Vector<SimpleJumpTable> characterSwitchJumpTables;
         Vector<StringJumpTable> stringSwitchJumpTables;
+        
+        HashSet<unsigned, DefaultHash<unsigned>::Hash, WTF::UnsignedWithZeroKeyHashTraits<unsigned> > labels;
+
+#if ENABLE(CTI)
+        HashMap<void*, unsigned> ctiReturnAddressVPCMap;
+#endif
 
     private:
 #if !defined(NDEBUG) || ENABLE(SAMPLING_TOOL)
index 2b11ea0..240baa8 100644 (file)
@@ -1192,7 +1192,7 @@ RegisterID* CodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* ite
 
 RegisterID* CodeGenerator::emitCatch(RegisterID* targetRegister, LabelID* start, LabelID* end)
 {
-    HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth };
+    HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth, 0 };
     exceptionHandlers().append(info);
     emitOpcode(op_catch);
     instructions().append(targetRegister->index());
@@ -1320,7 +1320,12 @@ static void prepareJumpTableForStringSwitch(StringJumpTable& jumpTable, int32_t
         
         ASSERT(nodes[i]->isString());
         UString::Rep* clause = static_cast<StringNode*>(nodes[i])->value().rep();
-        jumpTable.add(clause, labels[i]->offsetFrom(switchAddress)); 
+        OffsetLocation location;
+        location.branchOffset = labels[i]->offsetFrom(switchAddress);
+#if ENABLE(CTI)
+        location.ctiOffset = 0;
+#endif
+        jumpTable.offsetTable.add(clause, location);
     }
 }
 
index 575d48c..3c167d2 100644 (file)
@@ -70,6 +70,8 @@ namespace KJS {
                 unsigned j = m_unresolvedJumps[i];
                 m_codeBlock->instructions[j].u.operand = m_location - j;
             }
+
+            m_codeBlock->labels.add(location);
         }
 
         int offsetFrom(int location) const
index 3621794..139d3cf 100644 (file)
@@ -75,9 +75,6 @@ using namespace std;
 
 namespace KJS {
 
-// Default number of ticks before a timeout check should be done.
-static const int initialTickCountThreshold = 255;
-
 // Preferred number of milliseconds between each timeout check
 static const int preferredScriptCheckTimeInterval = 1000;
 
@@ -306,11 +303,8 @@ static bool NEVER_INLINE resolve_skip(ExecState* exec, Instruction* vPC, Registe
     return false;
 }
 
-static void NEVER_INLINE resolveBase(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock)
+ALWAYS_INLINE static JSValue* inlineResolveBase(ExecState* exec, Identifier& property, ScopeChainNode* scopeChain)
 {
-    int dst = (vPC + 1)->u.operand;
-    int property = (vPC + 2)->u.operand;
-
     ScopeChainIterator iter = scopeChain->begin();
     ScopeChainIterator next = iter;
     ++next;
@@ -318,17 +312,25 @@ static void NEVER_INLINE resolveBase(ExecState* exec, Instruction* vPC, Register
     ASSERT(iter != end);
 
     PropertySlot slot;
-    Identifier& ident = codeBlock->identifiers[property];
     JSObject* base;
     while (true) {
         base = *iter;
-        if (next == end || base->getPropertySlot(exec, ident, slot)) {
-            r[dst] = base;
-            return;
-        }
+        if (next == end || base->getPropertySlot(exec, property, slot))
+            return base;
+
         iter = next;
         ++next;
     }
+
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+NEVER_INLINE static void resolveBase(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock)
+{
+    int dst = (vPC + 1)->u.operand;
+    int property = (vPC + 2)->u.operand;
+    r[dst] = inlineResolveBase(exec, codeBlock->identifiers[property], scopeChain);
 }
 
 static bool NEVER_INLINE resolveBaseAndProperty(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
@@ -465,7 +467,6 @@ ALWAYS_INLINE Register* slideRegisterWindowForCall(ExecState* exec, CodeBlock* n
     for (Register* it = r - newCodeBlock->numVars; it != r; ++it)
         (*it) = jsUndefined();
 
-
     for (size_t i = 0; i < newCodeBlock->constantRegisters.size(); ++i)
         r[i] = newCodeBlock->constantRegisters[i];
 
@@ -528,6 +529,11 @@ NEVER_INLINE JSValue* Machine::callEval(ExecState* exec, JSObject* thisObj, Scop
 
 Machine::Machine()
     : m_sampler(0)
+#if ENABLE(CTI)
+    , m_ctiArrayLengthTrampoline(0)
+    , m_ctiStringLengthTrampoline(0)
+    , m_jitCodeBuffer(new JITCodeBuffer(1024 * 1024))
+#endif
     , m_reentryDepth(0)
     , m_timeoutTime(0)
     , m_timeAtLastCheckTimeout(0)
@@ -547,10 +553,24 @@ Machine::Machine()
     JSString* jsString = new (storage) JSString("");
     m_jsStringVptr = jsString->vptr();
     static_cast<JSCell*>(jsString)->~JSCell();
+
+    JSFunction* jsFunction = new (storage) JSFunction(StructureID::create(jsNull()));
+    m_jsFunctionVptr = jsFunction->vptr();
+    static_cast<JSCell*>(jsFunction)->~JSCell();
     
     fastFree(storage);
 }
 
+Machine::~Machine()
+{
+#if ENABLE(CTI)
+    if (m_ctiArrayLengthTrampoline)
+        fastFree(m_ctiArrayLengthTrampoline);
+    if (m_ctiStringLengthTrampoline)
+        fastFree(m_ctiStringLengthTrampoline);
+#endif
+}
+
 #ifndef NDEBUG
 
 void Machine::dumpCallFrame(const CodeBlock* codeBlock, ScopeChainNode* scopeChain, RegisterFile* registerFile, const Register* r)
@@ -626,7 +646,7 @@ void Machine::dumpRegisters(const CodeBlock* codeBlock, RegisterFile* registerFi
 
 #endif
 
-#if !defined(NDEBUG) || ENABLE(SAMPLING_TOOL)
+//#if !defined(NDEBUG) || ENABLE(SAMPLING_TOOL)
 
 bool Machine::isOpcode(Opcode opcode)
 {
@@ -639,7 +659,7 @@ bool Machine::isOpcode(Opcode opcode)
 #endif
 }
 
-#endif
+//#endif
 
 NEVER_INLINE bool Machine::unwindCallFrame(ExecState* exec, JSValue* exceptionValue, const Instruction*& vPC, CodeBlock*& codeBlock, ScopeChainNode*& scopeChain, Register*& r)
 {
@@ -685,7 +705,7 @@ NEVER_INLINE bool Machine::unwindCallFrame(ExecState* exec, JSValue* exceptionVa
 NEVER_INLINE Instruction* Machine::throwException(ExecState* exec, JSValue*& exceptionValue, const Instruction* vPC, CodeBlock*& codeBlock, ScopeChainNode*& scopeChain, Register*& r, bool explicitThrow)
 {
     // Set up the exception object
-
+    
     if (exceptionValue->isObject()) {
         JSObject* exception = static_cast<JSObject*>(exceptionValue);
         if (exception->isNotAnObjectErrorStub()) {
@@ -792,7 +812,13 @@ JSValue* Machine::execute(ProgramNode* programNode, ExecState* exec, ScopeChainN
         (*profiler)->willExecute(exec, programNode->sourceURL(), programNode->lineNo());
 
     m_reentryDepth++;
+#if ENABLE(CTI)
+    if (!codeBlock->ctiCode)
+        CTI::compile(this, exec, codeBlock);
+    JSValue* result = CTI::execute(codeBlock->ctiCode, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
+#else
     JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
+#endif
     m_reentryDepth--;
 
     MACHINE_SAMPLING_privateExecuteReturned();
@@ -852,7 +878,13 @@ JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, ExecState* exec, J
         (*profiler)->willExecute(exec, function);
 
     m_reentryDepth++;
+#if ENABLE(CTI)
+    if (!newCodeBlock->ctiCode)
+        CTI::compile(this, exec, newCodeBlock);
+    JSValue* result = CTI::execute(newCodeBlock->ctiCode, &newExec, &m_registerFile, r, scopeChain, newCodeBlock, exception);
+#else
     JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, newCodeBlock, exception);
+#endif
     m_reentryDepth--;
 
     MACHINE_SAMPLING_privateExecuteReturned();
@@ -930,7 +962,13 @@ JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj
         (*profiler)->willExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
 
     m_reentryDepth++;
+#if ENABLE(CTI)
+    if (!codeBlock->ctiCode)
+        CTI::compile(this, exec, codeBlock);
+    JSValue* result = CTI::execute(codeBlock->ctiCode, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
+#else
     JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
+#endif
     m_reentryDepth--;
 
     MACHINE_SAMPLING_privateExecuteReturned();
@@ -948,43 +986,33 @@ ALWAYS_INLINE void Machine::setScopeChain(ExecState* exec, ScopeChainNode*& scop
     exec->m_scopeChain = newScopeChain;
 }
 
-NEVER_INLINE void Machine::debug(ExecState* exec, const Instruction* vPC, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, Register* r)
+NEVER_INLINE void Machine::debug(ExecState* exec, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, Register* r, DebugHookID debugHookID, int firstLine, int lastLine)
 {
-    int debugHookID = (++vPC)->u.operand;
-    int firstLine = (++vPC)->u.operand;
-    int lastLine = (++vPC)->u.operand;
-
     Debugger* debugger = exec->dynamicGlobalObject()->debugger();
     if (!debugger)
         return;
 
     DebuggerCallFrame debuggerCallFrame(exec, exec->dynamicGlobalObject(), codeBlock, scopeChain, r, 0);
 
-    switch((DebugHookID)debugHookID) {
-    case DidEnterCallFrame: {
-        debugger->callEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
-        return;
-    }
-    case WillLeaveCallFrame: {
-        debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
-        return;
-    }
-    case WillExecuteStatement: {
-        debugger->atStatement(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
-        return;
-    }
-    case WillExecuteProgram: {
-        debugger->willExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
-        return;
-    }
-    case DidExecuteProgram: {
-        debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
-        return;
-    }
-    case DidReachBreakpoint: {
-        debugger->didReachBreakpoint(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
-        return;
-    }
+    switch (debugHookID) {
+        case DidEnterCallFrame:
+            debugger->callEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
+            return;
+        case WillLeaveCallFrame:
+            debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
+            return;
+        case WillExecuteStatement:
+            debugger->atStatement(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
+            return;
+        case WillExecuteProgram:
+            debugger->willExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
+            return;
+        case DidExecuteProgram:
+            debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
+            return;
+        case DidReachBreakpoint:
+            debugger->didReachBreakpoint(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
+            return;
     }
 }
 
@@ -1073,15 +1101,6 @@ ALWAYS_INLINE JSValue* Machine::checkTimeout(JSGlobalObject* globalObject)
     return 0;
 }
 
-static int32_t offsetForStringSwitch(StringJumpTable& jumpTable, JSValue* scrutinee, int32_t defaultOffset) {
-    StringJumpTable::const_iterator end = jumpTable.end();
-    UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
-    StringJumpTable::const_iterator loc = jumpTable.find(value);
-    if (loc == end)
-        return defaultOffset;
-    return loc->second;
-}
-
 static NEVER_INLINE ScopeChainNode* createExceptionScope(ExecState* exec, CodeBlock* codeBlock, const Instruction* vPC, Register* r, ScopeChainNode* scopeChain)
 {
     int dst = (++vPC)->u.operand;
@@ -1235,18 +1254,18 @@ NEVER_INLINE void Machine::tryCacheGetByID(ExecState* exec, CodeBlock* codeBlock
     if (slot.slotBase() == structureID->prototype()) {
         ASSERT(slot.slotBase()->isObject());
 
-        JSObject* slotBaseObject = static_cast<JSObject*>(slot.slotBase());
+        JSObject* baseObject = static_cast<JSObject*>(slot.slotBase());
 
         // Heavy access to a prototype is a good indication that it's not being
         // used as a dictionary.
-        if (slotBaseObject->structureID()->isDictionary()) {
-            RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(slotBaseObject->structureID());
-            slotBaseObject->setStructureID(transition.release());
+        if (baseObject->structureID()->isDictionary()) {
+            RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(baseObject->structureID());
+            baseObject->setStructureID(transition.release());
             static_cast<JSObject*>(baseValue)->structureID()->setCachedPrototypeChain(0);
         }
 
         vPC[0] = getOpcode(op_get_by_id_proto);
-        vPC[5] = slotBaseObject->structureID();
+        vPC[5] = baseObject->structureID();
         vPC[6] = slot.cachedOffset();
 
         codeBlock->refStructureIDs(vPC);
@@ -1258,7 +1277,7 @@ NEVER_INLINE void Machine::tryCacheGetByID(ExecState* exec, CodeBlock* codeBlock
     while (slot.slotBase() != o) {
         JSValue* v = o->structureID()->prototype();
 
-        // If we didn't find slotBase in baseValue's prototype chain, then baseValue
+        // If we didn't find base in baseValue's prototype chain, then baseValue
         // must be a proxy for another object.
         if (v->isNull()) {
             vPC[0] = getOpcode(op_get_by_id_generic);
@@ -1317,6 +1336,11 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
         return 0;
     }
 
+#if ENABLE(CTI)
+    // Currently with CTI enabled we never interpret functions
+    ASSERT_NOT_REACHED();
+#endif
+
     JSValue* exceptionValue = 0;
     Instruction* handlerVPC = 0;
 
@@ -1326,7 +1350,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
     unsigned tickCount = m_ticksUntilNextTimeoutCheck + 1;
 
 #define VM_CHECK_EXCEPTION() \
-     do { \
+    do { \
         if (UNLIKELY(exec->hadException())) { \
             exceptionValue = exec->exception(); \
             goto vm_throw; \
@@ -1343,7 +1367,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
             goto vm_throw; \
         tickCount = m_ticksUntilNextTimeoutCheck; \
     }
-    
+
 #if HAVE(COMPUTED_GOTO)
     #define NEXT_OPCODE MACHINE_SAMPLING_sample(codeBlock, vPC); goto *vPC->u.opcode
 #if DUMP_OPCODE_STATS
@@ -2484,7 +2508,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
         int dst = (++vPC)->u.operand;
         int base = (++vPC)->u.operand;
         int property = (++vPC)->u.operand;
-
+        
         JSValue* baseValue = r[base].jsValue(exec);
         JSValue* subscript = r[property].jsValue(exec);
 
@@ -2798,7 +2822,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
         if (!scrutinee->isString())
             vPC += defaultOffset;
         else 
-            vPC += offsetForStringSwitch(codeBlock->stringSwitchJumpTables[tableIndex], scrutinee, defaultOffset);
+            vPC += codeBlock->stringSwitchJumpTables[tableIndex].offsetForValue(static_cast<JSString*>(scrutinee)->value().rep(), defaultOffset);
         NEXT_OPCODE;
     }
     BEGIN_OPCODE(op_new_func) {
@@ -3380,10 +3404,13 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
          Notifies the debugger of the current state of execution. This opcode
          is only generated while the debugger is attached.
         */
+        int debugHookID = (++vPC)->u.operand;
+        int firstLine = (++vPC)->u.operand;
+        int lastLine = (++vPC)->u.operand;
 
-        debug(exec, vPC, codeBlock, scopeChain, r);
+        debug(exec, codeBlock, scopeChain, r, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
 
-        vPC += 4;
+        ++vPC;
         NEXT_OPCODE;
     }
     vm_throw: {
@@ -3405,6 +3432,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
     #undef NEXT_OPCODE
     #undef BEGIN_OPCODE
     #undef VM_CHECK_EXCEPTION
+    #undef CHECK_FOR_TIMEOUT
 }
 
 JSValue* Machine::retrieveArguments(ExecState* exec, JSFunction* function) const
@@ -3498,4 +3526,1613 @@ void Machine::getArgumentsData(Register* callFrame, JSFunction*& function, Regis
     argc = callFrame[RegisterFile::ArgumentCount].i() - 1; // - 1 to skip "this"
 }
 
+#if ENABLE(CTI)
+
+NEVER_INLINE static void doSetReturnAddressVMThrowTrampoline(void** returnAddress)
+{
+    ctiSetReturnAddress(returnAddress, (void*)ctiVMThrowTrampoline);
+}
+
+NEVER_INLINE void Machine::tryCTICachePutByID(ExecState* exec, CodeBlock* codeBlock, void* returnAddress, JSValue* baseValue, const PutPropertySlot& slot)
+{
+    // The interpreter checks for recursion here; I do not believe this can occur in CTI.
+
+    if (JSImmediate::isImmediate(baseValue))
+        return;
+
+    // Uncacheable: give up.
+    if (!slot.isCacheable()) {
+        ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
+        return;
+    }
+
+    // FIXME: Cache new property transitions, too.
+    if (slot.type() == PutPropertySlot::NewProperty) {
+        ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
+        return;
+    }
+    
+    JSCell* baseCell = static_cast<JSCell*>(baseValue);
+    StructureID* structureID = baseCell->structureID();
+
+    // FIXME: Remove this !structureID check once all objects have StructureIDs.
+    if (!structureID) {
+        ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
+        return;
+    }
+
+    if (structureID->isDictionary()) {
+        ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
+        return;
+    }
+
+    // In the interpreter the last structure is trapped here; in CTI we use the
+    // *_second method to achieve a similar (but not quite the same) effect.
+
+    unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(returnAddress);
+    Instruction* vPC = codeBlock->instructions.begin() + vPCIndex;
+
+    // Cache hit: Specialize instruction and ref StructureIDs.
+
+    // If baseCell != base, then baseCell must be a proxy for another object.
+    if (baseCell != slot.base()) {
+        ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
+        return;
+    }
+    vPC[0] = getOpcode(op_put_by_id_replace);
+    vPC[4] = structureID;
+    vPC[5] = slot.cachedOffset();
+    codeBlock->refStructureIDs(vPC);
+
+    ctiRepatchCallByReturnAddress(returnAddress, CTI::compilePutByIdReplace(this, exec, codeBlock, structureID, slot.cachedOffset()));
+}
+
+void* Machine::getCTIArrayLengthTrampoline(ExecState* exec, CodeBlock* codeBlock)
+{
+    if (!m_ctiArrayLengthTrampoline)
+        m_ctiArrayLengthTrampoline = CTI::compileArrayLengthTrampoline(this, exec, codeBlock);
+        
+    return m_ctiArrayLengthTrampoline;
+}
+
+void* Machine::getCTIStringLengthTrampoline(ExecState* exec, CodeBlock* codeBlock)
+{
+    if (!m_ctiStringLengthTrampoline)
+        m_ctiStringLengthTrampoline = CTI::compileStringLengthTrampoline(this, exec, codeBlock);
+        
+    return m_ctiStringLengthTrampoline;
+}
+
+NEVER_INLINE void Machine::tryCTICacheGetByID(ExecState* exec, CodeBlock* codeBlock, void* returnAddress, JSValue* baseValue, const Identifier& propertyName, const PropertySlot& slot)
+{
+    // The interpreter checks for recursion here; I do not believe this can occur in CTI.
+
+    if (isJSArray(baseValue) && propertyName == exec->propertyNames().length) {
+        ctiRepatchCallByReturnAddress(returnAddress, getCTIArrayLengthTrampoline(exec, codeBlock));
+        return;
+    }
+    if (isJSString(baseValue) && propertyName == exec->propertyNames().length) {
+        ctiRepatchCallByReturnAddress(returnAddress, getCTIStringLengthTrampoline(exec, codeBlock));
+        return;
+    }
+
+    // Uncacheable: give up.
+    if (!slot.isCacheable()) {
+        ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_get_by_id_generic);
+        return;
+    }
+
+    // FIXME: Cache property access for immediates.
+    if (JSImmediate::isImmediate(baseValue)) {
+        ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_get_by_id_generic);
+        return;
+    }
+
+    JSCell* baseCell = static_cast<JSCell*>(baseValue);
+    StructureID* structureID = baseCell->structureID();
+
+    // FIXME: Remove this !structureID check once all JSCells have StructureIDs.
+    if (!structureID) {
+        ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_get_by_id_generic);
+        return;
+    }
+
+    if (structureID->isDictionary()) {
+        ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_get_by_id_generic);
+        return;
+    }
+
+    // In the interpreter the last structure is trapped here; in CTI we use the
+    // *_second method to achieve a similar (but not quite the same) effect.
+
+    unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(returnAddress);
+    Instruction* vPC = codeBlock->instructions.begin() + vPCIndex;
+
+    // Cache hit: Specialize instruction and ref StructureIDs.
+
+    if (slot.slotBase() == baseValue) {
+        // set this up, so derefStructureIDs can do it's job.
+        vPC[0] = getOpcode(op_get_by_id_self);
+        vPC[4] = structureID;
+        vPC[5] = slot.cachedOffset();
+        codeBlock->refStructureIDs(vPC);
+        
+        ctiRepatchCallByReturnAddress(returnAddress, CTI::compileGetByIdSelf(this, exec, codeBlock, structureID, slot.cachedOffset()));
+        return;
+    }
+
+    if (slot.slotBase() == structureID->prototype()) {
+        ASSERT(slot.slotBase()->isObject());
+
+        JSObject* slotBaseObject = static_cast<JSObject*>(slot.slotBase());
+
+        // Heavy access to a prototype is a good indication that it's not being
+        // used as a dictionary.
+        if (slotBaseObject->structureID()->isDictionary()) {
+            RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(slotBaseObject->structureID());
+            slotBaseObject->setStructureID(transition.release());
+            static_cast<JSObject*>(baseValue)->structureID()->setCachedPrototypeChain(0);
+        }
+
+        vPC[0] = getOpcode(op_get_by_id_proto);
+        vPC[4] = structureID;
+        vPC[5] = slotBaseObject->structureID();
+        vPC[6] = slot.cachedOffset();
+        codeBlock->refStructureIDs(vPC);
+
+        ctiRepatchCallByReturnAddress(returnAddress, CTI::compileGetByIdProto(this, exec, codeBlock, structureID, slotBaseObject->structureID(), slot.cachedOffset()));
+        return;
+    }
+
+    size_t count = 0;
+    JSObject* o = static_cast<JSObject*>(baseValue);
+    while (slot.slotBase() != o) {
+        JSValue* v = o->structureID()->prototype();
+
+        // If we didn't find slotBase in baseValue's prototype chain, then baseValue
+        // must be a proxy for another object.
+
+        if (v->isNull()) {
+            vPC[0] = getOpcode(op_get_by_id_generic);
+            return;
+        }
+
+        o = static_cast<JSObject*>(v);
+
+        // Heavy access to a prototype is a good indication that it's not being
+        // used as a dictionary.
+        if (o->structureID()->isDictionary()) {
+            RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(o->structureID());
+            o->setStructureID(transition.release());
+            static_cast<JSObject*>(baseValue)->structureID()->setCachedPrototypeChain(0);
+        }
+
+        ++count;
+    }
+
+    StructureIDChain* chain = structureID->cachedPrototypeChain();
+    if (!chain)
+        chain = cachePrototypeChain(structureID);
+
+    vPC[0] = getOpcode(op_get_by_id_chain);
+    vPC[4] = structureID;
+    vPC[5] = chain;
+    vPC[6] = count;
+    vPC[7] = slot.cachedOffset();
+    codeBlock->refStructureIDs(vPC);
+
+    ctiRepatchCallByReturnAddress(returnAddress, CTI::compileGetByIdChain(this, exec, codeBlock, structureID, chain, count, slot.cachedOffset()));
+}
+
+
+#define JSVALUE_VM_CHECK_EXCEPTION_ARG(exception) \
+    do { \
+        if (UNLIKELY(exception != 0)) { \
+            exec->setException(exception); \
+            exec->setCTIReturnAddress(CTI_RETURN_ADDRESS); \
+            doSetReturnAddressVMThrowTrampoline(&CTI_RETURN_ADDRESS); \
+            return 0; \
+        } \
+    } while (0)
+#define VM_CHECK_EXCEPTION_v() \
+    do { \
+        if (UNLIKELY(exec->hadException())) { \
+            exec->setCTIReturnAddress(CTI_RETURN_ADDRESS); \
+            doSetReturnAddressVMThrowTrampoline(&CTI_RETURN_ADDRESS); \
+            return; \
+        } \
+    } while (0)
+#define VM_CHECK_EXCEPTION(type) \
+    do { \
+        if (UNLIKELY(exec->hadException())) { \
+            exec->setCTIReturnAddress(CTI_RETURN_ADDRESS); \
+            doSetReturnAddressVMThrowTrampoline(&CTI_RETURN_ADDRESS); \
+            return (type)0; \
+        } \
+    } while (0)
+#define VM_CHECK_EXCEPTION_AT_END() \
+    do { \
+        if (UNLIKELY(exec->hadException())) { \
+            /*printf("VM_CHECK_EXCEPTION_AT_END()\n");*/ \
+            exec->setCTIReturnAddress(CTI_RETURN_ADDRESS); \
+            doSetReturnAddressVMThrowTrampoline(&CTI_RETURN_ADDRESS); \
+        } \
+    } while (0)
+
+void Machine::cti_op_end(CTI_ARGS)
+{
+    ASSERT(ARG_scopeChain->refCount > 1);
+    ARG_scopeChain->deref();
+}
+
+JSValue* Machine::cti_op_add(CTI_ARGS)
+{
+    JSValue* src1 = ARG_src1;
+    JSValue* src2 = ARG_src2;
+
+    ExecState* exec = ARG_exec;
+    JSValue* result = jsAdd(exec, src1, src2);
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+JSValue* Machine::cti_op_pre_inc(CTI_ARGS)
+{
+    JSValue* v = ARG_src1;
+
+    ExecState* exec = ARG_exec;
+    JSValue* result = jsNumber(exec, v->toNumber(exec) + 1);
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+void Machine::cti_timeout_check(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+
+    if (exec->machine()->checkTimeout(exec->dynamicGlobalObject()))
+        exec->setException(createInterruptedExecutionException(exec));
+
+    VM_CHECK_EXCEPTION_AT_END();
+}
+
+
+int Machine::cti_op_loop_if_less(CTI_ARGS)
+{
+    JSValue* src1 = ARG_src1;
+    JSValue* src2 = ARG_src2;
+    ExecState* exec = ARG_exec;
+
+    bool result = jsLess(exec, src1, src2);
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+JSValue* Machine::cti_op_new_object(CTI_ARGS)
+{
+    return constructEmptyObject(ARG_exec);;
+}
+
+void Machine::cti_op_put_by_id(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    Identifier& ident = *ARG_id2;
+
+    PutPropertySlot slot;
+    ARG_src1->put(exec, ident, ARG_src3, slot);
+
+    ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, (void*)cti_op_put_by_id_second);
+
+    VM_CHECK_EXCEPTION_AT_END();
+}
+
+void Machine::cti_op_put_by_id_second(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    Identifier& ident = *ARG_id2;
+
+    JSValue* baseValue = ARG_src1;
+    PutPropertySlot slot;
+    baseValue->put(exec, ident, ARG_src3, slot);
+
+    exec->machine()->tryCTICachePutByID(exec, ARG_codeBlock, CTI_RETURN_ADDRESS, baseValue, slot);
+
+    VM_CHECK_EXCEPTION_AT_END();
+}
+
+void Machine::cti_op_put_by_id_generic(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    Identifier& ident = *ARG_id2;
+
+    PutPropertySlot slot;
+    ARG_src1->put(exec, ident, ARG_src3, slot);
+
+    VM_CHECK_EXCEPTION_AT_END();
+}
+
+void Machine::cti_op_put_by_id_fail(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    Identifier& ident = *ARG_id2;
+
+    PutPropertySlot slot;
+    ARG_src1->put(exec, ident, ARG_src3, slot);
+
+    // should probably uncachePutByID() ... this would mean doing a vPC lookup - might be worth just bleeding this until the end.
+    ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, (void*)cti_op_put_by_id_generic);
+
+    VM_CHECK_EXCEPTION_AT_END();
+}
+
+JSValue* Machine::cti_op_get_by_id(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    Identifier& ident = *ARG_id2;
+
+    JSValue* baseValue = ARG_src1;
+    PropertySlot slot(baseValue);
+    JSValue* result = baseValue->get(exec, ident, slot);
+
+    ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, (void*)cti_op_get_by_id_second);
+
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+JSValue* Machine::cti_op_get_by_id_second(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    Identifier& ident = *ARG_id2;
+
+    JSValue* baseValue = ARG_src1;
+    PropertySlot slot(baseValue);
+    JSValue* result = baseValue->get(exec, ident, slot);
+
+    exec->machine()->tryCTICacheGetByID(exec, ARG_codeBlock, CTI_RETURN_ADDRESS, baseValue, ident, slot);
+
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+JSValue* Machine::cti_op_get_by_id_generic(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    Identifier& ident = *ARG_id2;
+
+    JSValue* baseValue = ARG_src1;
+    PropertySlot slot(baseValue);
+    JSValue* result = baseValue->get(exec, ident, slot);
+
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+JSValue* Machine::cti_op_get_by_id_fail(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    Identifier& ident = *ARG_id2;
+
+    JSValue* baseValue = ARG_src1;
+    PropertySlot slot(baseValue);
+    JSValue* result = baseValue->get(exec, ident, slot);
+
+    // should probably uncacheGetByID() ... this would mean doing a vPC lookup - might be worth just bleeding this until the end.
+    ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, (void*)cti_op_get_by_id_generic);
+
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+JSValue* Machine::cti_op_instanceof(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    JSValue* baseVal = ARG_src2;
+
+    if (!baseVal->isObject()) {
+        CodeBlock* codeBlock = ARG_codeBlock;
+        ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
+        unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
+        exec->setException(createInvalidParamError(exec, "instanceof", baseVal, codeBlock->instructions.begin() + vPCIndex, codeBlock));
+        VM_CHECK_EXCEPTION(JSValue*);
+    }
+
+    JSObject* baseObj = static_cast<JSObject*>(baseVal);
+    JSValue* result = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec,  ARG_src1) : false);
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+JSValue* Machine::cti_op_del_by_id(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    Identifier& ident = *ARG_id2;
+    
+    JSObject* baseObj = ARG_src1->toObject(exec);
+
+    JSValue* result = jsBoolean(baseObj->deleteProperty(exec, ident));
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+JSValue* Machine::cti_op_mul(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    JSValue* src1 = ARG_src1;
+    JSValue* src2 = ARG_src2;
+
+    double left;
+    double right;
+    if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
+        return jsNumber(exec, left * right);
+    else {
+        JSValue* result = jsNumber(exec, src1->toNumber(exec) * src2->toNumber(exec));
+        VM_CHECK_EXCEPTION_AT_END();
+        return result;
+    }
+}
+
+JSValue* Machine::cti_op_new_func(CTI_ARGS)
+{
+    return ARG_func1->makeFunction(ARG_exec, ARG_scopeChain);
+}
+
+void* Machine::cti_op_call_JSFunction(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    RegisterFile* registerFile = ARG_registerFile;
+    Register* r = ARG_r;
+    CodeBlock* codeBlock = ARG_codeBlock;
+    ScopeChainNode* scopeChain = ARG_scopeChain;
+
+    Machine* machine = exec->machine();
+    JSValue* exceptionValue = 0;
+    Register* registerBase = registerFile->base();
+    
+    JSValue* funcVal = ARG_src1;
+    JSValue* thisValue = ARG_src2;
+    int firstArg = ARG_int3;
+    int argCount = ARG_int4;
+
+    CallData callData;
+#ifndef NDEBUG
+    CallType callType =
+#endif
+        funcVal->getCallData(callData);
+
+    ASSERT(callType == CallTypeJS);
+
+    if (*ARG_profilerReference)
+        (*ARG_profilerReference)->willExecute(exec, static_cast<JSObject*>(funcVal));
+
+    ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
+    FunctionBodyNode* functionBodyNode = callData.js.functionBody;
+    CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
+
+    r[firstArg] = thisValue;
+
+    Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
+    machine->initializeCallFrame(callFrame, codeBlock, ARG_instr5, scopeChain, r, 0/*dst*/, firstArg, argCount, 0, funcVal);
+    exec->m_callFrame = callFrame;
+
+    r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
+    JSVALUE_VM_CHECK_EXCEPTION_ARG(exceptionValue);
+    
+    codeBlock = newCodeBlock;
+    machine->setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
+
+    if (!codeBlock->ctiCode)
+        CTI::compile(machine, exec, codeBlock);
+
+    ARG_setScopeChain(scopeChain);
+    ARG_setCodeBlock(codeBlock);
+    ARG_setR(r);
+    return codeBlock->ctiCode;
+}
+
+JSValue* Machine::cti_op_call_NotJSFunction(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    Register* r = ARG_r;
+
+    JSValue* funcVal = ARG_src1;
+    JSValue* thisValue = ARG_src2;
+    int firstArg = ARG_int3;
+    int argCount = ARG_int4;
+
+    CallData callData;
+    CallType callType = funcVal->getCallData(callData);
+
+    ASSERT(callType != CallTypeJS);
+
+    if (callType == CallTypeHost) {
+        CodeBlock* codeBlock = ARG_codeBlock;
+        ScopeChainNode* scopeChain = ARG_scopeChain;
+        Machine* machine = exec->machine();
+
+        Register* oldCallFrame = exec->m_callFrame;
+        Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
+        machine->initializeCallFrame(callFrame, codeBlock, ARG_instr5, scopeChain, r, 0/*dst*/, firstArg, argCount, 0, funcVal);
+        exec->m_callFrame = callFrame;
+
+        if (*ARG_profilerReference)
+            (*ARG_profilerReference)->willExecute(exec, static_cast<JSObject*>(funcVal));
+
+        ArgList argList(r + firstArg + 1, argCount - 1);
+
+        CTI_MACHINE_SAMPLING_callingHostFunction();
+
+        JSValue* returnValue = callData.native.function(exec, static_cast<JSObject*>(funcVal), thisValue, argList);
+        exec->m_callFrame = oldCallFrame;
+        VM_CHECK_EXCEPTION(JSValue*);
+
+        if (*ARG_profilerReference)
+            (*ARG_profilerReference)->didExecute(exec, static_cast<JSObject*>(funcVal));
+
+        return returnValue;
+
+    }
+
+    ASSERT(callType == CallTypeNone);
+
+    exec->setException(createNotAFunctionError(exec, funcVal, ARG_instr5, ARG_codeBlock));
+    VM_CHECK_EXCEPTION_AT_END();
+    return 0;
+}
+
+JSValue* Machine::cti_op_ret(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    Register* r = ARG_r;
+    CodeBlock* codeBlock = ARG_codeBlock;
+    ScopeChainNode* scopeChain = ARG_scopeChain;
+
+    Machine* machine = exec->machine();
+
+    Register* callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
+    if (JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
+        ASSERT(!codeBlock->needsFullScopeChain || scopeChain->object == activation);
+        ASSERT(activation->isActivationObject());
+        activation->copyRegisters();
+    }
+
+    if (*ARG_profilerReference)
+        (*ARG_profilerReference)->didExecute(exec, static_cast<JSObject*>(callFrame[RegisterFile::Callee].jsValue(exec)));
+
+    if (codeBlock->needsFullScopeChain)
+        scopeChain->deref();
+
+    JSValue* returnValue = ARG_src1;
+    if (callFrame[RegisterFile::CalledAsConstructor].i() && !returnValue->isObject()) {
+        JSValue* thisObject = callFrame[RegisterFile::CallFrameHeaderSize].jsValue(exec);
+        returnValue = thisObject;
+    }
+
+    codeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
+    if (codeBlock) {
+        machine->setScopeChain(exec, scopeChain, callFrame[RegisterFile::CallerScopeChain].scopeChain());
+        r = callFrame[RegisterFile::CallerRegisters].r();
+        exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
+    }
+
+    ARG_setScopeChain(scopeChain);
+    ARG_setCodeBlock(codeBlock);
+    ARG_setR(r);
+
+    return returnValue;
+}
+
+JSValue* Machine::cti_op_new_array(CTI_ARGS)
+{
+    ArgList argsList(ARG_registers1, ARG_int2);
+    return constructArray(ARG_exec, argsList);
+}
+
+JSValue* Machine::cti_op_resolve(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    ScopeChainNode* scopeChain = ARG_scopeChain;
+
+    ScopeChainIterator iter = scopeChain->begin();
+    ScopeChainIterator end = scopeChain->end();
+    ASSERT(iter != end);
+
+    Identifier& ident = *ARG_id1;
+    do {
+        JSObject* o = *iter;
+        PropertySlot slot(o);
+        if (o->getPropertySlot(exec, ident, slot)) {
+            JSValue* result = slot.getValue(exec, ident);
+            VM_CHECK_EXCEPTION_AT_END();
+            return result;
+        }
+    } while (++iter != end);
+
+    CodeBlock* codeBlock = ARG_codeBlock;
+    ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
+    unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
+    exec->setException(createUndefinedVariableError(exec, ident, codeBlock->instructions.begin() + vPCIndex, codeBlock));
+
+    VM_CHECK_EXCEPTION_AT_END();
+    return 0;
+}
+
+void* Machine::cti_op_construct_JSConstruct(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    RegisterFile* registerFile = ARG_registerFile;
+    Register* r = ARG_r;
+    CodeBlock* codeBlock = ARG_codeBlock;
+    ScopeChainNode* scopeChain = ARG_scopeChain;
+
+    Machine* machine = exec->machine();
+    JSValue* exceptionValue = 0;
+    Register* registerBase = registerFile->base();
+    
+    JSValue* constrVal = ARG_src1;
+    int firstArg = ARG_int2;
+    int argCount = ARG_int3;
+
+    ConstructData constructData;
+#ifndef NDEBUG
+    ConstructType constructType =
+#endif
+        constrVal->getConstructData(constructData);
+
+    // Removing this line of code causes a measurable regression on squirrelfish.
+    JSObject* constructor = static_cast<JSObject*>(constrVal);
+
+    ASSERT(constructType == ConstructTypeJS);
+
+    if (*ARG_profilerReference)
+        (*ARG_profilerReference)->willExecute(exec, constructor);
+
+    JSObject* prototype;
+    JSValue* p = constructor->get(exec, exec->propertyNames().prototype);
+    if (p->isObject())
+        prototype = static_cast<JSObject*>(p);
+    else
+        prototype = scopeChain->globalObject()->objectPrototype();
+    JSObject* newObject = new (exec) JSObject(prototype);
+
+    ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
+    FunctionBodyNode* functionBodyNode = constructData.js.functionBody;
+    CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
+
+    r[firstArg] = newObject; // "this" value
+
+    Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
+    machine->initializeCallFrame(callFrame, codeBlock, ARG_instr4, scopeChain, r, 0/*dst*/, firstArg, argCount, 1, constructor);
+    exec->m_callFrame = callFrame;
+
+    r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
+    JSVALUE_VM_CHECK_EXCEPTION_ARG(exceptionValue);
+
+    codeBlock = newCodeBlock;
+    machine->setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
+
+    if (!codeBlock->ctiCode)
+        CTI::compile(machine, exec, codeBlock);
+
+    ARG_setScopeChain(scopeChain);
+    ARG_setCodeBlock(codeBlock);
+    ARG_setR(r);
+    return codeBlock->ctiCode;
+}
+
+JSValue* Machine::cti_op_construct_NotJSConstruct(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    Register* r = ARG_r;
+
+    JSValue* constrVal = ARG_src1;
+    int firstArg = ARG_int2;
+    int argCount = ARG_int3;
+
+    ConstructData constructData;
+    ConstructType constructType = constrVal->getConstructData(constructData);
+
+    // Removing this line of code causes a measurable regression on squirrelfish.
+    JSObject* constructor = static_cast<JSObject*>(constrVal);
+
+    ASSERT(constructType != ConstructTypeJS);
+
+    if (constructType == ConstructTypeHost) {
+        CodeBlock* codeBlock = ARG_codeBlock;
+        ScopeChainNode* scopeChain = ARG_scopeChain;
+        Machine* machine = exec->machine();
+
+        Register* oldCallFrame = exec->m_callFrame;
+        Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
+        machine->initializeCallFrame(callFrame, codeBlock, ARG_instr5, scopeChain, r, 0/*dst*/, firstArg, argCount, 1, constrVal);
+        exec->m_callFrame = callFrame;
+
+        if (*ARG_profilerReference)
+            (*ARG_profilerReference)->willExecute(exec, constructor);
+
+        ArgList argList(r + firstArg + 1, argCount - 1);
+
+        CTI_MACHINE_SAMPLING_callingHostFunction();
+
+        JSValue* returnValue = constructData.native.function(exec, constructor, argList);
+        exec->m_callFrame = oldCallFrame;
+        VM_CHECK_EXCEPTION(JSValue*);
+
+        if (*ARG_profilerReference)
+            (*ARG_profilerReference)->didExecute(exec, constructor);
+
+        return returnValue;
+    }
+
+    ASSERT(constructType == ConstructTypeNone);
+
+    exec->setException(createNotAConstructorError(exec, constrVal, ARG_instr4, ARG_codeBlock));
+    VM_CHECK_EXCEPTION_AT_END();
+    return 0;
+}
+
+JSValue* Machine::cti_op_get_by_val(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    Machine* machine = exec->machine();
+
+    JSValue* baseValue = ARG_src1;
+    JSValue* subscript = ARG_src2;
+
+    JSValue* result;
+    unsigned i;
+
+    bool isUInt32 = JSImmediate::getUInt32(subscript, i);
+    if (LIKELY(isUInt32)) {
+        if (machine->isJSArray(baseValue)) {
+            JSArray* jsArray = static_cast<JSArray*>(baseValue);
+            if (jsArray->canGetIndex(i))
+                result = jsArray->getIndex(i);
+            else
+                result = jsArray->JSArray::get(exec, i);
+        } else if (machine->isJSString(baseValue) && static_cast<JSString*>(baseValue)->canGetIndex(i))
+            result = static_cast<JSString*>(baseValue)->getIndex(exec, i);
+        else
+            result = baseValue->get(exec, i);
+    } else {
+        Identifier property(exec, subscript->toString(exec));
+        result = baseValue->get(exec, property);
+    }
+
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+JSValue* Machine::cti_op_resolve_func(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    ScopeChainNode* scopeChain = ARG_scopeChain;
+
+    ScopeChainIterator iter = scopeChain->begin();
+    ScopeChainIterator end = scopeChain->end();
+
+    // FIXME: add scopeDepthIsZero optimization
+
+    ASSERT(iter != end);
+
+    Identifier& ident = *ARG_id1;
+    JSObject* base;
+    do {
+        base = *iter;
+        PropertySlot slot(base);
+        if (base->getPropertySlot(exec, ident, slot)) {            
+            // ECMA 11.2.3 says that if we hit an activation the this value should be null.
+            // However, section 10.2.3 says that in the case where the value provided
+            // by the caller is null, the global object should be used. It also says
+            // that the section does not apply to internal functions, but for simplicity
+            // of implementation we use the global object anyway here. This guarantees
+            // that in host objects you always get a valid object for this.
+            // We also handle wrapper substitution for the global object at the same time.
+            JSObject* thisObj = base->toThisObject(exec);
+            JSValue* result = slot.getValue(exec, ident);
+            VM_CHECK_EXCEPTION_AT_END();
+
+            ARG_set2ndResult(result);
+            return thisObj;
+        }
+        ++iter;
+    } while (iter != end);
+
+    CodeBlock* codeBlock = ARG_codeBlock;
+    ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
+    unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
+    exec->setException(createUndefinedVariableError(exec, ident, codeBlock->instructions.begin() + vPCIndex, codeBlock));
+
+    VM_CHECK_EXCEPTION_AT_END();
+    return 0;
+}
+
+JSValue* Machine::cti_op_sub(CTI_ARGS)
+{
+    JSValue* src1 = ARG_src1;
+    JSValue* src2 = ARG_src2;
+
+    double left;
+    double right;
+    if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
+        return jsNumber(ARG_exec, left - right);
+    else {
+        ExecState* exec = ARG_exec;
+        JSValue* result = jsNumber(exec, src1->toNumber(exec) - src2->toNumber(exec));
+        VM_CHECK_EXCEPTION_AT_END();
+        return result;
+    }
+}
+
+void Machine::cti_op_put_by_val(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    Machine* machine = exec->machine();
+
+    JSValue* baseValue = ARG_src1;
+    JSValue* subscript = ARG_src2;
+    JSValue* value = ARG_src3;
+
+    unsigned i;
+
+    bool isUInt32 = JSImmediate::getUInt32(subscript, i);
+    if (LIKELY(isUInt32)) {
+        if (machine->isJSArray(baseValue)) {
+            JSArray* jsArray = static_cast<JSArray*>(baseValue);
+            if (jsArray->canSetIndex(i))
+                jsArray->setIndex(i, value);
+            else
+                jsArray->JSArray::put(exec, i, value);
+        } else
+            baseValue->put(exec, i, value);
+    } else {
+        Identifier property(exec, subscript->toString(exec));
+        if (!exec->hadException()) { // Don't put to an object if toString threw an exception.
+            PutPropertySlot slot;
+            baseValue->put(exec, property, value, slot);
+        }
+    }
+
+    VM_CHECK_EXCEPTION_AT_END();
+}
+
+JSValue* Machine::cti_op_lesseq(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    JSValue* result = jsBoolean(jsLessEq(exec, ARG_src1, ARG_src2));
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+int Machine::cti_op_loop_if_true(CTI_ARGS)
+{
+    JSValue* src1 = ARG_src1;
+
+    ExecState* exec = ARG_exec;
+
+    bool result = src1->toBoolean(exec);
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+JSValue* Machine::cti_op_negate(CTI_ARGS)
+{
+    JSValue* src = ARG_src1;
+
+    ExecState* exec = ARG_exec;
+
+    double v;
+    if (fastIsNumber(src, v))
+        return jsNumber(exec, -v);
+    else {
+        JSValue* result = jsNumber(exec, -src->toNumber(exec));
+        VM_CHECK_EXCEPTION_AT_END();
+        return result;
+    }
+}
+
+JSValue* Machine::cti_op_resolve_base(CTI_ARGS)
+{
+    return inlineResolveBase(ARG_exec, *ARG_id1, ARG_scopeChain);
+}
+
+JSValue* Machine::cti_op_resolve_skip(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    ScopeChainNode* scopeChain = ARG_scopeChain;
+
+    int skip = ARG_int2;
+
+    ScopeChainIterator iter = scopeChain->begin();
+    ScopeChainIterator end = scopeChain->end();
+    ASSERT(iter != end);
+    while (skip--) {
+        ++iter;
+        ASSERT(iter != end);
+    }
+    Identifier& ident = *ARG_id1;
+    do {
+        JSObject* o = *iter;
+        PropertySlot slot(o);
+        if (o->getPropertySlot(exec, ident, slot)) {
+            JSValue* result = slot.getValue(exec, ident);
+            VM_CHECK_EXCEPTION_AT_END();
+            return result;
+        }
+    } while (++iter != end);
+
+    CodeBlock* codeBlock = ARG_codeBlock;
+    ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
+    unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
+    exec->setException(createUndefinedVariableError(exec, ident, codeBlock->instructions.begin() + vPCIndex, codeBlock));
+
+    VM_CHECK_EXCEPTION_AT_END();
+    return 0;
+}
+
+JSValue* Machine::cti_op_div(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    JSValue* src1 = ARG_src1;
+    JSValue* src2 = ARG_src2;
+
+    double left;
+    double right;
+    if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
+        return jsNumber(exec, left / right);
+    else {
+        JSValue* result = jsNumber(exec, src1->toNumber(exec) / src2->toNumber(exec));
+        VM_CHECK_EXCEPTION_AT_END();
+        return result;
+    }
+}
+
+JSValue* Machine::cti_op_pre_dec(CTI_ARGS)
+{
+    JSValue* v = ARG_src1;
+
+    ExecState* exec = ARG_exec;
+    JSValue* result = jsNumber(exec, v->toNumber(exec) - 1);
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+int Machine::cti_op_jless(CTI_ARGS)
+{
+    JSValue* src1 = ARG_src1;
+    JSValue* src2 = ARG_src2;
+    ExecState* exec = ARG_exec;
+
+    bool result = jsLess(exec, src1, src2);
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+JSValue* Machine::cti_op_not(CTI_ARGS)
+{
+    JSValue* src = ARG_src1;
+
+    ExecState* exec = ARG_exec;
+
+    JSValue* result = jsBoolean(!src->toBoolean(exec));
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+int SFX_CALL Machine::cti_op_jtrue(CTI_ARGS)
+{
+    JSValue* src1 = ARG_src1;
+
+    ExecState* exec = ARG_exec;
+
+    bool result = src1->toBoolean(exec);
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+JSValue* Machine::cti_op_post_inc(CTI_ARGS)
+{
+    JSValue* v = ARG_src1;
+
+    ExecState* exec = ARG_exec;
+
+    JSValue* number = v->toJSNumber(exec);
+    VM_CHECK_EXCEPTION(JSValue*);
+    ARG_set2ndResult(jsNumber(exec, number->uncheckedGetNumber() + 1));
+    return number;
+}
+
+JSValue* Machine::cti_op_eq(CTI_ARGS)
+{
+    JSValue* src1 = ARG_src1;
+    JSValue* src2 = ARG_src2;
+
+    if (JSImmediate::areBothImmediateNumbers(src1, src2))
+        return jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
+    else {
+        ExecState* exec = ARG_exec;
+        JSValue* result = jsBoolean(equal(exec, src1, src2));
+        VM_CHECK_EXCEPTION_AT_END();
+        return result;
+    }
+}
+
+JSValue* Machine::cti_op_lshift(CTI_ARGS)
+{
+    JSValue* val = ARG_src1;
+    JSValue* shift = ARG_src2;
+
+    ExecState* exec = ARG_exec;
+
+    int32_t left;
+    uint32_t right;
+    if (JSImmediate::areBothImmediateNumbers(val, shift))
+        return jsNumber(exec, JSImmediate::getTruncatedInt32(val) << (JSImmediate::getTruncatedUInt32(shift) & 0x1f));
+    else if (fastToInt32(val, left) && fastToUInt32(shift, right))
+        return jsNumber(exec, left << (right & 0x1f));
+    else {
+        JSValue* result = jsNumber(exec, (val->toInt32(exec)) << (shift->toUInt32(exec) & 0x1f));
+        VM_CHECK_EXCEPTION_AT_END();
+        return result;
+    }
+}
+
+JSValue* Machine::cti_op_bitand(CTI_ARGS)
+{
+    JSValue* src1 = ARG_src1;
+    JSValue* src2 = ARG_src2;
+
+    ExecState* exec = ARG_exec;
+
+    int32_t left;
+    int32_t right;
+    if (fastToInt32(src1, left) && fastToInt32(src2, right))
+        return jsNumber(exec, left & right);
+    else {
+        JSValue* result = jsNumber(exec, src1->toInt32(exec) & src2->toInt32(exec));
+        VM_CHECK_EXCEPTION_AT_END();
+        return result;
+    }
+}
+
+JSValue* Machine::cti_op_rshift(CTI_ARGS)
+{
+    JSValue* val = ARG_src1;
+    JSValue* shift = ARG_src2;
+
+    ExecState* exec = ARG_exec;
+
+    int32_t left;
+    uint32_t right;
+    if (JSImmediate::areBothImmediateNumbers(val, shift))
+        return JSImmediate::rightShiftImmediateNumbers(val, shift);
+    else if (fastToInt32(val, left) && fastToUInt32(shift, right))
+        return jsNumber(exec, left >> (right & 0x1f));
+    else {
+        JSValue* result = jsNumber(exec, (val->toInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
+        VM_CHECK_EXCEPTION_AT_END();
+        return result;
+    }
+}
+
+JSValue* Machine::cti_op_bitnot(CTI_ARGS)
+{
+    JSValue* src = ARG_src1;
+
+    ExecState* exec = ARG_exec;
+
+    int value;
+    if (fastToInt32(src, value))
+        return jsNumber(exec, ~value);
+            
+    JSValue* result = jsNumber(exec, ~src->toInt32(exec));
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+JSValue* Machine::cti_op_resolve_with_base(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    ScopeChainNode* scopeChain = ARG_scopeChain;
+
+    ScopeChainIterator iter = scopeChain->begin();
+    ScopeChainIterator end = scopeChain->end();
+
+    // FIXME: add scopeDepthIsZero optimization
+
+    ASSERT(iter != end);
+
+    Identifier& ident = *ARG_id1;
+    JSObject* base;
+    do {
+        base = *iter;
+        PropertySlot slot(base);
+        if (base->getPropertySlot(exec, ident, slot)) {
+            JSValue* result = slot.getValue(exec, ident);
+            VM_CHECK_EXCEPTION_AT_END();
+            ARG_set2ndResult(result);
+            return base;
+        }
+        ++iter;
+    } while (iter != end);
+
+    CodeBlock* codeBlock = ARG_codeBlock;
+    ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
+    unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
+    exec->setException(createUndefinedVariableError(exec, ident, codeBlock->instructions.begin() + vPCIndex, codeBlock));
+
+    VM_CHECK_EXCEPTION_AT_END();
+    return 0;
+}
+
+JSValue* Machine::cti_op_new_func_exp(CTI_ARGS)
+{
+    return ARG_funcexp1->makeFunction(ARG_exec, ARG_scopeChain);
+}
+
+JSValue* Machine::cti_op_mod(CTI_ARGS)
+{
+    JSValue* dividendValue = ARG_src1;
+    JSValue* divisorValue = ARG_src2;
+
+    ExecState* exec = ARG_exec;
+    double d = dividendValue->toNumber(exec);
+    JSValue* result = jsNumber(exec, fmod(d, divisorValue->toNumber(exec)));
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+JSValue* Machine::cti_op_less(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    JSValue* result = jsBoolean(jsLess(exec, ARG_src1, ARG_src2));
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+JSValue* Machine::cti_op_neq(CTI_ARGS)
+{
+    JSValue* src1 = ARG_src1;
+    JSValue* src2 = ARG_src2;
+
+    if (JSImmediate::areBothImmediateNumbers(src1, src2))
+        return jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
+    else {
+        ExecState* exec = ARG_exec;
+        JSValue* result = jsBoolean(!equal(exec, src1, src2));
+        VM_CHECK_EXCEPTION_AT_END();
+        return result;
+    }
+}
+
+JSValue* Machine::cti_op_post_dec(CTI_ARGS)
+{
+    JSValue* v = ARG_src1;
+
+    ExecState* exec = ARG_exec;
+
+    JSValue* number = v->toJSNumber(exec);
+    VM_CHECK_EXCEPTION(JSValue*);
+
+    ARG_set2ndResult(jsNumber(exec, number->uncheckedGetNumber() - 1));
+    return number;
+}
+
+JSValue* Machine::cti_op_urshift(CTI_ARGS)
+{
+    JSValue* val = ARG_src1;
+    JSValue* shift = ARG_src2;
+
+    ExecState* exec = ARG_exec;
+
+    if (JSImmediate::areBothImmediateNumbers(val, shift) && !JSImmediate::isNegative(val))
+        return JSImmediate::rightShiftImmediateNumbers(val, shift);
+    else {
+        JSValue* result = jsNumber(exec, (val->toUInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
+        VM_CHECK_EXCEPTION_AT_END();
+        return result;
+    }
+}
+
+JSValue* Machine::cti_op_bitxor(CTI_ARGS)
+{
+    JSValue* src1 = ARG_src1;
+    JSValue* src2 = ARG_src2;
+
+    ExecState* exec = ARG_exec;
+
+    JSValue* result = jsNumber(exec, src1->toInt32(exec) ^ src2->toInt32(exec));
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+JSValue* Machine::cti_op_new_regexp(CTI_ARGS)
+{
+    return new (ARG_exec) RegExpObject(ARG_scopeChain->globalObject()->regExpPrototype(), ARG_regexp1);
+}
+
+JSValue* Machine::cti_op_bitor(CTI_ARGS)
+{
+    JSValue* src1 = ARG_src1;
+    JSValue* src2 = ARG_src2;
+
+    ExecState* exec = ARG_exec;
+
+    JSValue* result = jsNumber(exec, src1->toInt32(exec) | src2->toInt32(exec));
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+JSValue* Machine::cti_op_call_eval(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    RegisterFile* registerFile = ARG_registerFile;
+    Register* r = ARG_r;
+    CodeBlock* codeBlock = ARG_codeBlock;
+    ScopeChainNode* scopeChain = ARG_scopeChain;
+
+    Machine* machine = exec->machine();
+    JSValue* exceptionValue = 0;
+    
+    JSValue* funcVal = ARG_src1;
+    JSValue* baseVal = ARG_src2;
+    int firstArg = ARG_int3;
+    int argCount = ARG_int4;
+
+    if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) {
+        JSObject* thisObject = static_cast<JSObject*>(r[codeBlock->thisRegister].jsValue(exec));
+        JSValue* result = machine->callEval(exec, thisObject, scopeChain, registerFile,  r, firstArg, argCount, exceptionValue);
+        JSVALUE_VM_CHECK_EXCEPTION_ARG(exceptionValue);
+        return result;
+    }
+
+    return JSImmediate::impossibleValue();
+}
+
+void* Machine::cti_op_throw(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    CodeBlock* codeBlock = ARG_codeBlock;
+    ScopeChainNode* scopeChain = ARG_scopeChain;
+    Register* r = ARG_r;
+
+    ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
+    unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
+
+    JSValue* exceptionValue = ARG_src1;
+    Instruction* handlerVPC = ARG_exec->machine()->throwException(exec, exceptionValue, codeBlock->instructions.begin() + vPCIndex, codeBlock, scopeChain, r, true);
+
+    if (handlerVPC) {
+        exec->setException(exceptionValue);
+        ARG_setScopeChain(scopeChain);
+        ARG_setCodeBlock(codeBlock);
+        ARG_setR(r);
+
+        void* catchRoutine = codeBlock->nativeExceptionCodeForHandlerVPC(handlerVPC);
+        ASSERT(catchRoutine);
+        ctiSetReturnAddress(&CTI_RETURN_ADDRESS, catchRoutine);
+        return catchRoutine;
+    } else {
+        exec->clearException();
+        *ARG_exception = exceptionValue;
+        return JSImmediate::nullImmediate();
+    }
+}
+
+JSPropertyNameIterator* Machine::cti_op_get_pnames(CTI_ARGS)
+{
+    return JSPropertyNameIterator::create(ARG_exec, ARG_src1);
+}
+
+JSValue* Machine::cti_op_next_pname(CTI_ARGS)
+{
+    JSPropertyNameIterator* it = ARG_pni1;
+    JSValue* temp = it->next(ARG_exec);
+    if (!temp)
+        it->invalidate();
+    return temp;
+}
+
+void Machine::cti_op_push_scope(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+
+    JSValue* v = ARG_src1;
+    JSObject* o = v->toObject(exec);
+    VM_CHECK_EXCEPTION_v();
+
+    ScopeChainNode* newScopeChain = ARG_scopeChain->push(o);
+    ARG_setScopeChain(newScopeChain);
+    exec->m_scopeChain = newScopeChain;
+}
+
+void Machine::cti_op_pop_scope(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+
+    ScopeChainNode* newScopeChain = ARG_scopeChain->pop();
+    ARG_setScopeChain(newScopeChain);
+    exec->m_scopeChain = newScopeChain;
+}
+
+JSValue* Machine::cti_op_typeof(CTI_ARGS)
+{
+    return jsTypeStringForValue(ARG_exec, ARG_src1);
+}
+
+JSValue* Machine::cti_op_stricteq(CTI_ARGS)
+{
+    JSValue* src1 = ARG_src1;
+    JSValue* src2 = ARG_src2;
+
+    if (JSImmediate::areBothImmediateNumbers(src1, src2))
+        return jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
+    else {
+        ExecState* exec = ARG_exec;
+        JSValue* result = jsBoolean(strictEqual(src1, src2));
+        VM_CHECK_EXCEPTION_AT_END();
+        return result;
+    }
+}
+
+JSValue* Machine::cti_op_nstricteq(CTI_ARGS)
+{
+    JSValue* src1 = ARG_src1;
+    JSValue* src2 = ARG_src2;
+
+    if (JSImmediate::areBothImmediateNumbers(src1, src2))
+        return jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
+    else {
+        ExecState* exec = ARG_exec;
+        JSValue* result = jsBoolean(!strictEqual(src1, src2));
+        VM_CHECK_EXCEPTION_AT_END();
+        return result;
+    }
+}
+
+JSValue* Machine::cti_op_to_jsnumber(CTI_ARGS)
+{
+    JSValue* src = ARG_src1;
+    ExecState* exec = ARG_exec;
+
+    JSValue* result = src->toJSNumber(exec);
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+JSValue* Machine::cti_op_in(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    JSValue* baseVal = ARG_src2;
+
+    if (!baseVal->isObject()) {
+        CodeBlock* codeBlock = ARG_codeBlock;
+        ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
+        unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
+        exec->setException(createInvalidParamError(exec, "in", baseVal, codeBlock->instructions.begin() + vPCIndex, codeBlock));
+        VM_CHECK_EXCEPTION(JSValue*);
+    }
+
+    JSValue* propName = ARG_src1;
+    JSObject* baseObj = static_cast<JSObject*>(baseVal);
+
+    uint32_t i;
+    if (propName->getUInt32(i))
+        return jsBoolean(baseObj->hasProperty(exec, i));
+
+    Identifier property(exec, propName->toString(exec));
+    VM_CHECK_EXCEPTION(JSValue*);
+    return jsBoolean(baseObj->hasProperty(exec, property));
+}
+
+JSValue* Machine::cti_op_push_new_scope(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    JSObject* scope = new (exec) JSStaticScopeObject(exec, *ARG_id1, ARG_src2, DontDelete);
+
+    ScopeChainNode* newScopeChain = ARG_scopeChain->push(scope);
+    ARG_setScopeChain(newScopeChain);
+    exec->m_scopeChain = newScopeChain;
+
+    return scope;
+}
+
+void Machine::cti_op_jmp_scopes(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    unsigned count = ARG_int1;
+
+    ScopeChainNode* tmp = ARG_scopeChain;
+    while (count--)
+        tmp = tmp->pop();
+
+    ARG_setScopeChain(tmp);
+    exec->m_scopeChain = tmp;
+}
+
+void Machine::cti_op_put_by_index(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    unsigned property = ARG_int2;
+
+    ARG_src1->put(exec, property, ARG_src3);
+}
+
+void* Machine::cti_op_switch_imm(CTI_ARGS)
+{
+    JSValue* scrutinee = ARG_src1;
+    unsigned tableIndex = ARG_int2;
+
+    CodeBlock* codeBlock = ARG_codeBlock;
+
+    if (JSImmediate::isNumber(scrutinee)) {
+        int32_t value = JSImmediate::getTruncatedInt32(scrutinee);
+        return codeBlock->immediateSwitchJumpTables[tableIndex].ctiForValue(value);
+    }
+
+    return codeBlock->immediateSwitchJumpTables[tableIndex].ctiDefault;
+}
+
+void* Machine::cti_op_switch_char(CTI_ARGS)
+{
+    JSValue* scrutinee = ARG_src1;
+    unsigned tableIndex = ARG_int2;
+
+    CodeBlock* codeBlock = ARG_codeBlock;
+
+    void* result = codeBlock->characterSwitchJumpTables[tableIndex].ctiDefault;
+
+    if (scrutinee->isString()) {
+        UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
+        if (value->size() == 1)
+            result = codeBlock->characterSwitchJumpTables[tableIndex].ctiForValue(value->data()[0]);
+    }
+
+    return result;
+}
+
+void* Machine::cti_op_switch_string(CTI_ARGS)
+{
+    JSValue* scrutinee = ARG_src1;
+    unsigned tableIndex = ARG_int2;
+
+    CodeBlock* codeBlock = ARG_codeBlock;
+
+    void* result = codeBlock->stringSwitchJumpTables[tableIndex].ctiDefault;
+
+    if (scrutinee->isString()) {
+        UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
+        result = codeBlock->stringSwitchJumpTables[tableIndex].ctiForValue(value);
+    }
+
+    return result;
+}
+
+JSValue* Machine::cti_op_del_by_val(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+
+    JSValue* baseValue = ARG_src1;
+    JSObject* baseObj = baseValue->toObject(exec); // may throw
+
+    JSValue* subscript = ARG_src2;
+    JSValue* result;
+    uint32_t i;
+    if (subscript->getUInt32(i))
+        result = jsBoolean(baseObj->deleteProperty(exec, i));
+    else {
+        VM_CHECK_EXCEPTION(JSValue*);
+        Identifier property(exec, subscript->toString(exec));
+        VM_CHECK_EXCEPTION(JSValue*);
+        result = jsBoolean(baseObj->deleteProperty(exec, property));
+    }
+
+    VM_CHECK_EXCEPTION_AT_END();
+    return result;
+}
+
+void Machine::cti_op_put_getter(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+
+    ASSERT(ARG_src1->isObject());
+    JSObject* baseObj = static_cast<JSObject*>(ARG_src1);
+    Identifier& ident = *ARG_id2;
+    ASSERT(ARG_src3->isObject());
+    baseObj->defineGetter(exec, ident, static_cast<JSObject*>(ARG_src3));
+}
+
+void Machine::cti_op_put_setter(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+
+    ASSERT(ARG_src1->isObject());
+    JSObject* baseObj = static_cast<JSObject*>(ARG_src1);
+    Identifier& ident = *ARG_id2;
+    ASSERT(ARG_src3->isObject());
+    baseObj->defineSetter(exec, ident, static_cast<JSObject*>(ARG_src3));
+}
+
+JSValue* Machine::cti_op_new_error(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    CodeBlock* codeBlock = ARG_codeBlock;
+    unsigned type = ARG_int1;
+    JSValue* message = ARG_src2;
+    unsigned lineNumber = ARG_int3;
+
+    return Error::create(exec, static_cast<ErrorType>(type), message->toString(exec), lineNumber, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->sourceURL());
+}
+
+void Machine::cti_op_debug(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    CodeBlock* codeBlock = ARG_codeBlock;
+    ScopeChainNode* scopeChain = ARG_scopeChain;
+    Register* r = ARG_r;
+
+    int debugHookID = ARG_int1;
+    int firstLine = ARG_int2;
+    int lastLine = ARG_int3;
+
+    exec->machine()->debug(exec, codeBlock, scopeChain, r, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
+}
+
+JSValue* Machine::cti_op_eq_null(CTI_ARGS)
+{
+    JSValue* src = ARG_src1;
+    if (src->isUndefinedOrNull())
+        return jsBoolean(true);
+
+    return jsBoolean(!JSImmediate::isImmediate(src) && static_cast<JSCell*>(src)->masqueradeAsUndefined());
+}
+
+JSValue* Machine::cti_op_neq_null(CTI_ARGS)
+{
+    JSValue* src = ARG_src1;
+    if (src->isUndefinedOrNull())
+        return jsBoolean(false);
+
+    return jsBoolean(JSImmediate::isImmediate(src) || !static_cast<JSCell*>(src)->masqueradeAsUndefined());
+}
+
+void* Machine::cti_vm_throw(CTI_ARGS)
+{
+    ExecState* exec = ARG_exec;
+    CodeBlock* codeBlock = ARG_codeBlock;
+    ScopeChainNode* scopeChain = ARG_scopeChain;
+    Register* r = ARG_r;
+
+    ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(exec->ctiReturnAddress()));
+    unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(exec->ctiReturnAddress());
+
+    ASSERT(exec->hadException());
+
+    JSValue* exceptionValue = exec->exception();
+
+    Instruction* handlerVPC = ARG_exec->machine()->throwException(exec, exceptionValue, codeBlock->instructions.begin() + vPCIndex, codeBlock, scopeChain, r, false);
+
+    if (handlerVPC) {
+        exec->setException(exceptionValue);
+        ARG_setScopeChain(scopeChain);
+        ARG_setCodeBlock(codeBlock);
+        ARG_setR(r);
+
+        void* catchRoutine = codeBlock->nativeExceptionCodeForHandlerVPC(handlerVPC);
+        ASSERT(catchRoutine);
+        ctiSetReturnAddress(&CTI_RETURN_ADDRESS, catchRoutine);
+        return catchRoutine;
+    } else {
+        exec->clearException();
+        *ARG_exception = exceptionValue;
+        return JSImmediate::nullImmediate();
+    }
+}
+
+#undef VM_CHECK_EXCEPTION
+#undef VM_CHECK_EXCEPTION_v
+#undef VM_CHECK_EXCEPTION_AT_END
+
+#endif // ENABLE(CTI)
+
 } // namespace KJS
index 27cad69..f21a876 100644 (file)
 #include "RegisterFile.h"
 #include <wtf/HashMap.h>
 
+#if ENABLE(CTI)
+#include "CTI.h"
+#endif
+
 namespace KJS {
 
     class CodeBlock;
@@ -63,8 +67,11 @@ namespace KJS {
     enum { MaxReentryDepth = 128 };
 
     class Machine {
+        friend class CTI;
+        friend class WRECompiler;
     public:
         Machine();
+        ~Machine();
         
         RegisterFile& registerFile() { return m_registerFile; }
         
@@ -125,6 +132,100 @@ namespace KJS {
 
         SamplingTool* m_sampler;
 
+#if ENABLE(CTI)
+#if COMPILER(MSVC)
+#define SFX_CALL __cdecl
+#else
+#define SFX_CALL
+#endif
+
+        static void SFX_CALL cti_timeout_check(CTI_ARGS);
+
+        static void SFX_CALL cti_op_end(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_add(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_pre_inc(CTI_ARGS);
+        static int SFX_CALL cti_op_loop_if_less(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_new_object(CTI_ARGS);
+        static void SFX_CALL cti_op_put_by_id(CTI_ARGS);
+        static void SFX_CALL cti_op_put_by_id_second(CTI_ARGS);
+        static void SFX_CALL cti_op_put_by_id_generic(CTI_ARGS);
+        static void SFX_CALL cti_op_put_by_id_fail(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_get_by_id(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_get_by_id_second(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_get_by_id_generic(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_get_by_id_fail(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_del_by_id(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_instanceof(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_mul(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_new_func(CTI_ARGS);
+        static void* SFX_CALL cti_op_call_JSFunction(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_call_NotJSFunction(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_ret(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_new_array(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_resolve(CTI_ARGS);
+        static void* SFX_CALL cti_op_construct_JSConstruct(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_construct_NotJSConstruct(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_get_by_val(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_resolve_func(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_sub(CTI_ARGS);
+        static void SFX_CALL cti_op_put_by_val(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_lesseq(CTI_ARGS);
+        static int SFX_CALL cti_op_loop_if_true(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_resolve_base(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_negate(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_resolve_skip(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_div(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_pre_dec(CTI_ARGS);
+        static int SFX_CALL cti_op_jless(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_not(CTI_ARGS);
+        static int SFX_CALL cti_op_jtrue(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_post_inc(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_eq(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_lshift(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_bitand(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_rshift(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_bitnot(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_resolve_with_base(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_new_func_exp(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_mod(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_less(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_neq(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_post_dec(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_urshift(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_bitxor(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_new_regexp(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_bitor(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_call_eval(CTI_ARGS);
+        static void* SFX_CALL cti_op_throw(CTI_ARGS);
+        static JSPropertyNameIterator* SFX_CALL cti_op_get_pnames(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_next_pname(CTI_ARGS);
+        static void SFX_CALL cti_op_push_scope(CTI_ARGS);
+        static void SFX_CALL cti_op_pop_scope(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_typeof(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_stricteq(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_nstricteq(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_to_jsnumber(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_in(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_push_new_scope(CTI_ARGS);
+        static void SFX_CALL cti_op_jmp_scopes(CTI_ARGS);
+        static void SFX_CALL cti_op_put_by_index(CTI_ARGS);
+        static void* SFX_CALL cti_op_switch_imm(CTI_ARGS);
+        static void* SFX_CALL cti_op_switch_char(CTI_ARGS);
+        static void* SFX_CALL cti_op_switch_string(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_del_by_val(CTI_ARGS);
+        static void SFX_CALL cti_op_put_getter(CTI_ARGS);
+        static void SFX_CALL cti_op_put_setter(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_new_error(CTI_ARGS);
+        static void SFX_CALL cti_op_debug(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_eq_null(CTI_ARGS);
+        static JSValue* SFX_CALL cti_op_neq_null(CTI_ARGS);
+
+        static void* SFX_CALL cti_vm_throw(CTI_ARGS);
+#endif // ENABLE(CTI)
+
+        // Default number of ticks before a timeout check should be done.
+        static const int initialTickCountThreshold = 1024;
+
     private:
         enum ExecutionFlag { Normal, InitializeAndReturn };
 
@@ -134,7 +235,7 @@ namespace KJS {
         ALWAYS_INLINE void initializeCallFrame(Register* callFrame, CodeBlock*, Instruction*, ScopeChainNode*, Register* r, int returnValueRegister, int argv, int argc, int calledAsConstructor, JSValue* function);
 
         ALWAYS_INLINE void setScopeChain(ExecState* exec, ScopeChainNode*&, ScopeChainNode*);
-        NEVER_INLINE void debug(ExecState*, const Instruction*, const CodeBlock*, ScopeChainNode*, Register*);
+        NEVER_INLINE void debug(ExecState*, const CodeBlock*, ScopeChainNode*, Register*, DebugHookID, int firstLine, int lastLine);
 
         NEVER_INLINE bool unwindCallFrame(ExecState*, JSValue*, const Instruction*&, CodeBlock*&, ScopeChainNode*&, Register*&);
         NEVER_INLINE Instruction* throwException(ExecState*, JSValue*&, const Instruction*, CodeBlock*&, ScopeChainNode*&, Register*&, bool);
@@ -156,7 +257,21 @@ namespace KJS {
         void uncacheGetByID(CodeBlock*, Instruction* vPC);
         void tryCachePutByID(CodeBlock*, Instruction* vPC, JSValue* baseValue, const PutPropertySlot&);
         void uncachePutByID(CodeBlock*, Instruction* vPC);
-        
+
+#if ENABLE(CTI)
+        void tryCTICacheGetByID(ExecState*, CodeBlock*, void* returnAddress, JSValue* baseValue, const Identifier& propertyName, const PropertySlot&);
+        void tryCTICachePutByID(ExecState*, CodeBlock*, void* returnAddress, JSValue* baseValue, const PutPropertySlot&);
+
+        void* getCTIArrayLengthTrampoline(ExecState*, CodeBlock*);
+        void* getCTIStringLengthTrampoline(ExecState*, CodeBlock*);
+
+        void* m_ctiArrayLengthTrampoline;
+        void* m_ctiStringLengthTrampoline;
+
+        OwnPtr<JITCodeBuffer> m_jitCodeBuffer;
+        JITCodeBuffer* jitCodeBuffer() const { return m_jitCodeBuffer.get(); }
+#endif
+
         int m_reentryDepth;
         unsigned m_timeoutTime;
         unsigned m_timeAtLastCheckTimeout;
@@ -168,6 +283,7 @@ namespace KJS {
         
         void* m_jsArrayVptr;
         void* m_jsStringVptr;
+        void* m_jsFunctionVptr;
 
 #if HAVE(COMPUTED_GOTO)
         Opcode m_opcodeTable[numOpcodeIDs]; // Maps OpcodeID => Opcode for compiling
index 3512219..750b9b2 100644 (file)
@@ -65,6 +65,7 @@ namespace KJS {
         Register(Register*);
         Register(Instruction*);
         Register(JSPropertyNameIterator*);
+        explicit Register(void*);
 
         CodeBlock* codeBlock() const;
         ScopeChainNode* scopeChain() const;
@@ -99,6 +100,12 @@ namespace KJS {
             IntType
         } m_type;
 #endif
+
+// FIXME: The commented out ASSERTs below are valid; NDEBUG CTI should set these when up to date.
+//        static inline ptrdiff_t offsetOf_type()
+//        {
+//            return OBJECT_OFFSET(Register, m_type);
+//        }
     };
 
     ALWAYS_INLINE Register::Register()
@@ -121,13 +128,13 @@ namespace KJS {
     {
         // Once registers hold doubles, this function will allocate a JSValue*
         // if the register doesn't hold one already. 
-        ASSERT(m_type == JSValueType);
+//        ASSERT(m_type == JSValueType);
         return u.jsValue;
     }
     
     ALWAYS_INLINE JSValue* Register::getJSValue() const
     {
-        ASSERT(m_type == JSValueType);
+//        ASSERT(m_type == JSValueType);
         return u.jsValue;
     }
     
@@ -191,39 +198,44 @@ namespace KJS {
         u.i = i;
     }
 
+    ALWAYS_INLINE Register::Register(void* v)
+    {
+        u.v = v;
+    }
+
     ALWAYS_INLINE CodeBlock* Register::codeBlock() const
     {
-        ASSERT(m_type == CodeBlockType);
+//        ASSERT(m_type == CodeBlockType);
         return u.codeBlock;
     }
     
     ALWAYS_INLINE ScopeChainNode* Register::scopeChain() const
     {
-        ASSERT(m_type == ScopeChainNodeType);
+//        ASSERT(m_type == ScopeChainNodeType);
         return u.scopeChain;
     }
     
     ALWAYS_INLINE intptr_t Register::i() const
     {
-        ASSERT(m_type == IntType);
+//        ASSERT(m_type == IntType);
         return u.i;
     }
     
     ALWAYS_INLINE Register* Register::r() const
     {
-        ASSERT(m_type == RegisterType);
+//        ASSERT(m_type == RegisterType);
         return u.r;
     }
     
     ALWAYS_INLINE Instruction* Register::vPC() const
     {
-        ASSERT(m_type == InstructionType);
+//        ASSERT(m_type == InstructionType);
         return u.vPC;
     }
     
     ALWAYS_INLINE JSPropertyNameIterator* Register::jsPropertyNameIterator() const
     {
-        ASSERT(m_type == JSPropertyNameIteratorType);
+//        ASSERT(m_type == JSPropertyNameIteratorType);
         return u.jsPropertyNameIterator;
     }
     
index cbf61db..3a43816 100644 (file)
@@ -89,7 +89,7 @@ namespace KJS {
 
     class RegisterFile : Noncopyable {
     public:
-        enum {
+        enum CallFrameHeaderEntry {
             CallerCodeBlock = 0,
             ReturnVPC,
             CallerScopeChain,
@@ -100,6 +100,7 @@ namespace KJS {
             CalledAsConstructor,
             Callee,
             OptionalCalleeActivation,
+            CTIReturnEIP,
             CallFrameHeaderSize
         };
 
index 0eb0c26..8b26614 100644 (file)
@@ -79,13 +79,29 @@ static inline unsigned hertz2us(unsigned hertz)
     return 1000000 / hertz;
 }
 
+#if ENABLE(SAMPLING_TOOL)
+extern OpcodeID what;
+extern unsigned incall;
+unsigned cowdogs = 0;
+unsigned sampleCows[numOpcodeIDs] = {0};
+unsigned sampleDogs[numOpcodeIDs] = {0};
+#endif
+
 void SamplingTool::run()
 {
     while (m_running) {
         sleepForMicroseconds(hertz2us(m_hertz));
 
         m_totalSamples++;
-
+#if ENABLE(SAMPLING_TOOL)
+        if (what != (OpcodeID)-1) {
+            ++cowdogs;
+            if (incall)
+                sampleDogs[what]++;
+            else
+                sampleCows[what]++;
+        }
+#endif        
         CodeBlock* codeBlock = m_recordedCodeBlock;
         Instruction* vPC = m_recordedVPC;
 
@@ -129,6 +145,7 @@ struct OpcodeSampleInfo
 {
     OpcodeID opcode;
     long long count;
+    long long countincall;
 };
 
 struct LineCountInfo
@@ -250,7 +267,8 @@ void SamplingTool::dump(ExecState* exec)
     OpcodeSampleInfo opcodeSampleInfo[numOpcodeIDs];
     for (int i = 0; i < numOpcodeIDs; ++i) {
         opcodeSampleInfo[i].opcode = (OpcodeID)i;
-        opcodeSampleInfo[i].count = opcodeSampleCounts[i];
+        opcodeSampleInfo[i].count = sampleCows[i]+sampleDogs[i];
+        opcodeSampleInfo[i].countincall = sampleDogs[i];
     }
 #if HAVE(MERGESORT)
     mergesort(opcodeSampleInfo, numOpcodeIDs, sizeof(OpcodeSampleInfo), compareOpcodeIndicesSampling);
@@ -259,21 +277,25 @@ void SamplingTool::dump(ExecState* exec)
 #endif
 
     // (4) Print Opcode sampling results.
-    
+
+
     printf("\nOpcode sampling results\n\n"); 
     
-    printf("Total opcodes sampled (total samples): %lld (%lld)\n\n", totalOpcodeSamples, m_totalSamples);
-    printf("Opcodes in order:\n\n");
-    for (int i = 0; i < numOpcodeIDs; ++i) {
-        long long count = opcodeSampleCounts[i];
-        printf("%s:%s%6lld\t%.3f%%\t(%.3f%%)\n", opcodeNames[i], padOpcodeName(static_cast<OpcodeID>(i), 20), count, (static_cast<double>(count) * 100) / totalOpcodeSamples, (static_cast<double>(count) * 100) / m_totalSamples);    
-    }
-    printf("\n");
-    printf("Opcodes by sample count:\n\n");
+//    printf("Total opcodes sampled (total samples): %lld (%lld)\n\n", totalOpcodeSamples, m_totalSamples);
+//    printf("Opcodes in order:\n\n");
+//    for (int i = 0; i < numOpcodeIDs; ++i) {
+//        long long count = opcodeSampleCounts[i];
+//        printf("%s:%s%6lld\t%.3f%%\t(%.3f%%)\n", opcodeNames[i], padOpcodeName(static_cast<OpcodeID>(i), 20), count, (static_cast<double>(count) * 100) / totalOpcodeSamples, (static_cast<double>(count) * 100) / m_totalSamples);    
+//    }
+//    printf("\n");
+//    printf("Opcodes by sample count:\n\n");
+
     for (int i = 0; i < numOpcodeIDs; ++i) {
         OpcodeID opcode = opcodeSampleInfo[i].opcode;
         long long count = opcodeSampleInfo[i].count;
-        printf("%s:%s%6lld\t%.3f%%\t(%.3f%%)\n", opcodeNames[opcode], padOpcodeName(opcode, 20), count, (static_cast<double>(count) * 100) / totalOpcodeSamples, (static_cast<double>(count) * 100) / m_totalSamples);    
+//        printf("%s:%s%6lld\t%.3f%%\t(%.3f%%)\n", opcodeNames[opcode], padOpcodeName(opcode, 20), count, (static_cast<double>(count) * 100) / totalOpcodeSamples, (static_cast<double>(count) * 100) / m_totalSamples);    
+        long long countincall = opcodeSampleInfo[i].countincall;
+        fprintf(stdout, "%s:%s%6lld\t%6lld\t%.3f%%\t%.3f%%\t(%.3f%%)\n", opcodeNames[opcode], padOpcodeName(opcode, 20), count, countincall, ((double)count * 100)/cowdogs, ((double)count * 100)/m_totalSamples, ((double)countincall * 100)/m_totalSamples);    
     }
     printf("\n");
 }
index fad19c4..3505d1a 100644 (file)
@@ -43,6 +43,10 @@ namespace KJS {
     class CodeBlock;
     struct Instruction;
 
+#if ENABLE(SAMPLING_TOOL)
+extern OpcodeID what;
+#endif
+
     struct ScopeSampleRecord {
         RefPtr<ScopeNode> m_scope;
         CodeBlock* m_codeBlock;
@@ -108,6 +112,9 @@ namespace KJS {
         {
             m_recordedCodeBlock = 0;
             m_recordedVPC = 0;
+#if ENABLE(SAMPLING_TOOL)
+            what=(OpcodeID)-1;
+#endif
         }
         
     private:
@@ -134,11 +141,13 @@ namespace KJS {
 #define MACHINE_SAMPLING_sample(codeBlock, vPC) m_sampler->sample(codeBlock, vPC)
 #define MACHINE_SAMPLING_privateExecuteReturned() m_sampler->privateExecuteReturned()
 #define MACHINE_SAMPLING_callingHostFunction() m_sampler->callingHostFunction()
+#define CTI_MACHINE_SAMPLING_callingHostFunction() machine->m_sampler->callingHostFunction()
 #else
 #define SCOPENODE_SAMPLING_notifyOfScope(sampler)
 #define MACHINE_SAMPLING_sample(codeBlock, vPC)
 #define MACHINE_SAMPLING_privateExecuteReturned()
 #define MACHINE_SAMPLING_callingHostFunction()
+#define CTI_MACHINE_SAMPLING_callingHostFunction()
 #endif
 
 } // namespace KJS
index 40f5bc4..bd4b263 100644 (file)
@@ -46,9 +46,11 @@ namespace KJS  {
     // Represents the current state of script execution.
     // Passed as the first argument to most functions.
     class ExecState : Noncopyable {
+#if ENABLE(CTI)
+        friend class CTI;
+#endif
         friend class Machine;
         friend class DebuggerCallFrame;
-
     public:
         ExecState(JSGlobalObject*, JSObject* globalThisValue, ScopeChainNode* globalScopeChain);
 
@@ -70,6 +72,10 @@ namespace KJS  {
         JSValue* exception() const { return m_exception; }
         JSValue** exceptionSlot() { return &m_exception; }
         bool hadException() const { return !!m_exception; }
+#if ENABLE(CTI)
+        void setCTIReturnAddress(void* ctiRA) { m_ctiReturnAddress = ctiRA; }
+        void* ctiReturnAddress() const { return m_ctiReturnAddress; }
+#endif
 
         JSGlobalData& globalData() { return *m_globalData; }
 
@@ -101,7 +107,9 @@ namespace KJS  {
         JSObject* m_globalThisValue;
 
         JSValue* m_exception;
-
+#if ENABLE(CTI)
+        void* m_ctiReturnAddress;
+#endif
         JSGlobalData* m_globalData;
 
         // These values are controlled by the machine.
index 9e0bc97..23c303d 100644 (file)
@@ -39,6 +39,7 @@ namespace KJS {
         const UString& name(ExecState*);
 
     protected:
+        InternalFunction(PassRefPtr<KJS::StructureID> st) : JSObject(st){}
         InternalFunction(ExecState*);
         InternalFunction(ExecState*, FunctionPrototype*, const Identifier&);
 
index b65092b..00d373a 100644 (file)
@@ -37,6 +37,8 @@ namespace KJS {
     };
 
     class JSArray : public JSObject {
+        friend class CTI;
+
     public:
         JSArray(PassRefPtr<StructureID>);
         JSArray(JSObject* prototype, unsigned initialLength);
index 3e61ad4..a5aed3e 100644 (file)
@@ -38,6 +38,7 @@ namespace KJS {
         friend class JSNumberCell;
         friend class JSString;
         friend class Machine;
+        friend class CTI;
     private:
         JSCell();
         JSCell(StructureID*);
index bd3ac78..f2cc6c1 100644 (file)
@@ -38,7 +38,10 @@ namespace KJS {
     class JSGlobalObject;
 
     class JSFunction : public InternalFunction {
+        friend class Machine;
+
         typedef InternalFunction Base;
+        JSFunction(PassRefPtr<KJS::StructureID> st) : InternalFunction(st), m_scopeChain(NoScopeChain()) {}
     public:
         JSFunction(ExecState*, const Identifier&, FunctionBodyNode*, ScopeChainNode*);
 
index 5283ded..e2e216d 100644 (file)
@@ -82,6 +82,8 @@ namespace KJS {
 
     class JSImmediate {
     private:
+        friend class CTI; // Whooo!
+    
         static const uintptr_t TagMask           = 0x3u; // primary tag is 2 bits long
         static const uintptr_t TagBitTypeInteger = 0x1u; // bottom bit set indicates integer, this dominates the following bit
         static const uintptr_t TagBitTypeOther   = 0x2u; // second bit set indicates immediate other than an integer
@@ -230,6 +232,8 @@ namespace KJS {
         static JSValue* falseImmediate();
         static JSValue* undefinedImmediate();
         static JSValue* nullImmediate();
+        static JSValue* zeroImmediate();
+        static JSValue* oneImmediate();
 
         static JSValue* impossibleValue();
         
@@ -285,6 +289,8 @@ namespace KJS {
     ALWAYS_INLINE JSValue* JSImmediate::falseImmediate() { return makeBool(false); }
     ALWAYS_INLINE JSValue* JSImmediate::undefinedImmediate() { return makeUndefined(); }
     ALWAYS_INLINE JSValue* JSImmediate::nullImmediate() { return makeNull(); }
+    ALWAYS_INLINE JSValue* JSImmediate::zeroImmediate() { return makeInt(0); }
+    ALWAYS_INLINE JSValue* JSImmediate::oneImmediate() { return makeInt(1); }
 
     // This value is impossible because 0x4 is not a valid pointer but a tag of 0 would indicate non-immediate
     ALWAYS_INLINE JSValue* JSImmediate::impossibleValue() { return reinterpret_cast<JSValue*>(0x4); }
index 1882224..a53a5ec 100644 (file)
@@ -54,6 +54,7 @@ namespace KJS {
 
     class JSObject : public JSCell {
         friend class BatchedTransitionOptimizer;
+        friend class CTI;
 
     public:
         JSObject(PassRefPtr<StructureID>);
index 83a6b35..180e094 100644 (file)
@@ -51,6 +51,8 @@ namespace KJS {
     JSString* jsOwnedString(ExecState*, const UString&); 
 
     class JSString : public JSCell {
+        friend class CTI;
+
     public:
         JSString(const UString& value)
             : m_value(value)
index e1f90bf..4c18380 100644 (file)
 #include "ustring.h"
 #include <stddef.h> // for size_t
 
+// The magic number 0x4000 is not important here, it is being subtracted back out (avoiding using zero since this
+// can have unexpected effects in this type of macro, particularly where multiple-inheritance is involved).
+#define OBJECT_OFFSET(class, member) (reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<class*>(0x4000)->member)) - 0x4000)
+
 namespace KJS {
 
     class ExecState;
index ccbf3fa..3519f30 100644 (file)
@@ -75,6 +75,11 @@ namespace KJS {
             OwnArrayPtr<Register> registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file.
             size_t registerArraySize;
 
+            static inline ptrdiff_t offsetOf_registers()
+            {
+                return OBJECT_OFFSET(JSVariableObjectData, registers);
+            }
+
         private:
             JSVariableObjectData(const JSVariableObjectData&);
             JSVariableObjectData& operator=(const JSVariableObjectData&);
@@ -101,6 +106,17 @@ namespace KJS {
         bool symbolTablePutWithAttributes(const Identifier&, JSValue*, unsigned attributes);
 
         JSVariableObjectData* d;
+
+    public:
+        static inline ptrdiff_t offsetOf_d()
+        {
+            return OBJECT_OFFSET(JSVariableObject, d);
+        }
+
+        static inline ptrdiff_t offsetOf_Data_registers()
+        {
+            return JSVariableObjectData::offsetOf_registers();
+        }
     };
 
     inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot)
index 201fa1c..1887746 100644 (file)
@@ -81,6 +81,8 @@ namespace KJS {
     };
 
     class PropertyMap : Noncopyable {
+        friend class CTI;
+
     public:
         PropertyMap();
         ~PropertyMap();
index b36efec..e54b676 100644 (file)
@@ -292,7 +292,7 @@ static JSObject* constructRegExp(ExecState* exec, const ArgList& args)
     UString pattern = arg0->isUndefined() ? UString("") : arg0->toString(exec);
     UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec);
 
-    RefPtr<RegExp> regExp = RegExp::create(pattern, flags);
+    RefPtr<RegExp> regExp = RegExp::create(exec, pattern, flags);
     if (!regExp->isValid())
         return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));
     return new (exec) RegExpObject(exec->lexicalGlobalObject()->regExpPrototype(), regExp.release());
index 38a6cff..5aa3c6f 100644 (file)
@@ -86,7 +86,7 @@ JSValue* regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue* thisValue,
     } else {
         UString pattern = args.isEmpty() ? UString("") : arg0->toString(exec);
         UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec);
-        regExp = RegExp::create(pattern, flags);
+        regExp = RegExp::create(exec, pattern, flags);
     }
 
     if (!regExp->isValid())
index e4d8ce3..71c01d3 100644 (file)
@@ -146,8 +146,15 @@ namespace KJS {
         return ScopeChainIterator(0); 
     }
 
+    class NoScopeChain {};
+
     class ScopeChain {
     public:
+        ScopeChain(NoScopeChain)
+            : m_node(0)
+        {
+        }
+
         ScopeChain(JSObject* o, JSObject* globalThis)
             : m_node(new ScopeChainNode(0, o, globalThis))
         {
@@ -164,8 +171,12 @@ namespace KJS {
             : m_node(node->copy())
         {
         }
-    
-        ~ScopeChain() { m_node->deref(); }
+
+        ~ScopeChain()
+        {
+            if (m_node)
+                m_node->deref();
+        }
 
         void swap(ScopeChain&);
 
index 6718115..581caae 100644 (file)
@@ -409,7 +409,7 @@ JSValue* stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue* thisValue, co
          *  If regexp is not an object whose [[Class]] property is "RegExp", it is
          *  replaced with the result of the expression new RegExp(regexp).
          */
-        reg = RegExp::create(a0->toString(exec));
+        reg = RegExp::create(exec, a0->toString(exec));
     }
     RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor();
     int pos;
@@ -459,7 +459,7 @@ JSValue* stringProtoFuncSearch(ExecState* exec, JSObject*, JSValue* thisValue, c
          *  If regexp is not an object whose [[Class]] property is "RegExp", it is
          *  replaced with the result of the expression new RegExp(regexp).
          */
-        reg = RegExp::create(a0->toString(exec));
+        reg = RegExp::create(exec, a0->toString(exec));
     }
     RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor();
     int pos;
index 6186004..798570a 100644 (file)
@@ -262,11 +262,12 @@ RegisterID* StringNode::emitCode(CodeGenerator& generator, RegisterID* dst)
 
 RegisterID* RegExpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
 {
-    if (!m_regExp->isValid())
-        return emitThrowError(generator, SyntaxError, ("Invalid regular expression: " + UString(m_regExp->errorMessage())).UTF8String().c_str());
+    RefPtr<RegExp> regExp = RegExp::create(generator.globalExec(), m_pattern, m_flags);
+    if (!regExp->isValid())
+        return emitThrowError(generator, SyntaxError, ("Invalid regular expression: " + UString(regExp->errorMessage())).UTF8String().c_str());
     if (dst == ignoredResult())
         return 0;
-    return generator.emitNewRegExp(generator.finalDestination(dst), m_regExp.get());
+    return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get());
 }
 
 // ------------------------------ ThisNode -------------------------------------
@@ -1629,11 +1630,17 @@ RegisterID* TryNode::emitCode(CodeGenerator& generator, RegisterID* dst)
         RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
         RefPtr<LabelID> finallyEndLabel = generator.newLabel();
         generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
+        // Use a label to record the subtle fact that sret will return to the
+        // next instruction. sret is the only way to jump without an explicit label.
+        generator.emitLabel(generator.newLabel().get());
         generator.emitJump(finallyEndLabel.get());
 
         // Finally block for exception path
         RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), generator.emitLabel(generator.newLabel().get()).get());
         generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
+        // Use a label to record the subtle fact that sret will return to the
+        // next instruction. sret is the only way to jump without an explicit label.
+        generator.emitLabel(generator.newLabel().get());
         generator.emitThrow(tempExceptionRegister.get());
 
         // emit the finally block itself
index 9e7cdfc..da56e33 100644 (file)
@@ -427,7 +427,8 @@ namespace KJS {
     public:
         RegExpNode(JSGlobalData* globalData, const UString& pattern, const UString& flags) KJS_FAST_CALL
             : ExpressionNode(globalData)
-            , m_regExp(RegExp::create(pattern, flags))
+            , m_pattern(pattern)
+            , m_flags(flags)
         {
         }
 
@@ -437,7 +438,8 @@ namespace KJS {
         virtual Precedence precedence() const { return PrecPrimary; }
 
     private:
-        RefPtr<RegExp> m_regExp;
+        UString m_pattern;
+        UString m_flags;
     };
 
     class ThisNode : public ExpressionNode {
index eafed5b..06e892a 100644 (file)
@@ -314,7 +314,7 @@ void StringNode::streamTo(SourceStream& s) const
 
 void RegExpNode::streamTo(SourceStream& s) const
 {
-    s << '/' <<  m_regExp->pattern() << '/' << m_regExp->flags();
+    s << '/' <<  m_pattern << '/' << m_flags;
 }
 
 void ThisNode::streamTo(SourceStream& s) const
index c44e300..f25e3c1 100644 (file)
@@ -21,6 +21,7 @@
 #include "config.h"
 #include "regexp.h"
 
+#include "CTI.h"
 #include "lexer.h"
 #include <pcre/pcre.h>
 #include <stdio.h>
 
 namespace KJS {
 
-inline RegExp::RegExp(const UString& pattern)
+
+
+inline RegExp::RegExp(ExecState* exec, const UString& pattern)
     : m_pattern(pattern)
     , m_flagBits(0)
+    , m_regExp(0)
     , m_constructionError(0)
     , m_numSubpatterns(0)
 {
-    m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(pattern.data()), pattern.size(),
-        JSRegExpDoNotIgnoreCase, JSRegExpSingleLine, &m_numSubpatterns, &m_constructionError);
+#if ENABLE(WREC)
+    if (!(m_wrecFunction = (WRECFunction)CTI::compileRegExp(exec, pattern, &m_numSubpatterns, &m_constructionError)))
+#else
+    UNUSED_PARAM(exec);
+#endif
+    {
+        m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(pattern.data()), pattern.size(),
+            JSRegExpDoNotIgnoreCase, JSRegExpSingleLine, &m_numSubpatterns, &m_constructionError);
+    }
 }
 
-PassRefPtr<RegExp> RegExp::create(const UString& pattern)
+PassRefPtr<RegExp> RegExp::create(ExecState* exec, const UString& pattern)
 {
-    return adoptRef(new RegExp(pattern));
+    return adoptRef(new RegExp(exec, pattern));
 }
 
-inline RegExp::RegExp(const UString& pattern, const UString& flags)
+inline RegExp::RegExp(ExecState* exec, const UString& pattern, const UString& flags)
     : m_pattern(pattern)
     , m_flags(flags)
     , m_flagBits(0)
+    , m_regExp(0)
     , m_constructionError(0)
     , m_numSubpatterns(0)
 {
@@ -71,18 +83,29 @@ inline RegExp::RegExp(const UString& pattern, const UString& flags)
         multilineOption = JSRegExpMultiline;
     }
 
-    m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(pattern.data()), pattern.size(),
-        ignoreCaseOption, multilineOption, &m_numSubpatterns, &m_constructionError);
+#if ENABLE(WREC)
+    if (!(m_wrecFunction = (WRECFunction)CTI::compileRegExp(exec, pattern, &m_numSubpatterns, &m_constructionError, (m_flagBits & IgnoreCase), (m_flagBits & Multiline))))
+#else
+    UNUSED_PARAM(exec);
+#endif
+    {
+        m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(pattern.data()), pattern.size(),
+            ignoreCaseOption, multilineOption, &m_numSubpatterns, &m_constructionError);
+    }
 }
 
-PassRefPtr<RegExp> RegExp::create(const UString& pattern, const UString& flags)
+PassRefPtr<RegExp> RegExp::create(ExecState* exec, const UString& pattern, const UString& flags)
 {
-    return adoptRef(new RegExp(pattern, flags));
+    return adoptRef(new RegExp(exec, pattern, flags));
 }
 
 RegExp::~RegExp()
 {
     jsRegExpFree(m_regExp);
+#if ENABLE(WREC)
+    if (m_wrecFunction)
+        fastFree(reinterpret_cast<void*>(m_wrecFunction));
+#endif
 }
 
 int RegExp::match(const UString& s, int i, OwnArrayPtr<int>* ovector)
@@ -95,36 +118,64 @@ int RegExp::match(const UString& s, int i, OwnArrayPtr<int>* ovector)
     if (i > s.size() || s.isNull())
         return -1;
 
-    if (!m_regExp)
-        return -1;
+#if ENABLE(WREC)
+    if (m_wrecFunction) {
+        int offsetVectorSize = (m_numSubpatterns + 1) * 2;
+        int* offsetVector = new int [offsetVectorSize];
+        for (int j = 0; j < offsetVectorSize; ++j)
+            offsetVector[j] = -1;
 
-    // Set up the offset vector for the result.
-    // First 2/3 used for result, the last third used by PCRE.
-    int* offsetVector;
-    int offsetVectorSize;
-    int fixedSizeOffsetVector[3];
-    if (!ovector) {
-        offsetVectorSize = 3;
-        offsetVector = fixedSizeOffsetVector;
-    } else {
-        offsetVectorSize = (m_numSubpatterns + 1) * 3;
-        offsetVector = new int [offsetVectorSize];
-        ovector->set(offsetVector);
-    }
+        OwnArrayPtr<int> nonReturnedOvector;
+        if (!ovector)
+            nonReturnedOvector.set(offsetVector);
+        else
+            ovector->set(offsetVector);
 
-    int numMatches = jsRegExpExecute(m_regExp, reinterpret_cast<const UChar*>(s.data()), s.size(), i, offsetVector, offsetVectorSize);
+        int result = m_wrecFunction(s.data(), i, s.size(), offsetVector);
 
-    if (numMatches < 0) {
+        if (result < 0) {
 #ifndef NDEBUG
-        if (numMatches != JSRegExpErrorNoMatch)
-            fprintf(stderr, "jsRegExpExecute failed with result %d\n", numMatches);
+            // TODO: define up a symbol, rather than magic -1
+            if (result != -1)
+                fprintf(stderr, "jsRegExpExecute failed with result %d\n", result);
 #endif
-        if (ovector)
-            ovector->clear();
-        return -1;
+            if (ovector)
+                ovector->clear();
+        }
+        return result;
+    } else
+#endif
+    if (m_regExp) {
+        // Set up the offset vector for the result.
+        // First 2/3 used for result, the last third used by PCRE.
+        int* offsetVector;
+        int offsetVectorSize;
+        int fixedSizeOffsetVector[3];
+        if (!ovector) {
+            offsetVectorSize = 3;
+            offsetVector = fixedSizeOffsetVector;
+        } else {
+            offsetVectorSize = (m_numSubpatterns + 1) * 3;
+            offsetVector = new int [offsetVectorSize];
+            ovector->set(offsetVector);
+        }
+
+        int numMatches = jsRegExpExecute(m_regExp, reinterpret_cast<const UChar*>(s.data()), s.size(), i, offsetVector, offsetVectorSize);
+    
+        if (numMatches < 0) {
+#ifndef NDEBUG
+            if (numMatches != JSRegExpErrorNoMatch)
+                fprintf(stderr, "jsRegExpExecute failed with result %d\n", numMatches);
+#endif
+            if (ovector)
+                ovector->clear();
+            return -1;
+        }
+
+        return offsetVector[0];
     }
 
-    return offsetVector[0];
+    return -1;
 }
 
 } // namespace KJS
index 097ab9d..4f5072c 100644 (file)
 #define KJS_REGEXP_H
 
 #include "ustring.h"
+#include "ExecState.h"
 #include <wtf/Forward.h>
 #include <wtf/RefCounted.h>
+#include <wrec/WREC.h>
 
 struct JSRegExp;
 
@@ -31,8 +33,8 @@ namespace KJS {
 
     class RegExp : public RefCounted<RegExp> {
     public:
-        static PassRefPtr<RegExp> create(const UString& pattern);
-        static PassRefPtr<RegExp> create(const UString& pattern, const UString& flags);
+        static PassRefPtr<RegExp> create(ExecState*, const UString& pattern);
+        static PassRefPtr<RegExp> create(ExecState*, const UString& pattern, const UString& flags);
         ~RegExp();
 
         bool global() const { return m_flagBits & Global; }
@@ -49,8 +51,8 @@ namespace KJS {
         unsigned numSubpatterns() const { return m_numSubpatterns; }
 
     private:
-        RegExp(const UString& pattern);
-        RegExp(const UString& pattern, const UString& flags);
+        RegExp(ExecState*, const UString& pattern);
+        RegExp(ExecState*, const UString& pattern, const UString& flags);
 
         void compile();
 
@@ -62,6 +64,10 @@ namespace KJS {
         JSRegExp* m_regExp;
         const char* m_constructionError;
         unsigned m_numSubpatterns;
+
+#if ENABLE(WREC)
+        WRECFunction m_wrecFunction;
+#endif
     };
 
 } // namespace KJS
index 82123fb..efabeaf 100644 (file)
@@ -71,8 +71,12 @@ namespace KJS {
     typedef Vector<char, 32> CStringBuffer;
 
     class UString {
+        friend class CTI;
+
     public:
         struct Rep {
+            friend class CTI;
+
             static PassRefPtr<Rep> create(UChar*, int);
             static PassRefPtr<Rep> createCopying(const UChar*, int);
             static PassRefPtr<Rep> create(PassRefPtr<Rep> base, int offset, int length);
diff --git a/JavaScriptCore/masm/IA32MacroAsm.h b/JavaScriptCore/masm/IA32MacroAsm.h
new file mode 100644 (file)
index 0000000..83e76aa
--- /dev/null
@@ -0,0 +1,898 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef IA32MacroAsm_h
+#define IA32MacroAsm_h
+
+#if ENABLE(MASM) && PLATFORM(X86)
+
+#include <wtf/Assertions.h>
+#include <wtf/AlwaysInline.h>
+#if HAVE(MMAN)
+#include <sys/mman.h>
+#endif
+
+#include <string.h>
+
+namespace KJS {
+
+class JITCodeBuffer {
+public:
+    JITCodeBuffer(int size)
+        : m_buffer(static_cast<char*>(fastMalloc(size)))
+        , m_size(size)
+        , m_index(0)
+    {
+    }
+
+    ~JITCodeBuffer()
+    {
+        fastFree(m_buffer);
+    }
+
+    void ensureSpace(int space)
+    {
+        if (m_index > m_size - space)
+            growBuffer();
+    }
+
+    void putByteUnchecked(int value)
+    {
+        m_buffer[m_index] = value;
+        m_index++;
+    }
+
+    void putByte(int value)
+    {
+        if (m_index > m_size - 4)
+            growBuffer();
+        putByteUnchecked(value);
+    }
+    
+    void putShortUnchecked(int value)
+    {
+        *(short*)(&m_buffer[m_index]) = value;
+        m_index += 2;
+    }
+
+    void putShort(int value)
+    {
+        if (m_index > m_size - 4)
+            growBuffer();
+        putShortUnchecked(value);
+    }
+    
+    void putIntUnchecked(int value)
+    {
+        *(int*)(&m_buffer[m_index]) = value;
+        m_index += 4;
+    }
+
+    void putInt(int value)
+    {
+        if (m_index > m_size - 4)
+            growBuffer();
+        putIntUnchecked(value);
+    }
+
+    void* getEIP()
+    {
+        return m_buffer + m_index;
+    }
+    
+    void* start()
+    {
+        return m_buffer;
+    }
+    
+    int getOffset()
+    {
+        return m_index;
+    }
+    
+    JITCodeBuffer* reset()
+    {
+        m_index = 0;
+        return this;
+    }
+    
+    void* copy()
+    {
+        if (!m_index)
+            return 0;
+
+        void* result = fastMalloc(m_index);
+
+        if (!result)
+            return 0;
+
+        return memcpy(result, m_buffer, m_index);
+    }
+
+private:
+    void growBuffer()
+    {
+        m_size += m_size / 2;
+        m_buffer = static_cast<char*>(fastRealloc(m_buffer, m_size));
+    }
+
+    char* m_buffer;
+    int m_size;
+    int m_index;
+};
+
+#define MODRM(type, reg, rm) ((type << 6) | (reg << 3) | (rm))
+#define SIB(type, reg, rm) MODRM(type, reg, rm)
+#define CAN_SIGN_EXTEND_8_32(value) (value == ((int)(signed char)value))
+
+class IA32MacroAssembler {
+public:
+    typedef enum {
+        eax,
+        ecx,
+        edx,
+        ebx,
+        esp,
+        ebp,
+        esi,
+        edi,
+
+        NO_BASE  = ebp,
+        HAS_SIB  = esp,
+        NO_SCALE = esp,
+    } RegisterID;
+
+    typedef enum {
+        OP_ADD_EvGv                     = 0x01,
+        OP_ADD_GvEv                     = 0x03,
+        OP_OR_EvGv                      = 0x09,
+        OP_2BYTE_ESCAPE                 = 0x0F,
+        OP_AND_EvGv                     = 0x21,
+        OP_SUB_EvGv                     = 0x29,
+        OP_SUB_GvEv                     = 0x2B,
+        PRE_PREDICT_BRANCH_NOT_TAKEN    = 0x2E,
+        OP_XOR_EvGv                     = 0x31,
+        OP_CMP_EvGv                     = 0x39,
+        OP_PUSH_EAX                     = 0x50,
+        OP_POP_EAX                      = 0x58,
+        PRE_OPERAND_SIZE                = 0x66,
+        OP_GROUP1_EvIz                  = 0x81,
+        OP_GROUP1_EvIb                  = 0x83,
+        OP_TEST_EvGv                    = 0x85,
+        OP_MOV_EvGv                     = 0x89,
+        OP_MOV_GvEv                     = 0x8B,
+        OP_LEA                          = 0x8D,
+        OP_GROUP1A_Ev                   = 0x8F,
+        OP_CDQ                          = 0x99,
+        OP_GROUP2_EvIb                  = 0xC1,
+        OP_RET                          = 0xC3,
+        OP_GROUP11_EvIz                 = 0xC7,
+        OP_INT3                         = 0xCC,
+        OP_GROUP2_Ev1                   = 0xD1,
+        OP_GROUP2_EvCL                  = 0xD3,
+        OP_CALL_rel32                   = 0xE8,
+        OP_JMP_rel32                    = 0xE9,
+        OP_GROUP3_Ev                    = 0xF7,
+        OP_GROUP3_EvIz                  = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test. 
+        OP_GROUP5_Ev                    = 0xFF,
+
+        OP2_JO_rel32    = 0x80,
+        OP2_JB_rel32    = 0x82,
+        OP2_JAE_rel32   = 0x83,
+        OP2_JE_rel32    = 0x84,
+        OP2_JNE_rel32   = 0x85,
+        OP2_JBE_rel32   = 0x86,
+        OP2_JL_rel32    = 0x8C,
+        OP2_JGE_rel32   = 0x8D,
+        OP2_JLE_rel32   = 0x8E,
+        OP2_MUL_GvEv    = 0xAF,
+        OP2_MOVZX_GvEw  = 0xB7,
+
+        GROUP1_OP_ADD = 0,
+        GROUP1_OP_OR  = 1,
+        GROUP1_OP_AND = 4,
+        GROUP1_OP_SUB = 5,
+        GROUP1_OP_XOR = 6,
+        GROUP1_OP_CMP = 7,
+
+        GROUP1A_OP_POP = 0,
+
+        GROUP2_OP_SHL = 4,
+        GROUP2_OP_SAR = 7,
+
+        GROUP3_OP_TEST = 0,
+        GROUP3_OP_IDIV = 7,
+
+        GROUP5_OP_CALLN = 2,
+        GROUP5_OP_JMPN  = 4,
+        GROUP5_OP_PUSH  = 6,
+
+        GROUP11_MOV = 0,
+    } OpcodeID;
+    
+    static const int MAX_INSTRUCTION_SIZE = 16;
+
+    IA32MacroAssembler(JITCodeBuffer* m_buffer)
+        : m_buffer(m_buffer)
+    {
+        m_buffer->reset();
+    }
+
+    void emitInt3()
+    {
+        m_buffer->putByte(OP_INT3);
+    }
+    
+    void emitPushl_r(RegisterID reg)
+    {
+        m_buffer->putByte(OP_PUSH_EAX + reg);
+    }
+    
+    void emitPushl_m(int offset, RegisterID base)
+    {
+        m_buffer->putByte(OP_GROUP5_Ev);
+        emitModRm_opm(GROUP5_OP_PUSH, base, offset);
+    }
+    
+    void emitPopl_r(RegisterID reg)
+    {
+        m_buffer->putByte(OP_POP_EAX + reg);
+    }
+
+    void emitPopl_m(int offset, RegisterID base)
+    {
+        m_buffer->putByte(OP_GROUP1A_Ev);
+        emitModRm_opm(GROUP1A_OP_POP, base, offset);
+    }
+    
+    void emitMovl_rr(RegisterID src, RegisterID dst)
+    {
+        m_buffer->putByte(OP_MOV_EvGv);
+        emitModRm_rr(src, dst);
+    }
+    
+    void emitAddl_rr(RegisterID src, RegisterID dst)
+    {
+        m_buffer->putByte(OP_ADD_EvGv);
+        emitModRm_rr(src, dst);
+    }
+
+    void emitAddl_i8r(int imm, RegisterID dst)
+    {
+        m_buffer->putByte(OP_GROUP1_EvIb);
+        emitModRm_opr(GROUP1_OP_ADD, dst);
+        m_buffer->putByte(imm);
+    }
+
+    void emitAddl_i32r(int imm, RegisterID dst)
+    {
+        m_buffer->putByte(OP_GROUP1_EvIz);
+        emitModRm_opr(GROUP1_OP_ADD, dst);
+        m_buffer->putInt(imm);
+    }
+
+    void emitAddl_mr(int offset, RegisterID base, RegisterID dst)
+    {
+        m_buffer->putByte(OP_ADD_GvEv);
+        emitModRm_rm(dst, base, offset);
+    }
+
+    void emitAndl_rr(RegisterID src, RegisterID dst)
+    {
+        m_buffer->putByte(OP_AND_EvGv);
+        emitModRm_rr(src, dst);
+    }
+
+    void emitAndl_i32r(int imm, RegisterID dst)
+    {
+        m_buffer->putByte(OP_GROUP1_EvIz);
+        emitModRm_opr(GROUP1_OP_AND, dst);
+        m_buffer->putInt(imm);
+    }
+
+    void emitCmpl_i8r(int imm, RegisterID dst)
+    {
+        m_buffer->putByte(OP_GROUP1_EvIb);
+        emitModRm_opr(GROUP1_OP_CMP, dst);
+        m_buffer->putByte(imm);
+    }
+
+    void emitCmpl_rr(RegisterID src, RegisterID dst)
+    {
+        m_buffer->putByte(OP_CMP_EvGv);
+        emitModRm_rr(src, dst);
+    }
+
+    void emitCmpl_rm(RegisterID src, int offset, RegisterID base)
+    {
+        m_buffer->putByte(OP_CMP_EvGv);
+        emitModRm_rm(src, base, offset);
+    }
+
+    void emitCmpl_i32r(int imm, RegisterID dst)
+    {
+        m_buffer->putByte(OP_GROUP1_EvIz);
+        emitModRm_opr(GROUP1_OP_CMP, dst);
+        m_buffer->putInt(imm);
+    }
+
+    void emitCmpl_i32m(int imm, RegisterID dst)
+    {
+        m_buffer->putByte(OP_GROUP1_EvIz);
+        emitModRm_opm(GROUP1_OP_CMP, dst);
+        m_buffer->putInt(imm);
+    }
+
+    void emitCmpl_i32m(int imm, int offset, RegisterID dst)
+    {
+        m_buffer->putByte(OP_GROUP1_EvIz);
+        emitModRm_opm(GROUP1_OP_CMP, dst, offset);
+        m_buffer->putInt(imm);
+    }
+
+    void emitCmpl_i32m(int imm, void* addr)
+    {
+        m_buffer->putByte(OP_GROUP1_EvIz);
+        emitModRm_opm(GROUP1_OP_CMP, addr);
+        m_buffer->putInt(imm);
+    }
+
+    void emitCmpw_rm(RegisterID src, RegisterID base, RegisterID index, int scale)
+    {
+        m_buffer->putByte(PRE_OPERAND_SIZE);
+        m_buffer->putByte(OP_CMP_EvGv);
+        emitModRm_rmsib(src, base, index, scale);
+    }
+
+    void emitOrl_rr(RegisterID src, RegisterID dst)
+    {
+        m_buffer->putByte(OP_OR_EvGv);
+        emitModRm_rr(src, dst);
+    }
+
+    void emitOrl_i8r(int imm, Regis