JSC should be a triple-tier VM
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Feb 2012 06:49:37 +0000 (06:49 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Feb 2012 06:49:37 +0000 (06:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=75812
<rdar://problem/10079694>

Source/JavaScriptCore:

Reviewed by Gavin Barraclough.

Implemented an interpreter that uses the JIT's calling convention. This
interpreter is called LLInt, or the Low Level Interpreter. JSC will now
will start by executing code in LLInt and will only tier up to the old
JIT after the code is proven hot.

LLInt is written in a modified form of our macro assembly. This new macro
assembly is compiled by an offline assembler (see offlineasm), which
implements many modern conveniences such as a Turing-complete CPS-based
macro language and direct access to relevant C++ type information
(basically offsets of fields and sizes of structs/classes).

Code executing in LLInt appears to the rest of the JSC world "as if" it
were executing in the old JIT. Hence, things like exception handling and
cross-execution-engine calls just work and require pretty much no
additional overhead.

This interpreter is 2-2.5x faster than our old interpreter on SunSpider,
V8, and Kraken. With triple-tiering turned on, we're neutral on SunSpider,
V8, and Kraken, but appear to get a double-digit improvement on real-world
websites due to a huge reduction in the amount of JIT'ing.

* CMakeLists.txt:
* GNUmakefile.am:
* GNUmakefile.list.am:
* JavaScriptCore.pri:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops:
* JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* assembler/LinkBuffer.h:
* assembler/MacroAssemblerCodeRef.h:
(MacroAssemblerCodePtr):
(JSC::MacroAssemblerCodePtr::createFromExecutableAddress):
* bytecode/BytecodeConventions.h: Added.
* bytecode/CallLinkStatus.cpp:
(JSC::CallLinkStatus::computeFromLLInt):
(JSC):
(JSC::CallLinkStatus::computeFor):
* bytecode/CallLinkStatus.h:
(JSC::CallLinkStatus::isSet):
(JSC::CallLinkStatus::operator!):
(CallLinkStatus):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dump):
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::~CodeBlock):
(JSC::CodeBlock::finalizeUnconditionally):
(JSC::CodeBlock::stronglyVisitStrongReferences):
(JSC):
(JSC::CodeBlock::unlinkCalls):
(JSC::CodeBlock::unlinkIncomingCalls):
(JSC::CodeBlock::bytecodeOffset):
(JSC::ProgramCodeBlock::jettison):
(JSC::EvalCodeBlock::jettison):
(JSC::FunctionCodeBlock::jettison):
(JSC::ProgramCodeBlock::jitCompileImpl):
(JSC::EvalCodeBlock::jitCompileImpl):
(JSC::FunctionCodeBlock::jitCompileImpl):
* bytecode/CodeBlock.h:
(JSC):
(CodeBlock):
(JSC::CodeBlock::baselineVersion):
(JSC::CodeBlock::linkIncomingCall):
(JSC::CodeBlock::bytecodeOffset):
(JSC::CodeBlock::jitCompile):
(JSC::CodeBlock::hasOptimizedReplacement):
(JSC::CodeBlock::addPropertyAccessInstruction):
(JSC::CodeBlock::addGlobalResolveInstruction):
(JSC::CodeBlock::addLLIntCallLinkInfo):
(JSC::CodeBlock::addGlobalResolveInfo):
(JSC::CodeBlock::numberOfMethodCallLinkInfos):
(JSC::CodeBlock::valueProfilePredictionForBytecodeOffset):
(JSC::CodeBlock::likelyToTakeSlowCase):
(JSC::CodeBlock::couldTakeSlowCase):
(JSC::CodeBlock::likelyToTakeSpecialFastCase):
(JSC::CodeBlock::likelyToTakeDeepestSlowCase):
(JSC::CodeBlock::likelyToTakeAnySlowCase):
(JSC::CodeBlock::addFrequentExitSite):
(JSC::CodeBlock::dontJITAnytimeSoon):
(JSC::CodeBlock::jitAfterWarmUp):
(JSC::CodeBlock::jitSoon):
(JSC::CodeBlock::llintExecuteCounter):
(ProgramCodeBlock):
(EvalCodeBlock):
(FunctionCodeBlock):
* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeFromLLInt):
(JSC):
(JSC::GetByIdStatus::computeFor):
* bytecode/GetByIdStatus.h:
(JSC::GetByIdStatus::GetByIdStatus):
(JSC::GetByIdStatus::wasSeenInJIT):
(GetByIdStatus):
* bytecode/Instruction.h:
(JSC):
(JSC::Instruction::Instruction):
(Instruction):
* bytecode/LLIntCallLinkInfo.h: Added.
(JSC):
(JSC::LLIntCallLinkInfo::LLIntCallLinkInfo):
(LLIntCallLinkInfo):
(JSC::LLIntCallLinkInfo::~LLIntCallLinkInfo):
(JSC::LLIntCallLinkInfo::isLinked):
(JSC::LLIntCallLinkInfo::unlink):
* bytecode/MethodCallLinkStatus.cpp:
(JSC::MethodCallLinkStatus::computeFor):
* bytecode/Opcode.cpp:
(JSC):
* bytecode/Opcode.h:
(JSC):
(JSC::padOpcodeName):
* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::computeFromLLInt):
(JSC):
(JSC::PutByIdStatus::computeFor):
* bytecode/PutByIdStatus.h:
(PutByIdStatus):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitResolve):
(JSC::BytecodeGenerator::emitResolveWithBase):
(JSC::BytecodeGenerator::emitGetById):
(JSC::BytecodeGenerator::emitPutById):
(JSC::BytecodeGenerator::emitDirectPutById):
(JSC::BytecodeGenerator::emitCall):
(JSC::BytecodeGenerator::emitConstruct):
(JSC::BytecodeGenerator::emitCatch):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::getPredictionWithoutOSRExit):
(JSC::DFG::ByteCodeParser::handleInlining):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.h:
(JSC::DFG::canCompileOpcode):
* dfg/DFGOSRExitCompiler.cpp:
* dfg/DFGOperations.cpp:
* heap/Heap.h:
(JSC):
(JSC::Heap::firstAllocatorWithoutDestructors):
(Heap):
* heap/MarkStack.cpp:
(JSC::visitChildren):
* heap/MarkedAllocator.h:
(JSC):
(MarkedAllocator):
* heap/MarkedSpace.h:
(JSC):
(MarkedSpace):
(JSC::MarkedSpace::firstAllocator):
* interpreter/CallFrame.cpp:
(JSC):
(JSC::CallFrame::bytecodeOffsetForNonDFGCode):
(JSC::CallFrame::setBytecodeOffsetForNonDFGCode):
(JSC::CallFrame::currentVPC):
(JSC::CallFrame::setCurrentVPC):
(JSC::CallFrame::trueCallerFrame):
* interpreter/CallFrame.h:
(JSC::ExecState::hasReturnPC):
(JSC::ExecState::clearReturnPC):
(ExecState):
(JSC::ExecState::bytecodeOffsetForNonDFGCode):
(JSC::ExecState::currentVPC):
(JSC::ExecState::setCurrentVPC):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::Interpreter):
(JSC::Interpreter::~Interpreter):
(JSC):
(JSC::Interpreter::initialize):
(JSC::Interpreter::isOpcode):
(JSC::Interpreter::unwindCallFrame):
(JSC::getCallerInfo):
(JSC::Interpreter::privateExecute):
(JSC::Interpreter::retrieveLastCaller):
* interpreter/Interpreter.h:
(JSC):
(Interpreter):
(JSC::Interpreter::getOpcode):
(JSC::Interpreter::getOpcodeID):
(JSC::Interpreter::classicEnabled):
* interpreter/RegisterFile.h:
(JSC):
(RegisterFile):
* jit/ExecutableAllocator.h:
(JSC):
* jit/HostCallReturnValue.cpp: Added.
(JSC):
(JSC::getHostCallReturnValueWithExecState):
* jit/HostCallReturnValue.h: Added.
(JSC):
(JSC::initializeHostCallReturnValue):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
(JSC::JIT::privateCompile):
* jit/JITCode.h:
(JSC::JITCode::isOptimizingJIT):
(JITCode):
(JSC::JITCode::isBaselineCode):
(JSC::JITCode::JITCode):
* jit/JITDriver.h:
(JSC::jitCompileIfAppropriate):
(JSC::jitCompileFunctionIfAppropriate):
* jit/JITExceptions.cpp:
(JSC::jitThrow):
* jit/JITInlineMethods.h:
(JSC::JIT::updateTopCallFrame):
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
(JSC):
* jit/JITStubs.h:
(JSC):
* jit/JSInterfaceJIT.h:
* llint: Added.
* llint/LLIntCommon.h: Added.
* llint/LLIntData.cpp: Added.
(LLInt):
(JSC::LLInt::Data::Data):
(JSC::LLInt::Data::performAssertions):
(JSC::LLInt::Data::~Data):
* llint/LLIntData.h: Added.
(JSC):
(LLInt):
(Data):
(JSC::LLInt::Data::exceptionInstructions):
(JSC::LLInt::Data::opcodeMap):
(JSC::LLInt::Data::performAssertions):
* llint/LLIntEntrypoints.cpp: Added.
(LLInt):
(JSC::LLInt::getFunctionEntrypoint):
(JSC::LLInt::getEvalEntrypoint):
(JSC::LLInt::getProgramEntrypoint):
* llint/LLIntEntrypoints.h: Added.
(JSC):
(LLInt):
(JSC::LLInt::getEntrypoint):
* llint/LLIntExceptions.cpp: Added.
(LLInt):
(JSC::LLInt::interpreterThrowInCaller):
(JSC::LLInt::returnToThrowForThrownException):
(JSC::LLInt::returnToThrow):
(JSC::LLInt::callToThrow):
* llint/LLIntExceptions.h: Added.
(JSC):
(LLInt):
* llint/LLIntOfflineAsmConfig.h: Added.
* llint/LLIntOffsetsExtractor.cpp: Added.
(JSC):
(LLIntOffsetsExtractor):
(JSC::LLIntOffsetsExtractor::dummy):
(main):
* llint/LLIntSlowPaths.cpp: Added.
(LLInt):
(JSC::LLInt::llint_trace_operand):
(JSC::LLInt::llint_trace_value):
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
(JSC::LLInt::traceFunctionPrologue):
(JSC::LLInt::shouldJIT):
(JSC::LLInt::entryOSR):
(JSC::LLInt::resolveGlobal):
(JSC::LLInt::getByVal):
(JSC::LLInt::handleHostCall):
(JSC::LLInt::setUpCall):
(JSC::LLInt::genericCall):
* llint/LLIntSlowPaths.h: Added.
(JSC):
(LLInt):
* llint/LLIntThunks.cpp: Added.
(LLInt):
(JSC::LLInt::generateThunkWithJumpTo):
(JSC::LLInt::functionForCallEntryThunkGenerator):
(JSC::LLInt::functionForConstructEntryThunkGenerator):
(JSC::LLInt::functionForCallArityCheckThunkGenerator):
(JSC::LLInt::functionForConstructArityCheckThunkGenerator):
(JSC::LLInt::evalEntryThunkGenerator):
(JSC::LLInt::programEntryThunkGenerator):
* llint/LLIntThunks.h: Added.
(JSC):
(LLInt):
* llint/LowLevelInterpreter.asm: Added.
* llint/LowLevelInterpreter.cpp: Added.
* llint/LowLevelInterpreter.h: Added.
* offlineasm: Added.
* offlineasm/armv7.rb: Added.
* offlineasm/asm.rb: Added.
* offlineasm/ast.rb: Added.
* offlineasm/backends.rb: Added.
* offlineasm/generate_offset_extractor.rb: Added.
* offlineasm/instructions.rb: Added.
* offlineasm/offset_extractor_constants.rb: Added.
* offlineasm/offsets.rb: Added.
* offlineasm/opt.rb: Added.
* offlineasm/parser.rb: Added.
* offlineasm/registers.rb: Added.
* offlineasm/self_hash.rb: Added.
* offlineasm/settings.rb: Added.
* offlineasm/transform.rb: Added.
* offlineasm/x86.rb: Added.
* runtime/CodeSpecializationKind.h: Added.
(JSC):
* runtime/CommonSlowPaths.h:
(JSC::CommonSlowPaths::arityCheckFor):
(CommonSlowPaths):
* runtime/Executable.cpp:
(JSC::jettisonCodeBlock):
(JSC):
(JSC::EvalExecutable::jitCompile):
(JSC::samplingDescription):
(JSC::EvalExecutable::compileInternal):
(JSC::ProgramExecutable::jitCompile):
(JSC::ProgramExecutable::compileInternal):
(JSC::FunctionExecutable::baselineCodeBlockFor):
(JSC::FunctionExecutable::jitCompileForCall):
(JSC::FunctionExecutable::jitCompileForConstruct):
(JSC::FunctionExecutable::compileForCallInternal):
(JSC::FunctionExecutable::compileForConstructInternal):
* runtime/Executable.h:
(JSC):
(EvalExecutable):
(ProgramExecutable):
(FunctionExecutable):
(JSC::FunctionExecutable::jitCompileFor):
* runtime/ExecutionHarness.h: Added.
(JSC):
(JSC::prepareForExecution):
(JSC::prepareFunctionForExecution):
* runtime/JSArray.h:
(JSC):
(JSArray):
* runtime/JSCell.h:
(JSC):
(JSCell):
* runtime/JSFunction.h:
(JSC):
(JSFunction):
* runtime/JSGlobalData.cpp:
(JSC::JSGlobalData::JSGlobalData):
* runtime/JSGlobalData.h:
(JSC):
(JSGlobalData):
* runtime/JSGlobalObject.h:
(JSC):
(JSGlobalObject):
* runtime/JSObject.h:
(JSC):
(JSObject):
(JSFinalObject):
* runtime/JSPropertyNameIterator.h:
(JSC):
(JSPropertyNameIterator):
* runtime/JSString.h:
(JSC):
(JSString):
* runtime/JSTypeInfo.h:
(JSC):
(TypeInfo):
* runtime/JSValue.cpp:
(JSC::JSValue::description):
* runtime/JSValue.h:
(LLInt):
(JSValue):
* runtime/JSVariableObject.h:
(JSC):
(JSVariableObject):
* runtime/Options.cpp:
(Options):
(JSC::Options::initializeOptions):
* runtime/Options.h:
(Options):
* runtime/ScopeChain.h:
(JSC):
(ScopeChainNode):
* runtime/Structure.cpp:
(JSC::Structure::addPropertyTransition):
* runtime/Structure.h:
(JSC):
(Structure):
* runtime/StructureChain.h:
(JSC):
(StructureChain):
* wtf/InlineASM.h:
* wtf/Platform.h:
* wtf/SentinelLinkedList.h:
(SentinelLinkedList):
(WTF::SentinelLinkedList::isEmpty):
* wtf/text/StringImpl.h:
(JSC):
(StringImpl):

Source/WebCore:

Reviewed by Gavin Barraclough.

No new tests, because there is no change in behavior.

* CMakeLists.txt:

Source/WebKit:

Reviewed by Gavin Barraclough.

Changed EFL's build system to include a new directory in JavaScriptCore.

* CMakeLists.txt:

Tools:

Reviewed by Gavin Barraclough.

Changed EFL's build system to include a new directory in JavaScriptCore.

* DumpRenderTree/efl/CMakeLists.txt:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@108309 268f45cc-cd09-0410-ab3c-d52691b4dbfc

116 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/GNUmakefile.am
Source/JavaScriptCore/GNUmakefile.list.am
Source/JavaScriptCore/JavaScriptCore.pri
Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops
Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Target.pri
Source/JavaScriptCore/assembler/LinkBuffer.h
Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h
Source/JavaScriptCore/bytecode/BytecodeConventions.h [new file with mode: 0644]
Source/JavaScriptCore/bytecode/CallLinkStatus.cpp
Source/JavaScriptCore/bytecode/CallLinkStatus.h
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
Source/JavaScriptCore/bytecode/GetByIdStatus.h
Source/JavaScriptCore/bytecode/Instruction.h
Source/JavaScriptCore/bytecode/LLIntCallLinkInfo.h [new file with mode: 0644]
Source/JavaScriptCore/bytecode/MethodCallLinkStatus.cpp
Source/JavaScriptCore/bytecode/Opcode.cpp
Source/JavaScriptCore/bytecode/Opcode.h
Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
Source/JavaScriptCore/bytecode/PutByIdStatus.h
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGCapabilities.h
Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/heap/Heap.h
Source/JavaScriptCore/heap/MarkStack.cpp
Source/JavaScriptCore/heap/MarkedAllocator.h
Source/JavaScriptCore/heap/MarkedSpace.h
Source/JavaScriptCore/interpreter/CallFrame.cpp
Source/JavaScriptCore/interpreter/CallFrame.h
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/interpreter/Interpreter.h
Source/JavaScriptCore/interpreter/RegisterFile.h
Source/JavaScriptCore/jit/ExecutableAllocator.h
Source/JavaScriptCore/jit/HostCallReturnValue.cpp [new file with mode: 0644]
Source/JavaScriptCore/jit/HostCallReturnValue.h [new file with mode: 0644]
Source/JavaScriptCore/jit/JIT.cpp
Source/JavaScriptCore/jit/JITCode.h
Source/JavaScriptCore/jit/JITDriver.h
Source/JavaScriptCore/jit/JITExceptions.cpp
Source/JavaScriptCore/jit/JITInlineMethods.h
Source/JavaScriptCore/jit/JITStubs.cpp
Source/JavaScriptCore/jit/JITStubs.h
Source/JavaScriptCore/jit/JSInterfaceJIT.h
Source/JavaScriptCore/llint/LLIntCommon.h [new file with mode: 0644]
Source/JavaScriptCore/llint/LLIntData.cpp [new file with mode: 0644]
Source/JavaScriptCore/llint/LLIntData.h [new file with mode: 0644]
Source/JavaScriptCore/llint/LLIntEntrypoints.cpp [new file with mode: 0644]
Source/JavaScriptCore/llint/LLIntEntrypoints.h [new file with mode: 0644]
Source/JavaScriptCore/llint/LLIntExceptions.cpp [new file with mode: 0644]
Source/JavaScriptCore/llint/LLIntExceptions.h [new file with mode: 0644]
Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h [new file with mode: 0644]
Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp [new file with mode: 0644]
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp [new file with mode: 0644]
Source/JavaScriptCore/llint/LLIntSlowPaths.h [new file with mode: 0644]
Source/JavaScriptCore/llint/LLIntThunks.cpp [new file with mode: 0644]
Source/JavaScriptCore/llint/LLIntThunks.h [new file with mode: 0644]
Source/JavaScriptCore/llint/LowLevelInterpreter.asm [new file with mode: 0644]
Source/JavaScriptCore/llint/LowLevelInterpreter.cpp [new file with mode: 0644]
Source/JavaScriptCore/llint/LowLevelInterpreter.h [new file with mode: 0644]
Source/JavaScriptCore/offlineasm/armv7.rb [new file with mode: 0644]
Source/JavaScriptCore/offlineasm/asm.rb [new file with mode: 0644]
Source/JavaScriptCore/offlineasm/ast.rb [new file with mode: 0644]
Source/JavaScriptCore/offlineasm/backends.rb [new file with mode: 0644]
Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb [new file with mode: 0644]
Source/JavaScriptCore/offlineasm/instructions.rb [new file with mode: 0644]
Source/JavaScriptCore/offlineasm/offset_extractor_constants.rb [new file with mode: 0644]
Source/JavaScriptCore/offlineasm/offsets.rb [new file with mode: 0644]
Source/JavaScriptCore/offlineasm/opt.rb [new file with mode: 0644]
Source/JavaScriptCore/offlineasm/parser.rb [new file with mode: 0644]
Source/JavaScriptCore/offlineasm/registers.rb [new file with mode: 0644]
Source/JavaScriptCore/offlineasm/self_hash.rb [new file with mode: 0644]
Source/JavaScriptCore/offlineasm/settings.rb [new file with mode: 0644]
Source/JavaScriptCore/offlineasm/transform.rb [new file with mode: 0644]
Source/JavaScriptCore/offlineasm/x86.rb [new file with mode: 0644]
Source/JavaScriptCore/runtime/CodeSpecializationKind.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/CommonSlowPaths.h
Source/JavaScriptCore/runtime/Executable.cpp
Source/JavaScriptCore/runtime/Executable.h
Source/JavaScriptCore/runtime/ExecutionHarness.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/JSArray.h
Source/JavaScriptCore/runtime/JSCell.h
Source/JavaScriptCore/runtime/JSFunction.h
Source/JavaScriptCore/runtime/JSGlobalData.cpp
Source/JavaScriptCore/runtime/JSGlobalData.h
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/JSObject.h
Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
Source/JavaScriptCore/runtime/JSString.h
Source/JavaScriptCore/runtime/JSTypeInfo.h
Source/JavaScriptCore/runtime/JSValue.cpp
Source/JavaScriptCore/runtime/JSValue.h
Source/JavaScriptCore/runtime/JSVariableObject.h
Source/JavaScriptCore/runtime/Options.cpp
Source/JavaScriptCore/runtime/Options.h
Source/JavaScriptCore/runtime/ScopeChain.h
Source/JavaScriptCore/runtime/Structure.cpp
Source/JavaScriptCore/runtime/Structure.h
Source/JavaScriptCore/runtime/StructureChain.h
Source/JavaScriptCore/wtf/InlineASM.h
Source/JavaScriptCore/wtf/Platform.h
Source/JavaScriptCore/wtf/SentinelLinkedList.h
Source/JavaScriptCore/wtf/text/StringImpl.h
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebKit/CMakeLists.txt
Source/WebKit/ChangeLog
Tools/ChangeLog
Tools/DumpRenderTree/efl/CMakeLists.txt

index 815a5bc..d9d6231 100644 (file)
@@ -11,6 +11,7 @@ SET(JavaScriptCore_INCLUDE_DIRECTORIES
     "${JAVASCRIPTCORE_DIR}/debugger"
     "${JAVASCRIPTCORE_DIR}/interpreter"
     "${JAVASCRIPTCORE_DIR}/jit"
+    "${JAVASCRIPTCORE_DIR}/llint"
     "${JAVASCRIPTCORE_DIR}/parser"
     "${JAVASCRIPTCORE_DIR}/profiler"
     "${JAVASCRIPTCORE_DIR}/runtime"
@@ -102,6 +103,7 @@ SET(JavaScriptCore_SOURCES
     interpreter/RegisterFile.cpp
 
     jit/ExecutableAllocator.cpp
+    jit/HostCallReturnValue.cpp
     jit/JITArithmetic32_64.cpp
     jit/JITArithmetic.cpp
     jit/JITCall32_64.cpp
index 3b1f560..b640a87 100644 (file)
@@ -1,5 +1,400 @@
 2012-02-20  Filip Pizlo  <fpizlo@apple.com>
 
+        JSC should be a triple-tier VM
+        https://bugs.webkit.org/show_bug.cgi?id=75812
+        <rdar://problem/10079694>
+
+        Reviewed by Gavin Barraclough.
+        
+        Implemented an interpreter that uses the JIT's calling convention. This
+        interpreter is called LLInt, or the Low Level Interpreter. JSC will now
+        will start by executing code in LLInt and will only tier up to the old
+        JIT after the code is proven hot.
+        
+        LLInt is written in a modified form of our macro assembly. This new macro
+        assembly is compiled by an offline assembler (see offlineasm), which
+        implements many modern conveniences such as a Turing-complete CPS-based
+        macro language and direct access to relevant C++ type information
+        (basically offsets of fields and sizes of structs/classes).
+        
+        Code executing in LLInt appears to the rest of the JSC world "as if" it
+        were executing in the old JIT. Hence, things like exception handling and
+        cross-execution-engine calls just work and require pretty much no
+        additional overhead.
+        
+        This interpreter is 2-2.5x faster than our old interpreter on SunSpider,
+        V8, and Kraken. With triple-tiering turned on, we're neutral on SunSpider,
+        V8, and Kraken, but appear to get a double-digit improvement on real-world
+        websites due to a huge reduction in the amount of JIT'ing.
+        
+        * CMakeLists.txt:
+        * GNUmakefile.am:
+        * GNUmakefile.list.am:
+        * JavaScriptCore.pri:
+        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops:
+        * JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Target.pri:
+        * assembler/LinkBuffer.h:
+        * assembler/MacroAssemblerCodeRef.h:
+        (MacroAssemblerCodePtr):
+        (JSC::MacroAssemblerCodePtr::createFromExecutableAddress):
+        * bytecode/BytecodeConventions.h: Added.
+        * bytecode/CallLinkStatus.cpp:
+        (JSC::CallLinkStatus::computeFromLLInt):
+        (JSC):
+        (JSC::CallLinkStatus::computeFor):
+        * bytecode/CallLinkStatus.h:
+        (JSC::CallLinkStatus::isSet):
+        (JSC::CallLinkStatus::operator!):
+        (CallLinkStatus):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dump):
+        (JSC::CodeBlock::CodeBlock):
+        (JSC::CodeBlock::~CodeBlock):
+        (JSC::CodeBlock::finalizeUnconditionally):
+        (JSC::CodeBlock::stronglyVisitStrongReferences):
+        (JSC):
+        (JSC::CodeBlock::unlinkCalls):
+        (JSC::CodeBlock::unlinkIncomingCalls):
+        (JSC::CodeBlock::bytecodeOffset):
+        (JSC::ProgramCodeBlock::jettison):
+        (JSC::EvalCodeBlock::jettison):
+        (JSC::FunctionCodeBlock::jettison):
+        (JSC::ProgramCodeBlock::jitCompileImpl):
+        (JSC::EvalCodeBlock::jitCompileImpl):
+        (JSC::FunctionCodeBlock::jitCompileImpl):
+        * bytecode/CodeBlock.h:
+        (JSC):
+        (CodeBlock):
+        (JSC::CodeBlock::baselineVersion):
+        (JSC::CodeBlock::linkIncomingCall):
+        (JSC::CodeBlock::bytecodeOffset):
+        (JSC::CodeBlock::jitCompile):
+        (JSC::CodeBlock::hasOptimizedReplacement):
+        (JSC::CodeBlock::addPropertyAccessInstruction):
+        (JSC::CodeBlock::addGlobalResolveInstruction):
+        (JSC::CodeBlock::addLLIntCallLinkInfo):
+        (JSC::CodeBlock::addGlobalResolveInfo):
+        (JSC::CodeBlock::numberOfMethodCallLinkInfos):
+        (JSC::CodeBlock::valueProfilePredictionForBytecodeOffset):
+        (JSC::CodeBlock::likelyToTakeSlowCase):
+        (JSC::CodeBlock::couldTakeSlowCase):
+        (JSC::CodeBlock::likelyToTakeSpecialFastCase):
+        (JSC::CodeBlock::likelyToTakeDeepestSlowCase):
+        (JSC::CodeBlock::likelyToTakeAnySlowCase):
+        (JSC::CodeBlock::addFrequentExitSite):
+        (JSC::CodeBlock::dontJITAnytimeSoon):
+        (JSC::CodeBlock::jitAfterWarmUp):
+        (JSC::CodeBlock::jitSoon):
+        (JSC::CodeBlock::llintExecuteCounter):
+        (ProgramCodeBlock):
+        (EvalCodeBlock):
+        (FunctionCodeBlock):
+        * bytecode/GetByIdStatus.cpp:
+        (JSC::GetByIdStatus::computeFromLLInt):
+        (JSC):
+        (JSC::GetByIdStatus::computeFor):
+        * bytecode/GetByIdStatus.h:
+        (JSC::GetByIdStatus::GetByIdStatus):
+        (JSC::GetByIdStatus::wasSeenInJIT):
+        (GetByIdStatus):
+        * bytecode/Instruction.h:
+        (JSC):
+        (JSC::Instruction::Instruction):
+        (Instruction):
+        * bytecode/LLIntCallLinkInfo.h: Added.
+        (JSC):
+        (JSC::LLIntCallLinkInfo::LLIntCallLinkInfo):
+        (LLIntCallLinkInfo):
+        (JSC::LLIntCallLinkInfo::~LLIntCallLinkInfo):
+        (JSC::LLIntCallLinkInfo::isLinked):
+        (JSC::LLIntCallLinkInfo::unlink):
+        * bytecode/MethodCallLinkStatus.cpp:
+        (JSC::MethodCallLinkStatus::computeFor):
+        * bytecode/Opcode.cpp:
+        (JSC):
+        * bytecode/Opcode.h:
+        (JSC):
+        (JSC::padOpcodeName):
+        * bytecode/PutByIdStatus.cpp:
+        (JSC::PutByIdStatus::computeFromLLInt):
+        (JSC):
+        (JSC::PutByIdStatus::computeFor):
+        * bytecode/PutByIdStatus.h:
+        (PutByIdStatus):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitResolve):
+        (JSC::BytecodeGenerator::emitResolveWithBase):
+        (JSC::BytecodeGenerator::emitGetById):
+        (JSC::BytecodeGenerator::emitPutById):
+        (JSC::BytecodeGenerator::emitDirectPutById):
+        (JSC::BytecodeGenerator::emitCall):
+        (JSC::BytecodeGenerator::emitConstruct):
+        (JSC::BytecodeGenerator::emitCatch):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::getPredictionWithoutOSRExit):
+        (JSC::DFG::ByteCodeParser::handleInlining):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.h:
+        (JSC::DFG::canCompileOpcode):
+        * dfg/DFGOSRExitCompiler.cpp:
+        * dfg/DFGOperations.cpp:
+        * heap/Heap.h:
+        (JSC):
+        (JSC::Heap::firstAllocatorWithoutDestructors):
+        (Heap):
+        * heap/MarkStack.cpp:
+        (JSC::visitChildren):
+        * heap/MarkedAllocator.h:
+        (JSC):
+        (MarkedAllocator):
+        * heap/MarkedSpace.h:
+        (JSC):
+        (MarkedSpace):
+        (JSC::MarkedSpace::firstAllocator):
+        * interpreter/CallFrame.cpp:
+        (JSC):
+        (JSC::CallFrame::bytecodeOffsetForNonDFGCode):
+        (JSC::CallFrame::setBytecodeOffsetForNonDFGCode):
+        (JSC::CallFrame::currentVPC):
+        (JSC::CallFrame::setCurrentVPC):
+        (JSC::CallFrame::trueCallerFrame):
+        * interpreter/CallFrame.h:
+        (JSC::ExecState::hasReturnPC):
+        (JSC::ExecState::clearReturnPC):
+        (ExecState):
+        (JSC::ExecState::bytecodeOffsetForNonDFGCode):
+        (JSC::ExecState::currentVPC):
+        (JSC::ExecState::setCurrentVPC):
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::Interpreter):
+        (JSC::Interpreter::~Interpreter):
+        (JSC):
+        (JSC::Interpreter::initialize):
+        (JSC::Interpreter::isOpcode):
+        (JSC::Interpreter::unwindCallFrame):
+        (JSC::getCallerInfo):
+        (JSC::Interpreter::privateExecute):
+        (JSC::Interpreter::retrieveLastCaller):
+        * interpreter/Interpreter.h:
+        (JSC):
+        (Interpreter):
+        (JSC::Interpreter::getOpcode):
+        (JSC::Interpreter::getOpcodeID):
+        (JSC::Interpreter::classicEnabled):
+        * interpreter/RegisterFile.h:
+        (JSC):
+        (RegisterFile):
+        * jit/ExecutableAllocator.h:
+        (JSC):
+        * jit/HostCallReturnValue.cpp: Added.
+        (JSC):
+        (JSC::getHostCallReturnValueWithExecState):
+        * jit/HostCallReturnValue.h: Added.
+        (JSC):
+        (JSC::initializeHostCallReturnValue):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        (JSC::JIT::privateCompileSlowCases):
+        (JSC::JIT::privateCompile):
+        * jit/JITCode.h:
+        (JSC::JITCode::isOptimizingJIT):
+        (JITCode):
+        (JSC::JITCode::isBaselineCode):
+        (JSC::JITCode::JITCode):
+        * jit/JITDriver.h:
+        (JSC::jitCompileIfAppropriate):
+        (JSC::jitCompileFunctionIfAppropriate):
+        * jit/JITExceptions.cpp:
+        (JSC::jitThrow):
+        * jit/JITInlineMethods.h:
+        (JSC::JIT::updateTopCallFrame):
+        * jit/JITStubs.cpp:
+        (JSC::DEFINE_STUB_FUNCTION):
+        (JSC):
+        * jit/JITStubs.h:
+        (JSC):
+        * jit/JSInterfaceJIT.h:
+        * llint: Added.
+        * llint/LLIntCommon.h: Added.
+        * llint/LLIntData.cpp: Added.
+        (LLInt):
+        (JSC::LLInt::Data::Data):
+        (JSC::LLInt::Data::performAssertions):
+        (JSC::LLInt::Data::~Data):
+        * llint/LLIntData.h: Added.
+        (JSC):
+        (LLInt):
+        (Data):
+        (JSC::LLInt::Data::exceptionInstructions):
+        (JSC::LLInt::Data::opcodeMap):
+        (JSC::LLInt::Data::performAssertions):
+        * llint/LLIntEntrypoints.cpp: Added.
+        (LLInt):
+        (JSC::LLInt::getFunctionEntrypoint):
+        (JSC::LLInt::getEvalEntrypoint):
+        (JSC::LLInt::getProgramEntrypoint):
+        * llint/LLIntEntrypoints.h: Added.
+        (JSC):
+        (LLInt):
+        (JSC::LLInt::getEntrypoint):
+        * llint/LLIntExceptions.cpp: Added.
+        (LLInt):
+        (JSC::LLInt::interpreterThrowInCaller):
+        (JSC::LLInt::returnToThrowForThrownException):
+        (JSC::LLInt::returnToThrow):
+        (JSC::LLInt::callToThrow):
+        * llint/LLIntExceptions.h: Added.
+        (JSC):
+        (LLInt):
+        * llint/LLIntOfflineAsmConfig.h: Added.
+        * llint/LLIntOffsetsExtractor.cpp: Added.
+        (JSC):
+        (LLIntOffsetsExtractor):
+        (JSC::LLIntOffsetsExtractor::dummy):
+        (main):
+        * llint/LLIntSlowPaths.cpp: Added.
+        (LLInt):
+        (JSC::LLInt::llint_trace_operand):
+        (JSC::LLInt::llint_trace_value):
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        (JSC::LLInt::traceFunctionPrologue):
+        (JSC::LLInt::shouldJIT):
+        (JSC::LLInt::entryOSR):
+        (JSC::LLInt::resolveGlobal):
+        (JSC::LLInt::getByVal):
+        (JSC::LLInt::handleHostCall):
+        (JSC::LLInt::setUpCall):
+        (JSC::LLInt::genericCall):
+        * llint/LLIntSlowPaths.h: Added.
+        (JSC):
+        (LLInt):
+        * llint/LLIntThunks.cpp: Added.
+        (LLInt):
+        (JSC::LLInt::generateThunkWithJumpTo):
+        (JSC::LLInt::functionForCallEntryThunkGenerator):
+        (JSC::LLInt::functionForConstructEntryThunkGenerator):
+        (JSC::LLInt::functionForCallArityCheckThunkGenerator):
+        (JSC::LLInt::functionForConstructArityCheckThunkGenerator):
+        (JSC::LLInt::evalEntryThunkGenerator):
+        (JSC::LLInt::programEntryThunkGenerator):
+        * llint/LLIntThunks.h: Added.
+        (JSC):
+        (LLInt):
+        * llint/LowLevelInterpreter.asm: Added.
+        * llint/LowLevelInterpreter.cpp: Added.
+        * llint/LowLevelInterpreter.h: Added.
+        * offlineasm: Added.
+        * offlineasm/armv7.rb: Added.
+        * offlineasm/asm.rb: Added.
+        * offlineasm/ast.rb: Added.
+        * offlineasm/backends.rb: Added.
+        * offlineasm/generate_offset_extractor.rb: Added.
+        * offlineasm/instructions.rb: Added.
+        * offlineasm/offset_extractor_constants.rb: Added.
+        * offlineasm/offsets.rb: Added.
+        * offlineasm/opt.rb: Added.
+        * offlineasm/parser.rb: Added.
+        * offlineasm/registers.rb: Added.
+        * offlineasm/self_hash.rb: Added.
+        * offlineasm/settings.rb: Added.
+        * offlineasm/transform.rb: Added.
+        * offlineasm/x86.rb: Added.
+        * runtime/CodeSpecializationKind.h: Added.
+        (JSC):
+        * runtime/CommonSlowPaths.h:
+        (JSC::CommonSlowPaths::arityCheckFor):
+        (CommonSlowPaths):
+        * runtime/Executable.cpp:
+        (JSC::jettisonCodeBlock):
+        (JSC):
+        (JSC::EvalExecutable::jitCompile):
+        (JSC::samplingDescription):
+        (JSC::EvalExecutable::compileInternal):
+        (JSC::ProgramExecutable::jitCompile):
+        (JSC::ProgramExecutable::compileInternal):
+        (JSC::FunctionExecutable::baselineCodeBlockFor):
+        (JSC::FunctionExecutable::jitCompileForCall):
+        (JSC::FunctionExecutable::jitCompileForConstruct):
+        (JSC::FunctionExecutable::compileForCallInternal):
+        (JSC::FunctionExecutable::compileForConstructInternal):
+        * runtime/Executable.h:
+        (JSC):
+        (EvalExecutable):
+        (ProgramExecutable):
+        (FunctionExecutable):
+        (JSC::FunctionExecutable::jitCompileFor):
+        * runtime/ExecutionHarness.h: Added.
+        (JSC):
+        (JSC::prepareForExecution):
+        (JSC::prepareFunctionForExecution):
+        * runtime/JSArray.h:
+        (JSC):
+        (JSArray):
+        * runtime/JSCell.h:
+        (JSC):
+        (JSCell):
+        * runtime/JSFunction.h:
+        (JSC):
+        (JSFunction):
+        * runtime/JSGlobalData.cpp:
+        (JSC::JSGlobalData::JSGlobalData):
+        * runtime/JSGlobalData.h:
+        (JSC):
+        (JSGlobalData):
+        * runtime/JSGlobalObject.h:
+        (JSC):
+        (JSGlobalObject):
+        * runtime/JSObject.h:
+        (JSC):
+        (JSObject):
+        (JSFinalObject):
+        * runtime/JSPropertyNameIterator.h:
+        (JSC):
+        (JSPropertyNameIterator):
+        * runtime/JSString.h:
+        (JSC):
+        (JSString):
+        * runtime/JSTypeInfo.h:
+        (JSC):
+        (TypeInfo):
+        * runtime/JSValue.cpp:
+        (JSC::JSValue::description):
+        * runtime/JSValue.h:
+        (LLInt):
+        (JSValue):
+        * runtime/JSVariableObject.h:
+        (JSC):
+        (JSVariableObject):
+        * runtime/Options.cpp:
+        (Options):
+        (JSC::Options::initializeOptions):
+        * runtime/Options.h:
+        (Options):
+        * runtime/ScopeChain.h:
+        (JSC):
+        (ScopeChainNode):
+        * runtime/Structure.cpp:
+        (JSC::Structure::addPropertyTransition):
+        * runtime/Structure.h:
+        (JSC):
+        (Structure):
+        * runtime/StructureChain.h:
+        (JSC):
+        (StructureChain):
+        * wtf/InlineASM.h:
+        * wtf/Platform.h:
+        * wtf/SentinelLinkedList.h:
+        (SentinelLinkedList):
+        (WTF::SentinelLinkedList::isEmpty):
+        * wtf/text/StringImpl.h:
+        (JSC):
+        (StringImpl):
+
+2012-02-20  Filip Pizlo  <fpizlo@apple.com>
+
         Unreviewed, rolling out http://trac.webkit.org/changeset/108291
         It completely broke the 32-bit JIT.
 
index 654cd10..8d6d252 100644 (file)
@@ -57,6 +57,7 @@ javascriptcore_cppflags += \
        -I$(srcdir)/Source/JavaScriptCore/interpreter \
        -I$(srcdir)/Source/JavaScriptCore/jit \
        -I$(srcdir)/Source/JavaScriptCore/jit \
+       -I$(srcdir)/Source/JavaScriptCore/llint \
        -I$(srcdir)/Source/JavaScriptCore/parser \
        -I$(srcdir)/Source/JavaScriptCore/profiler \
        -I$(srcdir)/Source/JavaScriptCore/runtime \
index c39eda0..26fa271 100644 (file)
@@ -81,6 +81,7 @@ javascriptcore_sources += \
        Source/JavaScriptCore/assembler/RepatchBuffer.h \
        Source/JavaScriptCore/assembler/SH4Assembler.h \
        Source/JavaScriptCore/assembler/X86Assembler.h \
+       Source/JavaScriptCore/bytecode/BytecodeConventions.h \
        Source/JavaScriptCore/bytecode/CallLinkInfo.cpp \
        Source/JavaScriptCore/bytecode/CallLinkInfo.h \
        Source/JavaScriptCore/bytecode/CallLinkStatus.cpp \
@@ -102,6 +103,7 @@ javascriptcore_sources += \
        Source/JavaScriptCore/bytecode/Instruction.h \
        Source/JavaScriptCore/bytecode/JumpTable.cpp \
        Source/JavaScriptCore/bytecode/JumpTable.h \
+       Source/JavaScriptCore/bytecode/LLIntCallLinkInfo.h \
        Source/JavaScriptCore/bytecode/LineInfo.h \
        Source/JavaScriptCore/bytecode/MethodCallLinkInfo.cpp \
        Source/JavaScriptCore/bytecode/MethodCallLinkInfo.h \
@@ -297,6 +299,8 @@ javascriptcore_sources += \
        Source/JavaScriptCore/jit/CompactJITCodeMap.h \
        Source/JavaScriptCore/jit/ExecutableAllocator.cpp \
        Source/JavaScriptCore/jit/ExecutableAllocator.h \
+       Source/JavaScriptCore/jit/HostCallReturnValue.cpp \
+       Source/JavaScriptCore/jit/HostCallReturnValue.h \
        Source/JavaScriptCore/jit/JITArithmetic32_64.cpp \
        Source/JavaScriptCore/jit/JITArithmetic.cpp \
        Source/JavaScriptCore/jit/JITCall32_64.cpp \
@@ -320,6 +324,7 @@ javascriptcore_sources += \
        Source/JavaScriptCore/jit/SpecializedThunkJIT.h \
        Source/JavaScriptCore/jit/ThunkGenerators.cpp \
        Source/JavaScriptCore/jit/ThunkGenerators.h \
+       Source/JavaScriptCore/llint/LLIntData.h \
        Source/JavaScriptCore/os-win32/stdbool.h \
        Source/JavaScriptCore/os-win32/stdint.h \
        Source/JavaScriptCore/parser/ASTBuilder.h \
@@ -370,6 +375,7 @@ javascriptcore_sources += \
        Source/JavaScriptCore/runtime/CallData.cpp \
        Source/JavaScriptCore/runtime/CallData.h \
        Source/JavaScriptCore/runtime/ClassInfo.h \
+       Source/JavaScriptCore/runtime/CodeSpecializationKind.h \
        Source/JavaScriptCore/runtime/CommonIdentifiers.cpp \
        Source/JavaScriptCore/runtime/CommonIdentifiers.h \
        Source/JavaScriptCore/runtime/CommonSlowPaths.h \
@@ -398,6 +404,7 @@ javascriptcore_sources += \
        Source/JavaScriptCore/runtime/ExceptionHelpers.h \
        Source/JavaScriptCore/runtime/Executable.cpp \
        Source/JavaScriptCore/runtime/Executable.h \
+       Source/JavaScriptCore/runtime/ExecutionHarness.h \
        Source/JavaScriptCore/runtime/FunctionConstructor.cpp \
        Source/JavaScriptCore/runtime/FunctionConstructor.h \
        Source/JavaScriptCore/runtime/FunctionPrototype.cpp \
index 11749d4..eeace17 100644 (file)
@@ -20,6 +20,7 @@ INCLUDEPATH += \
     $$SOURCE_DIR/debugger \
     $$SOURCE_DIR/interpreter \
     $$SOURCE_DIR/jit \
+    $$SOURCE_DIR/llint \
     $$SOURCE_DIR/parser \
     $$SOURCE_DIR/profiler \
     $$SOURCE_DIR/runtime \
index 8989f80..7ec9b8c 100644 (file)
                                >
                        </File>
                        <File
+                               RelativePath="..\..\jit\HostCallReturnValue.cpp"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\..\jit\JIT.cpp"
                                >
                        </File>
                        </File>
                </Filter>
                <Filter
+                       Name="llint"
+                       >
+                       <File
+                               RelativePath="..\..\llint\LLIntData.h"
+                               >
+                       </File>
+               </Filter>
+               <Filter
                        Name="interpreter"
                        >
                        <File
index 33b5344..b0b45d3 100644 (file)
@@ -6,7 +6,7 @@
        >
        <Tool
                Name="VCCLCompilerTool"
-               AdditionalIncludeDirectories="&quot;$(ConfigurationBuildDir)\obj\JavaScriptCore\DerivedSources\&quot;;../../;../../API/;../../parser/;../../bytecompiler/;../../dfg/;../../jit/;../../runtime/;../../tools/;../../bytecode/;../../interpreter/;../../wtf/;../../profiler;../../assembler/;../../debugger/;../../heap/;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\private&quot;;&quot;$(ConfigurationBuildDir)\include&quot;;&quot;$(ConfigurationBuildDir)\include\JavaScriptCore&quot;;&quot;$(ConfigurationBuildDir)\include\private&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;"
+               AdditionalIncludeDirectories="&quot;$(ConfigurationBuildDir)\obj\JavaScriptCore\DerivedSources\&quot;;../../;../../API/;../../parser/;../../bytecompiler/;../../dfg/;../../jit/;../../llint/;../../runtime/;../../tools/;../../bytecode/;../../interpreter/;../../wtf/;../../profiler;../../assembler/;../../debugger/;../../heap/;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\private&quot;;&quot;$(ConfigurationBuildDir)\include&quot;;&quot;$(ConfigurationBuildDir)\include\JavaScriptCore&quot;;&quot;$(ConfigurationBuildDir)\include\private&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;"
                PreprocessorDefinitions="__STD_C"
                ForcedIncludeFiles="ICUVersion.h"
        />
index b8488af..5605ff5 100644 (file)
@@ -7,6 +7,15 @@
        objects = {
 
 /* Begin PBXAggregateTarget section */
+               0F4680A914BA7FD900BFE272 /* LLInt Offsets */ = {
+                       isa = PBXAggregateTarget;
+                       buildConfigurationList = 0F4680AC14BA7FD900BFE272 /* Build configuration list for PBXAggregateTarget "LLInt Offsets" */;
+                       buildPhases = (
+                               0F4680AA14BA7FD900BFE272 /* Generate Derived Sources */,
+                       );
+                       name = "LLInt Offsets";
+                       productName = "Derived Sources";
+               };
                65FB3F6609D11E9100F49DEB /* Derived Sources */ = {
                        isa = PBXAggregateTarget;
                        buildConfigurationList = 65FB3F7709D11EBD00F49DEB /* Build configuration list for PBXAggregateTarget "Derived Sources" */;
@@ -14,6 +23,9 @@
                                65FB3F6509D11E9100F49DEB /* Generate Derived Sources */,
                                5D35DEE10C7C140B008648B2 /* Generate DTrace header */,
                        );
+                       dependencies = (
+                               0F4680B414BA821400BFE272 /* PBXTargetDependency */,
+                       );
                        name = "Derived Sources";
                        productName = "Derived Sources";
                };
                0BAC94A01338728400CF135B /* ThreadRestrictionVerifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BAC949E1338728400CF135B /* ThreadRestrictionVerifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0BCD83571485845200EA2003 /* TemporaryChange.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BCD83541485841200EA2003 /* TemporaryChange.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0BF28A2911A33DC300638F84 /* SizeLimits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0BF28A2811A33DC300638F84 /* SizeLimits.cpp */; };
+               0F0B839A14BCF45D00885B4F /* LLIntEntrypoints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839514BCF45A00885B4F /* LLIntEntrypoints.cpp */; };
+               0F0B839B14BCF46000885B4F /* LLIntEntrypoints.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B839614BCF45A00885B4F /* LLIntEntrypoints.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */; };
+               0F0B839D14BCF46600885B4F /* LLIntThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B839814BCF45A00885B4F /* LLIntThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F0B83A714BCF50700885B4F /* CodeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83A514BCF50400885B4F /* CodeType.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F0B83A914BCF56200885B4F /* HandlerInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83A814BCF55E00885B4F /* HandlerInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F0B83AB14BCF5BB00885B4F /* ExpressionRangeInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83AA14BCF5B900885B4F /* ExpressionRangeInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F0B83B514BCF86200885B4F /* MethodCallLinkInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83B314BCF85E00885B4F /* MethodCallLinkInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F0B83B714BCF8E100885B4F /* GlobalResolveInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83B614BCF8DF00885B4F /* GlobalResolveInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F0B83B914BCF95F00885B4F /* CallReturnOffsetToBytecodeOffset.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F0FC45A14BD15F500B81154 /* LLIntCallLinkInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F16D726142C39C000CF784A /* BitVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F16D724142C39A200CF784A /* BitVector.cpp */; };
                0F21C26814BE5F6800ADC64B /* JITDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C26614BE5F5E00ADC64B /* JITDriver.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F21C27C14BE727600ADC64B /* ExecutionHarness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27A14BE727300ADC64B /* ExecutionHarness.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F21C27F14BEAA8200ADC64B /* BytecodeConventions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F242DA713F3B1E8007ADD4C /* WeakReferenceHarvester.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F2C556F14738F3100121E4F /* DFGCodeBlocks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F2C557014738F3500121E4F /* DFGCodeBlocks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */; };
                0F431738146BAC69007E3890 /* ListableHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F431736146BAC65007E3890 /* ListableHandler.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F46808214BA572D00BFE272 /* JITExceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F46808014BA572700BFE272 /* JITExceptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F46808314BA573100BFE272 /* JITExceptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F46807F14BA572700BFE272 /* JITExceptions.cpp */; };
+               0F4680A314BA7F8D00BFE272 /* LLIntExceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F46809E14BA7F8200BFE272 /* LLIntExceptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F4680A414BA7F8D00BFE272 /* LLIntSlowPaths.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F46809F14BA7F8200BFE272 /* LLIntSlowPaths.cpp */; settings = {COMPILER_FLAGS = "-Wno-unused-parameter"; }; };
+               0F4680A514BA7F8D00BFE272 /* LLIntSlowPaths.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680A014BA7F8200BFE272 /* LLIntSlowPaths.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F4680A714BA7FA100BFE272 /* LLIntOffsetsExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */; };
+               0F4680A814BA7FAB00BFE272 /* LLIntExceptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F46809D14BA7F8200BFE272 /* LLIntExceptions.cpp */; };
+               0F4680CA14BBB16C00BFE272 /* LLIntCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680C514BBB16900BFE272 /* LLIntCommon.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F4680CB14BBB17200BFE272 /* LLIntOfflineAsmConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680C614BBB16900BFE272 /* LLIntOfflineAsmConfig.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F4680CC14BBB17A00BFE272 /* LowLevelInterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680C714BBB16900BFE272 /* LowLevelInterpreter.cpp */; };
+               0F4680CD14BBB17D00BFE272 /* LowLevelInterpreter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680C814BBB16900BFE272 /* LowLevelInterpreter.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F4680D214BBD16500BFE272 /* LLIntData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680CE14BBB3D100BFE272 /* LLIntData.cpp */; };
+               0F4680D314BBD16700BFE272 /* LLIntData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680CF14BBB3D100BFE272 /* LLIntData.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F4680D414BBD24900BFE272 /* HostCallReturnValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */; };
+               0F4680D514BBD24B00BFE272 /* HostCallReturnValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F55F0F414D1063900AC7649 /* AbstractPC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F55F0F114D1063600AC7649 /* AbstractPC.cpp */; };
                0F55F0F514D1063C00AC7649 /* AbstractPC.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F55F0F214D1063600AC7649 /* AbstractPC.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F5F08CF146C7633000472A9 /* UnconditionalFinalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */; settings = {ATTRIBUTES = (Private, ); }; };
                86B99AE3117E578100DF5A90 /* StringBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86B99AE1117E578100DF5A90 /* StringBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
                86BB09C0138E381B0056702F /* DFGRepatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86BB09BE138E381B0056702F /* DFGRepatch.cpp */; };
                86BB09C1138E381B0056702F /* DFGRepatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 86BB09BF138E381B0056702F /* DFGRepatch.h */; };
-               86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */; };
+               86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
                86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86C568DD11A213EE0007F7F0 /* MacroAssemblerARM.cpp */; };
                86C568E111A213EE0007F7F0 /* MacroAssemblerMIPS.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C568DE11A213EE0007F7F0 /* MacroAssemblerMIPS.h */; };
                86C568E211A213EE0007F7F0 /* MIPSAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C568DF11A213EE0007F7F0 /* MIPSAssembler.h */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
+               0F4680B114BA811500BFE272 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 0F4680A914BA7FD900BFE272;
+                       remoteInfo = "LLInt Offsets";
+               };
+               0F4680B314BA821400BFE272 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 0F46808E14BA7E5E00BFE272;
+                       remoteInfo = JSCLLIntOffsetsExtractor;
+               };
                141214BE0A49190E00480255 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXCopyFilesBuildPhase section */
+               0F46808D14BA7E5E00BFE272 /* CopyFiles */ = {
+                       isa = PBXCopyFilesBuildPhase;
+                       buildActionMask = 2147483647;
+                       dstPath = /usr/share/man/man1/;
+                       dstSubfolderSpec = 0;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 1;
+               };
                5DBB1511131D0B130056AD36 /* Copy Support Script */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 12;
                0BAC949E1338728400CF135B /* ThreadRestrictionVerifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadRestrictionVerifier.h; sourceTree = "<group>"; };
                0BCD83541485841200EA2003 /* TemporaryChange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemporaryChange.h; sourceTree = "<group>"; };
                0BF28A2811A33DC300638F84 /* SizeLimits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SizeLimits.cpp; sourceTree = "<group>"; };
+               0F0B839514BCF45A00885B4F /* LLIntEntrypoints.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntEntrypoints.cpp; path = llint/LLIntEntrypoints.cpp; sourceTree = "<group>"; };
+               0F0B839614BCF45A00885B4F /* LLIntEntrypoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntEntrypoints.h; path = llint/LLIntEntrypoints.h; sourceTree = "<group>"; };
+               0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; };
+               0F0B839814BCF45A00885B4F /* LLIntThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntThunks.h; path = llint/LLIntThunks.h; sourceTree = "<group>"; };
                0F0B83A514BCF50400885B4F /* CodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeType.h; sourceTree = "<group>"; };
                0F0B83A814BCF55E00885B4F /* HandlerInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HandlerInfo.h; sourceTree = "<group>"; };
                0F0B83AA14BCF5B900885B4F /* ExpressionRangeInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExpressionRangeInfo.h; sourceTree = "<group>"; };
                0F0B83B314BCF85E00885B4F /* MethodCallLinkInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MethodCallLinkInfo.h; sourceTree = "<group>"; };
                0F0B83B614BCF8DF00885B4F /* GlobalResolveInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GlobalResolveInfo.h; sourceTree = "<group>"; };
                0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallReturnOffsetToBytecodeOffset.h; sourceTree = "<group>"; };
+               0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLIntCallLinkInfo.h; sourceTree = "<group>"; };
                0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonSlowPaths.h; sourceTree = "<group>"; };
                0F16D724142C39A200CF784A /* BitVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BitVector.cpp; sourceTree = "<group>"; };
                0F21C26614BE5F5E00ADC64B /* JITDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITDriver.h; sourceTree = "<group>"; };
+               0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeSpecializationKind.h; sourceTree = "<group>"; };
+               0F21C27A14BE727300ADC64B /* ExecutionHarness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutionHarness.h; sourceTree = "<group>"; };
+               0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeConventions.h; sourceTree = "<group>"; };
                0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakReferenceHarvester.h; sourceTree = "<group>"; };
                0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DFGCodeBlocks.cpp; sourceTree = "<group>"; };
                0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFGCodeBlocks.h; sourceTree = "<group>"; };
                0F431736146BAC65007E3890 /* ListableHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ListableHandler.h; sourceTree = "<group>"; };
                0F46807F14BA572700BFE272 /* JITExceptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITExceptions.cpp; sourceTree = "<group>"; };
                0F46808014BA572700BFE272 /* JITExceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITExceptions.h; sourceTree = "<group>"; };
+               0F46808F14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; };
+               0F46809D14BA7F8200BFE272 /* LLIntExceptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntExceptions.cpp; path = llint/LLIntExceptions.cpp; sourceTree = "<group>"; };
+               0F46809E14BA7F8200BFE272 /* LLIntExceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntExceptions.h; path = llint/LLIntExceptions.h; sourceTree = "<group>"; };
+               0F46809F14BA7F8200BFE272 /* LLIntSlowPaths.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntSlowPaths.cpp; path = llint/LLIntSlowPaths.cpp; sourceTree = "<group>"; };
+               0F4680A014BA7F8200BFE272 /* LLIntSlowPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntSlowPaths.h; path = llint/LLIntSlowPaths.h; sourceTree = "<group>"; };
+               0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntOffsetsExtractor.cpp; path = llint/LLIntOffsetsExtractor.cpp; sourceTree = "<group>"; };
+               0F4680C514BBB16900BFE272 /* LLIntCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntCommon.h; path = llint/LLIntCommon.h; sourceTree = "<group>"; };
+               0F4680C614BBB16900BFE272 /* LLIntOfflineAsmConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntOfflineAsmConfig.h; path = llint/LLIntOfflineAsmConfig.h; sourceTree = "<group>"; };
+               0F4680C714BBB16900BFE272 /* LowLevelInterpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LowLevelInterpreter.cpp; path = llint/LowLevelInterpreter.cpp; sourceTree = "<group>"; };
+               0F4680C814BBB16900BFE272 /* LowLevelInterpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LowLevelInterpreter.h; path = llint/LowLevelInterpreter.h; sourceTree = "<group>"; };
+               0F4680CE14BBB3D100BFE272 /* LLIntData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntData.cpp; path = llint/LLIntData.cpp; sourceTree = "<group>"; };
+               0F4680CF14BBB3D100BFE272 /* LLIntData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntData.h; path = llint/LLIntData.h; sourceTree = "<group>"; };
+               0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HostCallReturnValue.cpp; sourceTree = "<group>"; };
+               0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HostCallReturnValue.h; sourceTree = "<group>"; };
                0F55F0F114D1063600AC7649 /* AbstractPC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AbstractPC.cpp; sourceTree = "<group>"; };
                0F55F0F214D1063600AC7649 /* AbstractPC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbstractPC.h; sourceTree = "<group>"; };
                0F5F08CC146BE602000472A9 /* DFGByteCodeCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGByteCodeCache.h; path = dfg/DFGByteCodeCache.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
+               0F46808C14BA7E5E00BFE272 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                1412111E0A48793C00480255 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                                141211200A48793C00480255 /* minidom */,
                                14BD59BF0A3E8F9000BAF59C /* testapi */,
                                6511230514046A4C002B101D /* testRegExp */,
+                               0F46808F14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */,
                        );
                        name = Products;
                        sourceTree = "<group>";
                                F5C290E60284F98E018635CA /* JavaScriptCorePrefix.h */,
                                45E12D8806A49B0F00E9DF84 /* jsc.cpp */,
                                F68EBB8C0255D4C601FF60F7 /* config.h */,
+                               0F46809C14BA7F4D00BFE272 /* llint */,
                                1432EBD70A34CAD400717B9F /* API */,
                                9688CB120ED12B4E001D649F /* assembler */,
                                969A078F0ED1D3AE00F1F681 /* bytecode */,
                        tabWidth = 4;
                        usesTabs = 0;
                };
+               0F46809C14BA7F4D00BFE272 /* llint */ = {
+                       isa = PBXGroup;
+                       children = (
+                               0F0B839514BCF45A00885B4F /* LLIntEntrypoints.cpp */,
+                               0F0B839614BCF45A00885B4F /* LLIntEntrypoints.h */,
+                               0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */,
+                               0F0B839814BCF45A00885B4F /* LLIntThunks.h */,
+                               0F4680CE14BBB3D100BFE272 /* LLIntData.cpp */,
+                               0F4680CF14BBB3D100BFE272 /* LLIntData.h */,
+                               0F4680C514BBB16900BFE272 /* LLIntCommon.h */,
+                               0F4680C614BBB16900BFE272 /* LLIntOfflineAsmConfig.h */,
+                               0F4680C714BBB16900BFE272 /* LowLevelInterpreter.cpp */,
+                               0F4680C814BBB16900BFE272 /* LowLevelInterpreter.h */,
+                               0F46809D14BA7F8200BFE272 /* LLIntExceptions.cpp */,
+                               0F46809E14BA7F8200BFE272 /* LLIntExceptions.h */,
+                               0F46809F14BA7F8200BFE272 /* LLIntSlowPaths.cpp */,
+                               0F4680A014BA7F8200BFE272 /* LLIntSlowPaths.h */,
+                               0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */,
+                       );
+                       name = llint;
+                       sourceTree = "<group>";
+               };
                141211000A48772600480255 /* tests */ = {
                        isa = PBXGroup;
                        children = (
                1429D92C0ED22D7000B89619 /* jit */ = {
                        isa = PBXGroup;
                        children = (
+                               0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */,
+                               0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */,
                                0F46807F14BA572700BFE272 /* JITExceptions.cpp */,
                                0F46808014BA572700BFE272 /* JITExceptions.h */,
                                0FD82E37141AB14200179C94 /* CompactJITCodeMap.h */,
                7EF6E0BB0EB7A1EC0079AFAF /* runtime */ = {
                        isa = PBXGroup;
                        children = (
+                               0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */,
+                               0F21C27A14BE727300ADC64B /* ExecutionHarness.h */,
                                0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */,
                                BCF605110E203EF800B9A64D /* ArgList.cpp */,
                                BCF605120E203EF800B9A64D /* ArgList.h */,
                969A078F0ED1D3AE00F1F681 /* bytecode */ = {
                        isa = PBXGroup;
                        children = (
+                               0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */,
+                               0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */,
                                0F9FC8BF14E1B5FB00D52AE0 /* PolymorphicPutByIdList.cpp */,
                                0F9FC8C014E1B5FB00D52AE0 /* PolymorphicPutByIdList.h */,
                                0F9FC8C114E1B5FB00D52AE0 /* PutKind.h */,
                                86704B8A12DBA33700A9FE7B /* YarrPattern.h in Headers */,
                                86704B4312DB8A8100A9FE7B /* YarrSyntaxChecker.h in Headers */,
                                0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */,
+                               0F4680A314BA7F8D00BFE272 /* LLIntExceptions.h in Headers */,
+                               0F4680A514BA7F8D00BFE272 /* LLIntSlowPaths.h in Headers */,
                                0F46808214BA572D00BFE272 /* JITExceptions.h in Headers */,
+                               0F4680CA14BBB16C00BFE272 /* LLIntCommon.h in Headers */,
+                               0F4680CB14BBB17200BFE272 /* LLIntOfflineAsmConfig.h in Headers */,
+                               0F4680CD14BBB17D00BFE272 /* LowLevelInterpreter.h in Headers */,
+                               0F4680D314BBD16700BFE272 /* LLIntData.h in Headers */,
+                               0F4680D514BBD24B00BFE272 /* HostCallReturnValue.h in Headers */,
+                               0F0B839B14BCF46000885B4F /* LLIntEntrypoints.h in Headers */,
+                               0F0B839D14BCF46600885B4F /* LLIntThunks.h in Headers */,
                                0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
                                0F0B83A914BCF56200885B4F /* HandlerInfo.h in Headers */,
                                0F0B83AB14BCF5BB00885B4F /* ExpressionRangeInfo.h in Headers */,
                                0F0B83B514BCF86200885B4F /* MethodCallLinkInfo.h in Headers */,
                                0F0B83B714BCF8E100885B4F /* GlobalResolveInfo.h in Headers */,
                                0F0B83B914BCF95F00885B4F /* CallReturnOffsetToBytecodeOffset.h in Headers */,
+                               0F0FC45A14BD15F500B81154 /* LLIntCallLinkInfo.h in Headers */,
                                0F21C26814BE5F6800ADC64B /* JITDriver.h in Headers */,
+                               0F21C27C14BE727600ADC64B /* ExecutionHarness.h in Headers */,
+                               0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
+                               0F21C27F14BEAA8200ADC64B /* BytecodeConventions.h in Headers */,
                                0F7B294A14C3CD29007C3DB1 /* DFGCCallHelpers.h in Headers */,
                                0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */,
                                0F7B294C14C3CD43007C3DB1 /* DFGByteCodeCache.h in Headers */,
 /* End PBXHeadersBuildPhase section */
 
 /* Begin PBXNativeTarget section */
+               0F46808E14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 0F46809A14BA7E5F00BFE272 /* Build configuration list for PBXNativeTarget "JSCLLIntOffsetsExtractor" */;
+                       buildPhases = (
+                               0F46808B14BA7E5E00BFE272 /* Sources */,
+                               0F46808C14BA7E5E00BFE272 /* Frameworks */,
+                               0F46808D14BA7E5E00BFE272 /* CopyFiles */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               0F4680B214BA811500BFE272 /* PBXTargetDependency */,
+                       );
+                       name = JSCLLIntOffsetsExtractor;
+                       productName = JSCLLIntOffsetsExtractor;
+                       productReference = 0F46808F14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */;
+                       productType = "com.apple.product-type.tool";
+               };
                1412111F0A48793C00480255 /* minidom */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = 141211390A48798400480255 /* Build configuration list for PBXNativeTarget "minidom" */;
                                14BD59BE0A3E8F9000BAF59C /* testapi */,
                                932F5BDA0822A1C700736975 /* jsc */,
                                651122F714046A4C002B101D /* testRegExp */,
+                               0F46808E14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */,
+                               0F4680A914BA7FD900BFE272 /* LLInt Offsets */,
                        );
                };
 /* End PBXProject section */
 
 /* Begin PBXShellScriptBuildPhase section */
+               0F4680AA14BA7FD900BFE272 /* Generate Derived Sources */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "$(SRCROOT)/llint/LowLevelAssembler.asm",
+                       );
+                       name = "Generate Derived Sources";
+                       outputPaths = (
+                               "$(BUILT_PRODUCTS_DIR)/LLIntOffsets/LLIntDesiredOffsets.h",
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "mkdir -p \"${BUILT_PRODUCTS_DIR}/LLIntOffsets/\"\n\n/usr/bin/env ruby \"${SRCROOT}/offlineasm/generate_offset_extractor.rb\" \"${SRCROOT}/llint/LowLevelInterpreter.asm\" \"${BUILT_PRODUCTS_DIR}/LLIntOffsets/LLIntDesiredOffsets.h\"\n";
+               };
                3713F014142905240036387F /* Check For Inappropriate Objective-C Class Names */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/sh;
-                       shellScript = "mkdir -p \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore/docs\"\ncd \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore\"\n\n/bin/ln -sfh \"${SRCROOT}\" JavaScriptCore\nexport JavaScriptCore=\"JavaScriptCore\"\nexport BUILT_PRODUCTS_DIR=\"../..\"\n\nmake --no-builtin-rules -f \"JavaScriptCore/DerivedSources.make\" -j `/usr/sbin/sysctl -n hw.ncpu`\n";
+                       shellScript = "mkdir -p \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore/docs\"\ncd \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore\"\n\n/bin/ln -sfh \"${SRCROOT}\" JavaScriptCore\nexport JavaScriptCore=\"JavaScriptCore\"\nexport BUILT_PRODUCTS_DIR=\"../..\"\n\nmake --no-builtin-rules -f \"JavaScriptCore/DerivedSources.make\" -j `/usr/sbin/sysctl -n hw.ncpu`\n\n/usr/bin/env ruby JavaScriptCore/offlineasm/asm.rb JavaScriptCore/llint/LowLevelInterpreter.asm ${BUILT_PRODUCTS_DIR}/JSCLLIntOffsetsExtractor LLIntAssembly.h\n";
                };
                9319586B09D9F91A00A56FD4 /* Check For Global Initializers */ = {
                        isa = PBXShellScriptBuildPhase;
 /* End PBXShellScriptBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */
+               0F46808B14BA7E5E00BFE272 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               0F4680A714BA7FA100BFE272 /* LLIntOffsetsExtractor.cpp in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                1412111D0A48793C00480255 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                                86704B8612DBA33700A9FE7B /* YarrJIT.cpp in Sources */,
                                86704B8912DBA33700A9FE7B /* YarrPattern.cpp in Sources */,
                                86704B4212DB8A8100A9FE7B /* YarrSyntaxChecker.cpp in Sources */,
+                               0F4680A414BA7F8D00BFE272 /* LLIntSlowPaths.cpp in Sources */,
+                               0F4680A814BA7FAB00BFE272 /* LLIntExceptions.cpp in Sources */,
                                0F46808314BA573100BFE272 /* JITExceptions.cpp in Sources */,
+                               0F4680CC14BBB17A00BFE272 /* LowLevelInterpreter.cpp in Sources */,
+                               0F4680D214BBD16500BFE272 /* LLIntData.cpp in Sources */,
+                               0F4680D414BBD24900BFE272 /* HostCallReturnValue.cpp in Sources */,
+                               0F0B839A14BCF45D00885B4F /* LLIntEntrypoints.cpp in Sources */,
+                               0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */,
                                0F0B83B014BCF71600885B4F /* CallLinkInfo.cpp in Sources */,
                                0F0B83B414BCF86000885B4F /* MethodCallLinkInfo.cpp in Sources */,
                                F69E86C314C6E551002C2C62 /* NumberOfCores.cpp in Sources */,
 /* End PBXSourcesBuildPhase section */
 
 /* Begin PBXTargetDependency section */
+               0F4680B214BA811500BFE272 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 0F4680A914BA7FD900BFE272 /* LLInt Offsets */;
+                       targetProxy = 0F4680B114BA811500BFE272 /* PBXContainerItemProxy */;
+               };
+               0F4680B414BA821400BFE272 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 0F46808E14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */;
+                       targetProxy = 0F4680B314BA821400BFE272 /* PBXContainerItemProxy */;
+               };
                141214BF0A49190E00480255 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = 1412111F0A48793C00480255 /* minidom */;
 /* End PBXTargetDependency section */
 
 /* Begin XCBuildConfiguration section */
+               0F46809614BA7E5E00BFE272 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+                               COPY_PHASE_STRIP = NO;
+                               GCC_C_LANGUAGE_STANDARD = gnu99;
+                               GCC_DYNAMIC_NO_PIC = NO;
+                               GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+                               GCC_OPTIMIZATION_LEVEL = 0;
+                               GCC_PREPROCESSOR_DEFINITIONS = (
+                                       "DEBUG=1",
+                                       "$(inherited)",
+                               );
+                               GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+                               GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+                               GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               "HEADER_SEARCH_PATHS[arch=*]" = (
+                                       .,
+                                       icu,
+                                       "$(BUILT_PRODUCTS_DIR)/LLIntOffsets",
+                                       "$(HEADER_SEARCH_PATHS)",
+                               );
+                               MACOSX_DEPLOYMENT_TARGET = 10.7;
+                               ONLY_ACTIVE_ARCH = NO;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                               SDKROOT = macosx;
+                               USER_HEADER_SEARCH_PATHS = ". icu $(BUILT_PRODUCTS_DIR)/LLIntOffsets $(HEADER_SEARCH_PATHS)";
+                       };
+                       name = Debug;
+               };
+               0F46809714BA7E5E00BFE272 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+                               COPY_PHASE_STRIP = YES;
+                               DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                               GCC_C_LANGUAGE_STANDARD = gnu99;
+                               GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+                               GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+                               GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               "HEADER_SEARCH_PATHS[arch=*]" = (
+                                       .,
+                                       icu,
+                                       "$(BUILT_PRODUCTS_DIR)/LLIntOffsets$(HEADER_SEARCH_PATHS)",
+                               );
+                               MACOSX_DEPLOYMENT_TARGET = 10.7;
+                               ONLY_ACTIVE_ARCH = NO;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                               SDKROOT = macosx;
+                               USER_HEADER_SEARCH_PATHS = ". icu $(BUILT_PRODUCTS_DIR)/LLIntOffsets $(HEADER_SEARCH_PATHS)";
+                       };
+                       name = Release;
+               };
+               0F46809814BA7E5E00BFE272 /* Profiling */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+                               COPY_PHASE_STRIP = YES;
+                               DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                               GCC_C_LANGUAGE_STANDARD = gnu99;
+                               GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+                               GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+                               GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               "HEADER_SEARCH_PATHS[arch=*]" = (
+                                       .,
+                                       icu,
+                                       "$(BUILT_PRODUCTS_DIR)/LLIntOffsets",
+                                       "$(HEADER_SEARCH_PATHS)",
+                               );
+                               MACOSX_DEPLOYMENT_TARGET = 10.7;
+                               ONLY_ACTIVE_ARCH = NO;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                               SDKROOT = macosx;
+                               USER_HEADER_SEARCH_PATHS = ". icu $(BUILT_PRODUCTS_DIR)/LLIntOffsets $(HEADER_SEARCH_PATHS)";
+                       };
+                       name = Profiling;
+               };
+               0F46809914BA7E5E00BFE272 /* Production */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+                               COPY_PHASE_STRIP = YES;
+                               DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                               GCC_C_LANGUAGE_STANDARD = gnu99;
+                               GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+                               GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+                               GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               "HEADER_SEARCH_PATHS[arch=*]" = (
+                                       .,
+                                       icu,
+                                       "$(BUILT_PRODUCTS_DIR)/LLIntOffsets",
+                                       "$(HEADER_SEARCH_PATHS)",
+                               );
+                               MACOSX_DEPLOYMENT_TARGET = 10.7;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                               SDKROOT = macosx;
+                               USER_HEADER_SEARCH_PATHS = ". icu $(BUILT_PRODUCTS_DIR)/LLIntOffsets $(HEADER_SEARCH_PATHS)";
+                       };
+                       name = Production;
+               };
+               0F4680AD14BA7FD900BFE272 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "Derived Sources copy";
+                       };
+                       name = Debug;
+               };
+               0F4680AE14BA7FD900BFE272 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "Derived Sources copy";
+                       };
+                       name = Release;
+               };
+               0F4680AF14BA7FD900BFE272 /* Profiling */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "Derived Sources copy";
+                       };
+                       name = Profiling;
+               };
+               0F4680B014BA7FD900BFE272 /* Production */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "Derived Sources copy";
+                       };
+                       name = Production;
+               };
                1412113A0A48798400480255 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
+               0F46809A14BA7E5F00BFE272 /* Build configuration list for PBXNativeTarget "JSCLLIntOffsetsExtractor" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               0F46809614BA7E5E00BFE272 /* Debug */,
+                               0F46809714BA7E5E00BFE272 /* Release */,
+                               0F46809814BA7E5E00BFE272 /* Profiling */,
+                               0F46809914BA7E5E00BFE272 /* Production */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Production;
+               };
+               0F4680AC14BA7FD900BFE272 /* Build configuration list for PBXAggregateTarget "LLInt Offsets" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               0F4680AD14BA7FD900BFE272 /* Debug */,
+                               0F4680AE14BA7FD900BFE272 /* Release */,
+                               0F4680AF14BA7FD900BFE272 /* Profiling */,
+                               0F4680B014BA7FD900BFE272 /* Production */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Production;
+               };
                141211390A48798400480255 /* Build configuration list for PBXNativeTarget "minidom" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
index ba77229..e1a96d7 100644 (file)
@@ -113,6 +113,7 @@ SOURCES += \
     interpreter/RegisterFile.cpp \
     jit/ExecutableAllocatorFixedVMPool.cpp \
     jit/ExecutableAllocator.cpp \
+    jit/HostCallReturnValue.cpp \
     jit/JITArithmetic.cpp \
     jit/JITArithmetic32_64.cpp \
     jit/JITCall.cpp \
index 6177c91..2c07d13 100644 (file)
@@ -34,7 +34,7 @@
 #define GLOBAL_THUNK_ID reinterpret_cast<void*>(static_cast<intptr_t>(-1))
 #define REGEXP_CODE_ID reinterpret_cast<void*>(static_cast<intptr_t>(-2))
 
-#include <MacroAssembler.h>
+#include "MacroAssembler.h"
 #include <wtf/DataLog.h>
 #include <wtf/Noncopyable.h>
 
index c59d151..3d7d845 100644 (file)
@@ -31,8 +31,6 @@
 #include "RefPtr.h"
 #include "UnusedParam.h"
 
-#if ENABLE(ASSEMBLER)
-
 // ASSERT_VALID_CODE_POINTER checks that ptr is a non-null pointer, and that it is a valid
 // instruction address on the platform (for example, check any alignment requirements).
 #if CPU(ARM_THUMB2)
@@ -273,6 +271,14 @@ public:
     {
         ASSERT_VALID_CODE_POINTER(m_value);
     }
+    
+    static MacroAssemblerCodePtr createFromExecutableAddress(void* value)
+    {
+        ASSERT_VALID_CODE_POINTER(value);
+        MacroAssemblerCodePtr result;
+        result.m_value = value;
+        return result;
+    }
 
     explicit MacroAssemblerCodePtr(ReturnAddressPtr ra)
         : m_value(ra.value())
@@ -360,6 +366,4 @@ private:
 
 } // namespace JSC
 
-#endif // ENABLE(ASSEMBLER)
-
 #endif // MacroAssemblerCodeRef_h
diff --git a/Source/JavaScriptCore/bytecode/BytecodeConventions.h b/Source/JavaScriptCore/bytecode/BytecodeConventions.h
new file mode 100644 (file)
index 0000000..f33b060
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2012 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 BytecodeConventions_h
+#define BytecodeConventions_h
+
+// Register numbers used in bytecode operations have different meaning according to their ranges:
+//      0x80000000-0xFFFFFFFF  Negative indices from the CallFrame pointer are entries in the call frame, see RegisterFile.h.
+//      0x00000000-0x3FFFFFFF  Forwards indices from the CallFrame pointer are local vars and temporaries with the function's callframe.
+//      0x40000000-0x7FFFFFFF  Positive indices from 0x40000000 specify entries in the constant pool on the CodeBlock.
+static const int FirstConstantRegisterIndex = 0x40000000;
+
+#endif // BytecodeConventions_h
+
index f3fd5bb..7f9e9ee 100644 (file)
 #include "CallLinkStatus.h"
 
 #include "CodeBlock.h"
+#include "LLIntCallLinkInfo.h"
 
 namespace JSC {
 
+CallLinkStatus CallLinkStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex)
+{
+    UNUSED_PARAM(profiledBlock);
+    UNUSED_PARAM(bytecodeIndex);
+#if ENABLE(LLINT)
+    Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
+    LLIntCallLinkInfo* callLinkInfo = instruction[4].u.callLinkInfo;
+    
+    return CallLinkStatus(callLinkInfo->lastSeenCallee.get(), false);
+#else
+    return CallLinkStatus(0, false);
+#endif
+}
+
 CallLinkStatus CallLinkStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex)
 {
     UNUSED_PARAM(profiledBlock);
     UNUSED_PARAM(bytecodeIndex);
 #if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
-    return CallLinkStatus(
-        profiledBlock->getCallLinkInfo(bytecodeIndex).lastSeenCallee.get(),
-        profiledBlock->couldTakeSlowCase(bytecodeIndex));
+    if (!profiledBlock->numberOfCallLinkInfos())
+        return computeFromLLInt(profiledBlock, bytecodeIndex);
+    
+    if (profiledBlock->couldTakeSlowCase(bytecodeIndex))
+        return CallLinkStatus(0, true);
+    
+    JSFunction* target = profiledBlock->getCallLinkInfo(bytecodeIndex).lastSeenCallee.get();
+    if (!target)
+        return computeFromLLInt(profiledBlock, bytecodeIndex);
+    
+    return CallLinkStatus(target, false);
 #else
     return CallLinkStatus(0, false);
 #endif
index e1c7410..5f72019 100644 (file)
@@ -47,15 +47,17 @@ public:
     
     static CallLinkStatus computeFor(CodeBlock*, unsigned bytecodeIndex);
     
-    bool isSet() const { return !!m_callTarget; }
+    bool isSet() const { return !!m_callTarget || m_couldTakeSlowPath; }
     
-    bool operator!() const { return !m_callTarget; }
+    bool operator!() const { return !isSet(); }
     
     bool couldTakeSlowPath() const { return m_couldTakeSlowPath; }
     
     JSFunction* callTarget() const { return m_callTarget; }
     
 private:
+    static CallLinkStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex);
+    
     JSFunction* m_callTarget;
     bool m_couldTakeSlowPath;
 };
index 5e366a6..7c8eab9 100644 (file)
@@ -42,6 +42,7 @@
 #include "JSFunction.h"
 #include "JSStaticScopeObject.h"
 #include "JSValue.h"
+#include "LowLevelInterpreter.h"
 #include "RepatchBuffer.h"
 #include "UStringConcatenate.h"
 #include <stdio.h>
@@ -356,10 +357,10 @@ void CodeBlock::dump(ExecState* exec) const
     for (size_t i = 0; i < instructions().size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(instructions()[i].u.opcode)])
         ++instructionCount;
 
-    dataLog("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n",
+    dataLog("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s); %d variable(s)\n\n",
         static_cast<unsigned long>(instructionCount),
         static_cast<unsigned long>(instructions().size() * sizeof(Instruction)),
-        this, m_numParameters, m_numCalleeRegisters);
+        this, m_numParameters, m_numCalleeRegisters, m_numVars);
 
     Vector<Instruction>::const_iterator begin = instructions().begin();
     Vector<Instruction>::const_iterator end = instructions().end();
@@ -896,6 +897,14 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printPutByIdOp(exec, location, it, "put_by_id_transition");
             break;
         }
+        case op_put_by_id_transition_direct: {
+            printPutByIdOp(exec, location, it, "put_by_id_transition_direct");
+            break;
+        }
+        case op_put_by_id_transition_normal: {
+            printPutByIdOp(exec, location, it, "put_by_id_transition_normal");
+            break;
+        }
         case op_put_by_id_generic: {
             printPutByIdOp(exec, location, it, "put_by_id_generic");
             break;
@@ -1453,6 +1462,7 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other, SymbolTable* symTab)
 {
     setNumParameters(other.numParameters());
     optimizeAfterWarmUp();
+    jitAfterWarmUp();
     
     if (other.m_rareData) {
         createRareDataIfNecessary();
@@ -1501,6 +1511,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlo
     ASSERT(m_source);
     
     optimizeAfterWarmUp();
+    jitAfterWarmUp();
 
 #if DUMP_CODE_BLOCK_STATISTICS
     liveCodeBlockSet.add(this);
@@ -1518,7 +1529,11 @@ CodeBlock::~CodeBlock()
 #if ENABLE(VERBOSE_VALUE_PROFILE)
     dumpValueProfiles();
 #endif
-    
+
+#if ENABLE(LLINT)    
+    while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end())
+        m_incomingLLIntCalls.begin()->remove();
+#endif // ENABLE(LLINT)
 #if ENABLE(JIT)
     // We may be destroyed before any CodeBlocks that refer to us are destroyed.
     // Consider that two CodeBlocks become unreachable at the same time. There
@@ -1730,8 +1745,69 @@ void CodeBlock::finalizeUnconditionally()
 #else
     static const bool verboseUnlinking = false;
 #endif
-#endif
+#endif // ENABLE(JIT)
     
+#if ENABLE(LLINT)
+    Interpreter* interpreter = m_globalData->interpreter;
+    // interpreter->classicEnabled() returns true if the old C++ interpreter is enabled. If that's enabled
+    // then we're not using LLInt.
+    if (!interpreter->classicEnabled()) {
+        for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) {
+            Instruction* curInstruction = &instructions()[m_propertyAccessInstructions[i]];
+            switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) {
+            case op_get_by_id:
+            case op_put_by_id:
+                if (!curInstruction[4].u.structure || Heap::isMarked(curInstruction[4].u.structure.get()))
+                    break;
+                if (verboseUnlinking)
+                    dataLog("Clearing LLInt property access with structure %p.\n", curInstruction[4].u.structure.get());
+                curInstruction[4].u.structure.clear();
+                curInstruction[5].u.operand = 0;
+                break;
+            case op_put_by_id_transition_direct:
+            case op_put_by_id_transition_normal:
+                if (Heap::isMarked(curInstruction[4].u.structure.get())
+                    && Heap::isMarked(curInstruction[6].u.structure.get())
+                    && Heap::isMarked(curInstruction[7].u.structureChain.get()))
+                    break;
+                if (verboseUnlinking) {
+                    dataLog("Clearing LLInt put transition with structures %p -> %p, chain %p.\n",
+                            curInstruction[4].u.structure.get(),
+                            curInstruction[6].u.structure.get(),
+                            curInstruction[7].u.structureChain.get());
+                }
+                curInstruction[4].u.structure.clear();
+                curInstruction[6].u.structure.clear();
+                curInstruction[7].u.structureChain.clear();
+                curInstruction[0].u.opcode = interpreter->getOpcode(op_put_by_id);
+                break;
+            default:
+                ASSERT_NOT_REACHED();
+            }
+        }
+        for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i) {
+            Instruction* curInstruction = &instructions()[m_globalResolveInstructions[i]];
+            ASSERT(interpreter->getOpcodeID(curInstruction[0].u.opcode) == op_resolve_global
+                   || interpreter->getOpcodeID(curInstruction[0].u.opcode) == op_resolve_global_dynamic);
+            if (!curInstruction[3].u.structure || Heap::isMarked(curInstruction[3].u.structure.get()))
+                continue;
+            if (verboseUnlinking)
+                dataLog("Clearing LLInt global resolve cache with structure %p.\n", curInstruction[3].u.structure.get());
+            curInstruction[3].u.structure.clear();
+            curInstruction[4].u.operand = 0;
+        }
+        for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) {
+            if (m_llintCallLinkInfos[i].isLinked() && !Heap::isMarked(m_llintCallLinkInfos[i].callee.get())) {
+                if (verboseUnlinking)
+                    dataLog("Clearing LLInt call from %p.\n", this);
+                m_llintCallLinkInfos[i].unlink();
+            }
+            if (!!m_llintCallLinkInfos[i].lastSeenCallee && !Heap::isMarked(m_llintCallLinkInfos[i].lastSeenCallee.get()))
+                m_llintCallLinkInfos[i].lastSeenCallee.clear();
+        }
+    }
+#endif // ENABLE(LLINT)
+
 #if ENABLE(DFG_JIT)
     // Check if we're not live. If we are, then jettison.
     if (!(shouldImmediatelyAssumeLivenessDuringScan() || m_dfgData->livenessHasBeenProved)) {
@@ -1754,7 +1830,7 @@ void CodeBlock::finalizeUnconditionally()
         for (unsigned i = 0; i < numberOfCallLinkInfos(); ++i) {
             if (callLinkInfo(i).isLinked() && !Heap::isMarked(callLinkInfo(i).callee.get())) {
                 if (verboseUnlinking)
-                    dataLog("Clearing call from %p.\n", this);
+                    dataLog("Clearing call from %p to %p.\n", this, callLinkInfo(i).callee.get());
                 callLinkInfo(i).unlink(*m_globalData, repatchBuffer);
             }
             if (!!callLinkInfo(i).lastSeenCallee
@@ -1852,10 +1928,12 @@ void CodeBlock::stronglyVisitStrongReferences(SlotVisitor& visitor)
     for (size_t i = 0; i < m_functionDecls.size(); ++i)
         visitor.append(&m_functionDecls[i]);
 #if ENABLE(CLASSIC_INTERPRETER)
-    for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i)
-        visitStructures(visitor, &instructions()[m_propertyAccessInstructions[i]]);
-    for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)
-        visitStructures(visitor, &instructions()[m_globalResolveInstructions[i]]);
+    if (m_globalData->interpreter->classicEnabled()) {
+        for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i)
+            visitStructures(visitor, &instructions()[m_propertyAccessInstructions[i]]);
+        for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)
+            visitStructures(visitor, &instructions()[m_globalResolveInstructions[i]]);
+    }
 #endif
 
 #if ENABLE(DFG_JIT)
@@ -1863,8 +1941,9 @@ void CodeBlock::stronglyVisitStrongReferences(SlotVisitor& visitor)
         // Make sure that executables that we have inlined don't die.
         // FIXME: If they would have otherwise died, we should probably trigger recompilation.
         for (size_t i = 0; i < inlineCallFrames().size(); ++i) {
-            visitor.append(&inlineCallFrames()[i].executable);
-            visitor.append(&inlineCallFrames()[i].callee);
+            InlineCallFrame& inlineCallFrame = inlineCallFrames()[i];
+            visitor.append(&inlineCallFrame.executable);
+            visitor.append(&inlineCallFrame.callee);
         }
     }
 #endif
@@ -2068,12 +2147,18 @@ unsigned CodeBlock::addOrFindConstant(JSValue v)
     }
     return addConstant(v);
 }
-    
+
 #if ENABLE(JIT)
 void CodeBlock::unlinkCalls()
 {
     if (!!m_alternative)
         m_alternative->unlinkCalls();
+#if ENABLE(LLINT)
+    for (size_t i = 0; i < m_llintCallLinkInfos.size(); ++i) {
+        if (m_llintCallLinkInfos[i].isLinked())
+            m_llintCallLinkInfos[i].unlink();
+    }
+#endif
     if (!(m_callLinkInfos.size() || m_methodCallLinkInfos.size()))
         return;
     if (!m_globalData->canUseJIT())
@@ -2088,10 +2173,62 @@ void CodeBlock::unlinkCalls()
 
 void CodeBlock::unlinkIncomingCalls()
 {
+#if ENABLE(LLINT)
+    while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end())
+        m_incomingLLIntCalls.begin()->unlink();
+#endif
+    if (m_incomingCalls.isEmpty())
+        return;
     RepatchBuffer repatchBuffer(this);
     while (m_incomingCalls.begin() != m_incomingCalls.end())
         m_incomingCalls.begin()->unlink(*m_globalData, repatchBuffer);
 }
+
+unsigned CodeBlock::bytecodeOffset(ExecState* exec, ReturnAddressPtr returnAddress)
+{
+#if ENABLE(LLINT)
+    if (returnAddress.value() >= bitwise_cast<void*>(&llint_begin)
+        && returnAddress.value() <= bitwise_cast<void*>(&llint_end)) {
+        ASSERT(exec->codeBlock());
+        ASSERT(exec->codeBlock() == this);
+        ASSERT(JITCode::isBaselineCode(getJITType()));
+        Instruction* instruction = exec->currentVPC();
+        ASSERT(instruction);
+        
+        // The LLInt stores the PC after the call instruction rather than the PC of
+        // the call instruction. This requires some correcting. We rely on the fact
+        // that the preceding instruction must be one of the call instructions, so
+        // either it's a call_varargs or it's a call, construct, or eval.
+        ASSERT(OPCODE_LENGTH(op_call_varargs) <= OPCODE_LENGTH(op_call));
+        ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
+        ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_eval));
+        if (instruction[-OPCODE_LENGTH(op_call_varargs)].u.pointer == bitwise_cast<void*>(llint_op_call_varargs)) {
+            // We know that the preceding instruction must be op_call_varargs because there is no way that
+            // the pointer to the call_varargs could be an operand to the call.
+            instruction -= OPCODE_LENGTH(op_call_varargs);
+            ASSERT(instruction[-OPCODE_LENGTH(op_call)].u.pointer != bitwise_cast<void*>(llint_op_call)
+                   && instruction[-OPCODE_LENGTH(op_call)].u.pointer != bitwise_cast<void*>(llint_op_construct)
+                   && instruction[-OPCODE_LENGTH(op_call)].u.pointer != bitwise_cast<void*>(llint_op_call_eval));
+        } else {
+            // Must be that the last instruction was some op_call.
+            ASSERT(instruction[-OPCODE_LENGTH(op_call)].u.pointer == bitwise_cast<void*>(llint_op_call)
+                   || instruction[-OPCODE_LENGTH(op_call)].u.pointer == bitwise_cast<void*>(llint_op_construct)
+                   || instruction[-OPCODE_LENGTH(op_call)].u.pointer == bitwise_cast<void*>(llint_op_call_eval));
+            instruction -= OPCODE_LENGTH(op_call);
+        }
+        
+        return bytecodeOffset(instruction);
+    }
+#else
+    UNUSED_PARAM(exec);
+#endif
+    if (!m_rareData)
+        return 1;
+    Vector<CallReturnOffsetToBytecodeOffset>& callIndices = m_rareData->m_callReturnIndexVector;
+    if (!callIndices.size())
+        return 1;
+    return binarySearch<CallReturnOffsetToBytecodeOffset, unsigned, getCallReturnOffset>(callIndices.begin(), callIndices.size(), getJITCode().offsetOf(returnAddress.value()))->bytecodeOffset;
+}
 #endif
 
 void CodeBlock::clearEvalCache()
@@ -2187,24 +2324,45 @@ bool FunctionCodeBlock::canCompileWithDFGInternal()
 
 void ProgramCodeBlock::jettison()
 {
-    ASSERT(getJITType() != JITCode::BaselineJIT);
+    ASSERT(JITCode::isOptimizingJIT(getJITType()));
     ASSERT(this == replacement());
     static_cast<ProgramExecutable*>(ownerExecutable())->jettisonOptimizedCode(*globalData());
 }
 
 void EvalCodeBlock::jettison()
 {
-    ASSERT(getJITType() != JITCode::BaselineJIT);
+    ASSERT(JITCode::isOptimizingJIT(getJITType()));
     ASSERT(this == replacement());
     static_cast<EvalExecutable*>(ownerExecutable())->jettisonOptimizedCode(*globalData());
 }
 
 void FunctionCodeBlock::jettison()
 {
-    ASSERT(getJITType() != JITCode::BaselineJIT);
+    ASSERT(JITCode::isOptimizingJIT(getJITType()));
     ASSERT(this == replacement());
     static_cast<FunctionExecutable*>(ownerExecutable())->jettisonOptimizedCodeFor(*globalData(), m_isConstructor ? CodeForConstruct : CodeForCall);
 }
+
+void ProgramCodeBlock::jitCompileImpl(JSGlobalData& globalData)
+{
+    ASSERT(getJITType() == JITCode::InterpreterThunk);
+    ASSERT(this == replacement());
+    return static_cast<ProgramExecutable*>(ownerExecutable())->jitCompile(globalData);
+}
+
+void EvalCodeBlock::jitCompileImpl(JSGlobalData& globalData)
+{
+    ASSERT(getJITType() == JITCode::InterpreterThunk);
+    ASSERT(this == replacement());
+    return static_cast<EvalExecutable*>(ownerExecutable())->jitCompile(globalData);
+}
+
+void FunctionCodeBlock::jitCompileImpl(JSGlobalData& globalData)
+{
+    ASSERT(getJITType() == JITCode::InterpreterThunk);
+    ASSERT(this == replacement());
+    return static_cast<FunctionExecutable*>(ownerExecutable())->jitCompileFor(globalData, m_isConstructor ? CodeForConstruct : CodeForCall);
+}
 #endif
 
 #if ENABLE(VALUE_PROFILER)
index 3091df0..8e6d07b 100644 (file)
@@ -30,6 +30,7 @@
 #ifndef CodeBlock_h
 #define CodeBlock_h
 
+#include "BytecodeConventions.h"
 #include "CallLinkInfo.h"
 #include "CallReturnOffsetToBytecodeOffset.h"
 #include "CodeOrigin.h"
@@ -50,6 +51,7 @@
 #include "JITWriteBarrier.h"
 #include "JSGlobalObject.h"
 #include "JumpTable.h"
+#include "LLIntCallLinkInfo.h"
 #include "LineInfo.h"
 #include "Nodes.h"
 #include "PredictionTracker.h"
 #include <wtf/Vector.h>
 #include "StructureStubInfo.h"
 
-// Register numbers used in bytecode operations have different meaning according to their ranges:
-//      0x80000000-0xFFFFFFFF  Negative indices from the CallFrame pointer are entries in the call frame, see RegisterFile.h.
-//      0x00000000-0x3FFFFFFF  Forwards indices from the CallFrame pointer are local vars and temporaries with the function's callframe.
-//      0x40000000-0x7FFFFFFF  Positive indices from 0x40000000 specify entries in the constant pool on the CodeBlock.
-static const int FirstConstantRegisterIndex = 0x40000000;
-
 namespace JSC {
 
-    class ExecState;
     class DFGCodeBlocks;
+    class ExecState;
+    class LLIntOffsetsExtractor;
 
     inline int unmodifiedArgumentsRegister(int argumentsRegister) { return argumentsRegister - 1; }
 
@@ -83,6 +80,7 @@ namespace JSC {
     class CodeBlock : public UnconditionalFinalizer, public WeakReferenceHarvester {
         WTF_MAKE_FAST_ALLOCATED;
         friend class JIT;
+        friend class LLIntOffsetsExtractor;
     public:
         enum CopyParsedBlockTag { CopyParsedBlock };
     protected:
@@ -123,7 +121,7 @@ namespace JSC {
             while (result->alternative())
                 result = result->alternative();
             ASSERT(result);
-            ASSERT(result->getJITType() == JITCode::BaselineJIT);
+            ASSERT(JITCode::isBaselineCode(result->getJITType()));
             return result;
         }
 #endif
@@ -192,15 +190,7 @@ namespace JSC {
             return *(binarySearch<MethodCallLinkInfo, unsigned, getMethodCallLinkInfoBytecodeIndex>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), bytecodeIndex));
         }
 
-        unsigned bytecodeOffset(ReturnAddressPtr returnAddress)
-        {
-            if (!m_rareData)
-                return 1;
-            Vector<CallReturnOffsetToBytecodeOffset>& callIndices = m_rareData->m_callReturnIndexVector;
-            if (!callIndices.size())
-                return 1;
-            return binarySearch<CallReturnOffsetToBytecodeOffset, unsigned, getCallReturnOffset>(callIndices.begin(), callIndices.size(), getJITCode().offsetOf(returnAddress.value()))->bytecodeOffset;
-        }
+        unsigned bytecodeOffset(ExecState*, ReturnAddressPtr);
 
         unsigned bytecodeOffsetForCallAtIndex(unsigned index)
         {
@@ -221,11 +211,17 @@ namespace JSC {
         {
             m_incomingCalls.push(incoming);
         }
+#if ENABLE(LLINT)
+        void linkIncomingCall(LLIntCallLinkInfo* incoming)
+        {
+            m_incomingLLIntCalls.push(incoming);
+        }
+#endif // ENABLE(LLINT)
         
         void unlinkIncomingCalls();
-#endif
+#endif // ENABLE(JIT)
 
-#if ENABLE(DFG_JIT)
+#if ENABLE(DFG_JIT) || ENABLE(LLINT)
         void setJITCodeMap(PassOwnPtr<CompactJITCodeMap> jitCodeMap)
         {
             m_jitCodeMap = jitCodeMap;
@@ -234,7 +230,9 @@ namespace JSC {
         {
             return m_jitCodeMap.get();
         }
+#endif
         
+#if ENABLE(DFG_JIT)
         void createDFGDataIfNecessary()
         {
             if (!!m_dfgData)
@@ -333,12 +331,11 @@ namespace JSC {
         }
 #endif
 
-#if ENABLE(CLASSIC_INTERPRETER)
         unsigned bytecodeOffset(Instruction* returnAddress)
         {
+            ASSERT(returnAddress >= instructions().begin() && returnAddress < instructions().end());
             return static_cast<Instruction*>(returnAddress) - instructions().begin();
         }
-#endif
 
         void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; }
         bool isNumericCompareFunction() { return m_isNumericCompareFunction; }
@@ -376,6 +373,20 @@ namespace JSC {
         ExecutableMemoryHandle* executableMemory() { return getJITCode().getExecutableMemory(); }
         virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*) = 0;
         virtual void jettison() = 0;
+        bool jitCompile(JSGlobalData& globalData)
+        {
+            if (getJITType() != JITCode::InterpreterThunk) {
+                ASSERT(getJITType() == JITCode::BaselineJIT);
+                return false;
+            }
+#if ENABLE(JIT)
+            jitCompileImpl(globalData);
+            return true;
+#else
+            UNUSED_PARAM(globalData);
+            return false;
+#endif
+        }
         virtual CodeBlock* replacement() = 0;
 
         enum CompileWithDFGState {
@@ -395,13 +406,13 @@ namespace JSC {
 
         bool hasOptimizedReplacement()
         {
-            ASSERT(getJITType() == JITCode::BaselineJIT);
+            ASSERT(JITCode::isBaselineCode(getJITType()));
             bool result = replacement()->getJITType() > getJITType();
 #if !ASSERT_DISABLED
             if (result)
                 ASSERT(replacement()->getJITType() == JITCode::DFGJIT);
             else {
-                ASSERT(replacement()->getJITType() == JITCode::BaselineJIT);
+                ASSERT(JITCode::isBaselineCode(replacement()->getJITType()));
                 ASSERT(replacement() == this);
             }
 #endif
@@ -460,18 +471,21 @@ namespace JSC {
 
         void clearEvalCache();
 
-#if ENABLE(CLASSIC_INTERPRETER)
         void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
         {
-            if (!m_globalData->canUseJIT())
-                m_propertyAccessInstructions.append(propertyAccessInstruction);
+            m_propertyAccessInstructions.append(propertyAccessInstruction);
         }
         void addGlobalResolveInstruction(unsigned globalResolveInstruction)
         {
-            if (!m_globalData->canUseJIT())
-                m_globalResolveInstructions.append(globalResolveInstruction);
+            m_globalResolveInstructions.append(globalResolveInstruction);
         }
         bool hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset);
+#if ENABLE(LLINT)
+        LLIntCallLinkInfo* addLLIntCallLinkInfo()
+        {
+            m_llintCallLinkInfos.append(LLIntCallLinkInfo());
+            return &m_llintCallLinkInfos.last();
+        }
 #endif
 #if ENABLE(JIT)
         void setNumberOfStructureStubInfos(size_t size) { m_structureStubInfos.grow(size); }
@@ -480,8 +494,7 @@ namespace JSC {
 
         void addGlobalResolveInfo(unsigned globalResolveInstruction)
         {
-            if (m_globalData->canUseJIT())
-                m_globalResolveInfos.append(GlobalResolveInfo(globalResolveInstruction));
+            m_globalResolveInfos.append(GlobalResolveInfo(globalResolveInstruction));
         }
         GlobalResolveInfo& globalResolveInfo(int index) { return m_globalResolveInfos[index]; }
         bool hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset);
@@ -492,6 +505,7 @@ namespace JSC {
 
         void addMethodCallLinkInfos(unsigned n) { ASSERT(m_globalData->canUseJIT()); m_methodCallLinkInfos.grow(n); }
         MethodCallLinkInfo& methodCallLinkInfo(int index) { return m_methodCallLinkInfos[index]; }
+        size_t numberOfMethodCallLinkInfos() { return m_methodCallLinkInfos.size(); }
 #endif
         
 #if ENABLE(VALUE_PROFILER)
@@ -533,6 +547,10 @@ namespace JSC {
                                    bytecodeOffset].u.opcode)) - 1].u.profile == result);
             return result;
         }
+        PredictedType valueProfilePredictionForBytecodeOffset(int bytecodeOffset)
+        {
+            return valueProfileForBytecodeOffset(bytecodeOffset)->computeUpdatedPrediction();
+        }
         
         unsigned totalNumberOfValueProfiles()
         {
@@ -559,12 +577,16 @@ namespace JSC {
         
         bool likelyToTakeSlowCase(int bytecodeOffset)
         {
+            if (!numberOfRareCaseProfiles())
+                return false;
             unsigned value = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
             return value >= Options::likelyToTakeSlowCaseMinimumCount && static_cast<double>(value) / m_executionEntryCount >= Options::likelyToTakeSlowCaseThreshold;
         }
         
         bool couldTakeSlowCase(int bytecodeOffset)
         {
+            if (!numberOfRareCaseProfiles())
+                return false;
             unsigned value = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
             return value >= Options::couldTakeSlowCaseMinimumCount && static_cast<double>(value) / m_executionEntryCount >= Options::couldTakeSlowCaseThreshold;
         }
@@ -583,12 +605,16 @@ namespace JSC {
         
         bool likelyToTakeSpecialFastCase(int bytecodeOffset)
         {
+            if (!numberOfRareCaseProfiles())
+                return false;
             unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
             return specialFastCaseCount >= Options::likelyToTakeSlowCaseMinimumCount && static_cast<double>(specialFastCaseCount) / m_executionEntryCount >= Options::likelyToTakeSlowCaseThreshold;
         }
         
         bool likelyToTakeDeepestSlowCase(int bytecodeOffset)
         {
+            if (!numberOfRareCaseProfiles())
+                return false;
             unsigned slowCaseCount = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
             unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
             unsigned value = slowCaseCount - specialFastCaseCount;
@@ -597,6 +623,8 @@ namespace JSC {
         
         bool likelyToTakeAnySlowCase(int bytecodeOffset)
         {
+            if (!numberOfRareCaseProfiles())
+                return false;
             unsigned slowCaseCount = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
             unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
             unsigned value = slowCaseCount + specialFastCaseCount;
@@ -694,7 +722,7 @@ namespace JSC {
         
         bool addFrequentExitSite(const DFG::FrequentExitSite& site)
         {
-            ASSERT(getJITType() == JITCode::BaselineJIT);
+            ASSERT(JITCode::isBaselineCode(getJITType()));
             return m_exitProfile.add(site);
         }
 
@@ -802,6 +830,29 @@ namespace JSC {
         void copyPostParseDataFrom(CodeBlock* alternative);
         void copyPostParseDataFromAlternative();
         
+        // Functions for controlling when JITting kicks in, in a mixed mode
+        // execution world.
+        
+        void dontJITAnytimeSoon()
+        {
+            m_llintExecuteCounter = Options::executionCounterValueForDontJITAnytimeSoon;
+        }
+        
+        void jitAfterWarmUp()
+        {
+            m_llintExecuteCounter = Options::executionCounterValueForJITAfterWarmUp;
+        }
+        
+        void jitSoon()
+        {
+            m_llintExecuteCounter = Options::executionCounterValueForJITSoon;
+        }
+        
+        int32_t llintExecuteCounter() const
+        {
+            return m_llintExecuteCounter;
+        }
+        
         // Functions for controlling when tiered compilation kicks in. This
         // controls both when the optimizing compiler is invoked and when OSR
         // entry happens. Two triggers exist: the loop trigger and the return
@@ -994,6 +1045,9 @@ namespace JSC {
         bool m_shouldDiscardBytecode;
 
     protected:
+#if ENABLE(JIT)
+        virtual void jitCompileImpl(JSGlobalData&) = 0;
+#endif
         virtual void visitWeakReferences(SlotVisitor&);
         virtual void finalizeUnconditionally();
         
@@ -1075,9 +1129,11 @@ namespace JSC {
         RefPtr<SourceProvider> m_source;
         unsigned m_sourceOffset;
 
-#if ENABLE(CLASSIC_INTERPRETER)
         Vector<unsigned> m_propertyAccessInstructions;
         Vector<unsigned> m_globalResolveInstructions;
+#if ENABLE(LLINT)
+        SegmentedVector<LLIntCallLinkInfo, 8> m_llintCallLinkInfos;
+        SentinelLinkedList<LLIntCallLinkInfo, BasicRawSentinelNode<LLIntCallLinkInfo> > m_incomingLLIntCalls;
 #endif
 #if ENABLE(JIT)
         Vector<StructureStubInfo> m_structureStubInfos;
@@ -1088,9 +1144,10 @@ namespace JSC {
         MacroAssemblerCodePtr m_jitCodeWithArityCheck;
         SentinelLinkedList<CallLinkInfo, BasicRawSentinelNode<CallLinkInfo> > m_incomingCalls;
 #endif
-#if ENABLE(DFG_JIT)
+#if ENABLE(DFG_JIT) || ENABLE(LLINT)
         OwnPtr<CompactJITCodeMap> m_jitCodeMap;
-        
+#endif
+#if ENABLE(DFG_JIT)
         struct WeakReferenceTransition {
             WeakReferenceTransition() { }
             
@@ -1153,12 +1210,14 @@ namespace JSC {
 
         OwnPtr<CodeBlock> m_alternative;
         
+        int32_t m_llintExecuteCounter;
+        
         int32_t m_jitExecuteCounter;
         uint32_t m_speculativeSuccessCounter;
         uint32_t m_speculativeFailCounter;
         uint8_t m_optimizationDelayCounter;
         uint8_t m_reoptimizationRetryCounter;
-
+        
         struct RareData {
            WTF_MAKE_FAST_ALLOCATED;
         public:
@@ -1234,6 +1293,7 @@ namespace JSC {
     protected:
         virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
         virtual void jettison();
+        virtual void jitCompileImpl(JSGlobalData&);
         virtual CodeBlock* replacement();
         virtual bool canCompileWithDFGInternal();
 #endif
@@ -1268,6 +1328,7 @@ namespace JSC {
     protected:
         virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
         virtual void jettison();
+        virtual void jitCompileImpl(JSGlobalData&);
         virtual CodeBlock* replacement();
         virtual bool canCompileWithDFGInternal();
 #endif
@@ -1305,6 +1366,7 @@ namespace JSC {
     protected:
         virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
         virtual void jettison();
+        virtual void jitCompileImpl(JSGlobalData&);
         virtual CodeBlock* replacement();
         virtual bool canCompileWithDFGInternal();
 #endif
index 5eff1d4..11aead3 100644 (file)
 #include "GetByIdStatus.h"
 
 #include "CodeBlock.h"
+#include "LowLevelInterpreter.h"
 
 namespace JSC {
 
+GetByIdStatus GetByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
+{
+    UNUSED_PARAM(profiledBlock);
+    UNUSED_PARAM(bytecodeIndex);
+    UNUSED_PARAM(ident);
+#if ENABLE(LLINT)
+    Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
+    
+    if (instruction[0].u.opcode == llint_op_method_check)
+        instruction++;
+
+    Structure* structure = instruction[4].u.structure.get();
+    if (!structure)
+        return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
+    
+    size_t offset = structure->get(*profiledBlock->globalData(), ident);
+    if (offset == notFound)
+        return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
+    
+    return GetByIdStatus(SimpleDirect, StructureSet(structure), offset, false);
+#else
+    return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
+#endif
+}
+
 GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
 {
     UNUSED_PARAM(profiledBlock);
     UNUSED_PARAM(bytecodeIndex);
     UNUSED_PARAM(ident);
 #if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
+    if (!profiledBlock->numberOfStructureStubInfos())
+        return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
+    
     // First check if it makes either calls, in which case we want to be super careful, or
     // if it's not set at all, in which case we punt.
     StructureStubInfo& stubInfo = profiledBlock->getStubInfo(bytecodeIndex);
     if (!stubInfo.seen)
-        return GetByIdStatus(NoInformation, StructureSet(), notFound);
+        return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
     
     PolymorphicAccessStructureList* list;
     int listSize;
@@ -60,18 +89,19 @@ GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec
     }
     for (int i = 0; i < listSize; ++i) {
         if (!list->list[i].isDirect)
-            return GetByIdStatus(MakesCalls, StructureSet(), notFound);
+            return GetByIdStatus(MakesCalls, StructureSet(), notFound, true);
     }
     
     // Next check if it takes slow case, in which case we want to be kind of careful.
     if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex))
-        return GetByIdStatus(TakesSlowPath, StructureSet(), notFound);
+        return GetByIdStatus(TakesSlowPath, StructureSet(), notFound, true);
     
     // Finally figure out if we can derive an access strategy.
     GetByIdStatus result;
+    result.m_wasSeenInJIT = true;
     switch (stubInfo.accessType) {
     case access_unset:
-        return GetByIdStatus(NoInformation, StructureSet(), notFound);
+        return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
         
     case access_get_by_id_self: {
         Structure* structure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
@@ -130,7 +160,7 @@ GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec
     
     return result;
 #else // ENABLE(JIT)
-    return GetByIdStatus(NoInformation, StructureSet(), notFound);
+    return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
 #endif // ENABLE(JIT)
 }
 
index 00e50e7..39476c0 100644 (file)
@@ -49,10 +49,11 @@ public:
     {
     }
     
-    GetByIdStatus(State state, const StructureSet& structureSet, size_t offset)
+    GetByIdStatus(State state, const StructureSet& structureSet, size_t offset, bool wasSeenInJIT)
         : m_state(state)
         , m_structureSet(structureSet)
         , m_offset(offset)
+        , m_wasSeenInJIT(wasSeenInJIT)
     {
         ASSERT((state == SimpleDirect) == (offset != notFound));
     }
@@ -70,10 +71,15 @@ public:
     const StructureSet& structureSet() const { return m_structureSet; }
     size_t offset() const { return m_offset; }
     
+    bool wasSeenInJIT() const { return m_wasSeenInJIT; }
+    
 private:
+    static GetByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, Identifier&);
+    
     State m_state;
     StructureSet m_structureSet;
     size_t m_offset;
+    bool m_wasSeenInJIT;
 };
 
 } // namespace JSC
index 7fe1152..c4989d2 100644 (file)
@@ -48,6 +48,7 @@ namespace JSC {
     class JSCell;
     class Structure;
     class StructureChain;
+    struct LLIntCallLinkInfo;
     struct ValueProfile;
 
 #if ENABLE(JIT)
@@ -146,6 +147,11 @@ namespace JSC {
 #endif
 
     struct Instruction {
+        Instruction()
+        {
+            u.jsCell.clear();
+        }
+        
         Instruction(Opcode opcode)
         {
 #if !ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
@@ -182,6 +188,8 @@ namespace JSC {
 
         Instruction(PropertySlot::GetValueFunc getterFunc) { u.getterFunc = getterFunc; }
         
+        Instruction(LLIntCallLinkInfo* callLinkInfo) { u.callLinkInfo = callLinkInfo; }
+        
         Instruction(ValueProfile* profile) { u.profile = profile; }
 
         union {
@@ -191,7 +199,9 @@ namespace JSC {
             WriteBarrierBase<StructureChain> structureChain;
             WriteBarrierBase<JSCell> jsCell;
             PropertySlot::GetValueFunc getterFunc;
+            LLIntCallLinkInfo* callLinkInfo;
             ValueProfile* profile;
+            void* pointer;
         } u;
         
     private:
diff --git a/Source/JavaScriptCore/bytecode/LLIntCallLinkInfo.h b/Source/JavaScriptCore/bytecode/LLIntCallLinkInfo.h
new file mode 100644 (file)
index 0000000..bfb9510
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 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 LLIntCallLinkInfo_h
+#define LLIntCallLinkInfo_h
+
+#include "JSFunction.h"
+#include "MacroAssemblerCodeRef.h"
+#include <wtf/SentinelLinkedList.h>
+
+namespace JSC {
+
+struct Instruction;
+
+struct LLIntCallLinkInfo : public BasicRawSentinelNode<LLIntCallLinkInfo> {
+    LLIntCallLinkInfo()
+    {
+    }
+    
+    ~LLIntCallLinkInfo()
+    {
+        if (isOnList())
+            remove();
+    }
+    
+    bool isLinked() { return callee; }
+    
+    void unlink()
+    {
+        callee.clear();
+        machineCodeTarget = MacroAssemblerCodePtr();
+        if (isOnList())
+            remove();
+    }
+    
+    WriteBarrier<JSFunction> callee;
+    WriteBarrier<JSFunction> lastSeenCallee;
+    MacroAssemblerCodePtr machineCodeTarget;
+};
+
+} // namespace JSC
+
+#endif // LLIntCallLinkInfo_h
+
index e7d721c..795b41b 100644 (file)
@@ -35,6 +35,11 @@ MethodCallLinkStatus MethodCallLinkStatus::computeFor(CodeBlock* profiledBlock,
     UNUSED_PARAM(profiledBlock);
     UNUSED_PARAM(bytecodeIndex);
 #if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
+    // NOTE: This does not have an LLInt fall-back because LLInt does not do any method
+    // call link caching.
+    if (!profiledBlock->numberOfMethodCallLinkInfos())
+        return MethodCallLinkStatus();
+    
     MethodCallLinkInfo& methodCall = profiledBlock->getMethodCallLinkInfo(bytecodeIndex);
     
     if (!methodCall.seen || !methodCall.cachedStructure)
index 33db8e6..a277140 100644 (file)
@@ -39,16 +39,12 @@ using namespace std;
 
 namespace JSC {
 
-#if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING) || ENABLE(CODEBLOCK_SAMPLING) || ENABLE(OPCODE_STATS)
-
 const char* const opcodeNames[] = {
 #define OPCODE_NAME_ENTRY(opcode, size) #opcode,
     FOR_EACH_OPCODE_ID(OPCODE_NAME_ENTRY)
 #undef OPCODE_NAME_ENTRY
 };
 
-#endif
-
 #if ENABLE(OPCODE_STATS)
 
 long long OpcodeStats::opcodeCounts[numOpcodeIDs];
index d416af4..a47fa5e 100644 (file)
@@ -123,6 +123,8 @@ namespace JSC {
         macro(op_get_arguments_length, 4) \
         macro(op_put_by_id, 9) \
         macro(op_put_by_id_transition, 9) \
+        macro(op_put_by_id_transition_direct, 9) \
+        macro(op_put_by_id_transition_normal, 9) \
         macro(op_put_by_id_replace, 9) \
         macro(op_put_by_id_generic, 9) \
         macro(op_del_by_id, 4) \
@@ -201,6 +203,7 @@ namespace JSC {
         typedef enum { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) } OpcodeID;
     #undef OPCODE_ID_ENUM
 
+    const int maxOpcodeLength = 9;
     const int numOpcodeIDs = op_end + 1;
 
     #define OPCODE_ID_LENGTHS(id, length) const int id##_length = length;
@@ -217,7 +220,7 @@ namespace JSC {
         FOR_EACH_OPCODE_ID(VERIFY_OPCODE_ID);
     #undef VERIFY_OPCODE_ID
 
-#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
+#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)
 #if COMPILER(RVCT) || COMPILER(INTEL)
     typedef void* Opcode;
 #else
@@ -227,8 +230,6 @@ namespace JSC {
     typedef OpcodeID Opcode;
 #endif
 
-#if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING) || ENABLE(CODEBLOCK_SAMPLING) || ENABLE(OPCODE_STATS)
-
 #define PADDING_STRING "                                "
 #define PADDING_STRING_LENGTH static_cast<unsigned>(strlen(PADDING_STRING))
 
@@ -244,8 +245,6 @@ namespace JSC {
 #undef PADDING_STRING_LENGTH
 #undef PADDING_STRING
 
-#endif
-
 #if ENABLE(OPCODE_STATS)
 
     struct OpcodeStats {
index 45a5e61..209d4cd 100644 (file)
 #include "PutByIdStatus.h"
 
 #include "CodeBlock.h"
+#include "LowLevelInterpreter.h"
 #include "Structure.h"
 #include "StructureChain.h"
 
 namespace JSC {
 
+PutByIdStatus PutByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
+{
+    UNUSED_PARAM(profiledBlock);
+    UNUSED_PARAM(bytecodeIndex);
+    UNUSED_PARAM(ident);
+#if ENABLE(LLINT)
+    Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
+
+    Structure* structure = instruction[4].u.structure.get();
+    if (!structure)
+        return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
+    
+    if (instruction[0].u.opcode == llint_op_put_by_id) {
+        size_t offset = structure->get(*profiledBlock->globalData(), ident);
+        if (offset == notFound)
+            return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
+        
+        return PutByIdStatus(SimpleReplace, structure, 0, 0, offset);
+    }
+    
+    ASSERT(instruction[0].u.opcode == llint_op_put_by_id_transition_direct
+           || instruction[0].u.opcode == llint_op_put_by_id_transition_normal);
+    
+    Structure* newStructure = instruction[6].u.structure.get();
+    StructureChain* chain = instruction[7].u.structureChain.get();
+    ASSERT(newStructure);
+    ASSERT(chain);
+    
+    size_t offset = newStructure->get(*profiledBlock->globalData(), ident);
+    if (offset == notFound)
+        return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
+    
+    return PutByIdStatus(SimpleTransition, structure, newStructure, chain, offset);
+#else
+    return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
+#endif
+}
+
 PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
 {
     UNUSED_PARAM(profiledBlock);
     UNUSED_PARAM(bytecodeIndex);
     UNUSED_PARAM(ident);
 #if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
+    if (!profiledBlock->numberOfStructureStubInfos())
+        return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
+    
     if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex))
         return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound);
     
     StructureStubInfo& stubInfo = profiledBlock->getStubInfo(bytecodeIndex);
     if (!stubInfo.seen)
-        return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
+        return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
     
     switch (stubInfo.accessType) {
     case access_unset:
-        return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
+        return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
         
     case access_put_by_id_replace: {
         size_t offset = stubInfo.u.putByIdReplace.baseObjectStructure->get(
index b33f4d0..a6d95a4 100644 (file)
@@ -93,6 +93,8 @@ public:
     size_t offset() const { return m_offset; }
     
 private:
+    static PutByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, Identifier&);
+    
     State m_state;
     Structure* m_oldStructure;
     Structure* m_newStructure;
index 16a112a..6fa0ce9 100644 (file)
@@ -35,6 +35,7 @@
 #include "JSActivation.h"
 #include "JSFunction.h"
 #include "Interpreter.h"
+#include "LowLevelInterpreter.h"
 #include "ScopeChain.h"
 #include "StrongInlines.h"
 #include "UString.h"
@@ -1278,9 +1279,7 @@ RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const ResolveResult&
 #if ENABLE(JIT)
         m_codeBlock->addGlobalResolveInfo(instructions().size());
 #endif
-#if ENABLE(CLASSIC_INTERPRETER)
         m_codeBlock->addGlobalResolveInstruction(instructions().size());
-#endif
         bool dynamic = resolveResult.isDynamic() && resolveResult.depth();
         ValueProfile* profile = emitProfiledOpcode(dynamic ? op_resolve_global_dynamic : op_resolve_global);
         instructions().append(dst->index());
@@ -1384,9 +1383,6 @@ RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, Register
         return baseDst;
     }
 
-
-
-
     ValueProfile* profile = emitProfiledOpcode(op_resolve_with_base);
     instructions().append(baseDst->index());
     instructions().append(propDst->index());
@@ -1494,9 +1490,7 @@ void BytecodeGenerator::emitMethodCheck()
 
 RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
 {
-#if ENABLE(CLASSIC_INTERPRETER)
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
-#endif
 
     ValueProfile* profile = emitProfiledOpcode(op_get_by_id);
     instructions().append(dst->index());
@@ -1522,9 +1516,7 @@ RegisterID* BytecodeGenerator::emitGetArgumentsLength(RegisterID* dst, RegisterI
 
 RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
 {
-#if ENABLE(CLASSIC_INTERPRETER)
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
-#endif
 
     emitOpcode(op_put_by_id);
     instructions().append(base->index());
@@ -1540,9 +1532,7 @@ RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& p
 
 RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value)
 {
-#if ENABLE(CLASSIC_INTERPRETER)
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
-#endif
     
     emitOpcode(op_put_by_id);
     instructions().append(base->index());
@@ -1823,7 +1813,11 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
     instructions().append(func->index()); // func
     instructions().append(callArguments.argumentCountIncludingThis()); // argCount
     instructions().append(callArguments.registerOffset()); // registerOffset
+#if ENABLE(LLINT)
+    instructions().append(m_codeBlock->addLLIntCallLinkInfo());
+#else
     instructions().append(0);
+#endif
     instructions().append(0);
     if (dst != ignoredResult()) {
         ValueProfile* profile = emitProfiledOpcode(op_call_put_result);
@@ -1927,7 +1921,11 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
     instructions().append(func->index()); // func
     instructions().append(callArguments.argumentCountIncludingThis()); // argCount
     instructions().append(callArguments.registerOffset()); // registerOffset
+#if ENABLE(LLINT)
+    instructions().append(m_codeBlock->addLLIntCallLinkInfo());
+#else
     instructions().append(0);
+#endif
     instructions().append(0);
     if (dst != ignoredResult()) {
         ValueProfile* profile = emitProfiledOpcode(op_call_put_result);
@@ -2188,7 +2186,11 @@ RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* star
 {
     m_usesExceptions = true;
 #if ENABLE(JIT)
+#if ENABLE(LLINT)
+    HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(bitwise_cast<void*>(&llint_op_catch))) };
+#else
     HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel() };
+#endif
 #else
     HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth };
 #endif
index 6378203..6e465af 100644 (file)
@@ -585,9 +585,7 @@ private:
     {
         UNUSED_PARAM(nodeIndex);
         
-        ValueProfile* profile = m_inlineStackTop->m_profiledBlock->valueProfileForBytecodeOffset(bytecodeIndex);
-        ASSERT(profile);
-        PredictedType prediction = profile->computeUpdatedPrediction();
+        PredictedType prediction = m_inlineStackTop->m_profiledBlock->valueProfilePredictionForBytecodeOffset(bytecodeIndex);
 #if DFG_ENABLE(DEBUG_VERBOSE)
         dataLog("Dynamic [@%u, bc#%u] prediction: %s\n", nodeIndex, bytecodeIndex, predictionToString(prediction));
 #endif
@@ -1022,6 +1020,9 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c
     
     // If we get here then it looks like we should definitely inline this code. Proceed
     // with parsing the code to get bytecode, so that we can then parse the bytecode.
+    // Note that if LLInt is enabled, the bytecode will always be available. Also note
+    // that if LLInt is enabled, we may inline a code block that has never been JITted
+    // before!
     CodeBlock* codeBlock = m_codeBlockCache.get(CodeBlockKey(executable, kind), expectedFunction->scope());
     if (!codeBlock)
         return false;
@@ -1722,7 +1723,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                 m_inlineStackTop->m_profiledBlock, m_currentIndex);
             
             if (methodCallStatus.isSet()
-                && !getByIdStatus.isSet()
+                && !getByIdStatus.wasSeenInJIT()
                 && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
                 // It's monomorphic as far as we can tell, since the method_check was linked
                 // but the slow path (i.e. the normal get_by_id) never fired.
@@ -1791,7 +1792,9 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
             NEXT_OPCODE(op_get_by_id);
         }
-        case op_put_by_id: {
+        case op_put_by_id:
+        case op_put_by_id_transition_direct:
+        case op_put_by_id_transition_normal: {
             NodeIndex value = get(currentInstruction[3].u.operand);
             NodeIndex base = get(currentInstruction[1].u.operand);
             unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
index 2653c73..e339714 100644 (file)
@@ -111,6 +111,8 @@ inline bool canCompileOpcode(OpcodeID opcodeID)
     case op_put_scoped_var:
     case op_get_by_id:
     case op_put_by_id:
+    case op_put_by_id_transition_direct:
+    case op_put_by_id_transition_normal:
     case op_get_global_var:
     case op_put_global_var:
     case op_jmp:
index 68c3e72..a195ee3 100644 (file)
@@ -48,6 +48,21 @@ void compileOSRExit(ExecState* exec)
     uint32_t exitIndex = globalData->osrExitIndex;
     OSRExit& exit = codeBlock->osrExit(exitIndex);
     
+    // Make sure all code on our inline stack is JIT compiled. This is necessary since
+    // we may opt to inline a code block even before it had ever been compiled by the
+    // JIT, but our OSR exit infrastructure currently only works if the target of the
+    // OSR exit is JIT code. This could be changed since there is nothing particularly
+    // hard about doing an OSR exit into the interpreter, but for now this seems to make
+    // sense in that if we're OSR exiting from inlined code of a DFG code block, then
+    // probably it's a good sign that the thing we're exiting into is hot. Even more
+    // interestingly, since the code was inlined, it may never otherwise get JIT
+    // compiled since the act of inlining it may ensure that it otherwise never runs.
+    for (CodeOrigin codeOrigin = exit.m_codeOrigin; codeOrigin.inlineCallFrame; codeOrigin = codeOrigin.inlineCallFrame->caller) {
+        static_cast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())
+            ->baselineCodeBlockFor(codeOrigin.inlineCallFrame->isCall ? CodeForCall : CodeForConstruct)
+            ->jitCompile(*globalData);
+    }
+    
     SpeculationRecovery* recovery = 0;
     if (exit.m_recoveryIndex)
         recovery = &codeBlock->speculationRecovery(exit.m_recoveryIndex - 1);
index 2e5aad7..c8106eb 100644 (file)
@@ -31,6 +31,7 @@
 #include "CodeBlock.h"
 #include "DFGOSRExit.h"
 #include "DFGRepatch.h"
+#include "HostCallReturnValue.h"
 #include "GetterSetter.h"
 #include "InlineASM.h"
 #include "Interpreter.h"
@@ -737,50 +738,6 @@ size_t DFG_OPERATION operationCompareStrictEq(ExecState* exec, EncodedJSValue en
     return JSValue::strictEqual(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
 }
 
-EncodedJSValue DFG_OPERATION getHostCallReturnValue();
-EncodedJSValue DFG_OPERATION getHostCallReturnValueWithExecState(ExecState*);
-
-#if CPU(X86_64)
-asm (
-".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
-HIDE_SYMBOL(getHostCallReturnValue) "\n"
-SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
-    "mov -40(%r13), %r13\n"
-    "mov %r13, %rdi\n"
-    "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
-);
-#elif CPU(X86)
-asm (
-".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
-HIDE_SYMBOL(getHostCallReturnValue) "\n"
-SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
-    "mov -40(%edi), %edi\n"
-    "mov %edi, 4(%esp)\n"
-    "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
-);
-#elif CPU(ARM_THUMB2)
-asm (
-".text" "\n"
-".align 2" "\n"
-".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
-HIDE_SYMBOL(getHostCallReturnValue) "\n"
-".thumb" "\n"
-".thumb_func " THUMB_FUNC_PARAM(getHostCallReturnValue) "\n"
-SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
-    "ldr r5, [r5, #-40]" "\n"
-    "cpy r0, r5" "\n"
-    "b " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
-);
-#endif
-
-EncodedJSValue DFG_OPERATION getHostCallReturnValueWithExecState(ExecState* exec)
-{
-    JSGlobalData* globalData = &exec->globalData();
-    NativeCallFrameTracer tracer(globalData, exec);
-    
-    return JSValue::encode(exec->globalData().hostCallReturnValue);
-}
-
 static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializationKind kind)
 {
     ExecState* exec = execCallee->callerFrame();
@@ -788,6 +745,7 @@ static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializ
 
     execCallee->setScopeChain(exec->scopeChain());
     execCallee->setCodeBlock(0);
+    execCallee->clearReturnPC();
 
     if (kind == CodeForCall) {
         CallData callData;
index 250f3ef..bcacee6 100644 (file)
@@ -50,6 +50,7 @@ namespace JSC {
     class JSGlobalData;
     class JSValue;
     class LiveObjectIterator;
+    class LLIntOffsetsExtractor;
     class MarkedArgumentBuffer;
     class RegisterFile;
     class UString;
@@ -95,6 +96,7 @@ namespace JSC {
         // true if an allocation or collection is in progress
         inline bool isBusy();
         
+        MarkedAllocator& firstAllocatorWithoutDestructors() { return m_objectSpace.firstAllocator(); }
         MarkedAllocator& allocatorForObjectWithoutDestructor(size_t bytes) { return m_objectSpace.allocatorFor(bytes); }
         MarkedAllocator& allocatorForObjectWithDestructor(size_t bytes) { return m_objectSpace.destructorAllocatorFor(bytes); }
         CheckedBoolean tryAllocateStorage(size_t, void**);
@@ -136,12 +138,13 @@ namespace JSC {
         void getConservativeRegisterRoots(HashSet<JSCell*>& roots);
 
     private:
+        friend class CodeBlock;
+        friend class LLIntOffsetsExtractor;
         friend class MarkedSpace;
         friend class MarkedAllocator;
         friend class MarkedBlock;
         friend class CopiedSpace;
         friend class SlotVisitor;
-        friend class CodeBlock;
         template<typename T> friend void* allocateCell(Heap&);
 
         void* allocateWithDestructor(size_t);
index eab2482..129a7ab 100644 (file)
@@ -303,7 +303,7 @@ ALWAYS_INLINE static void visitChildren(SlotVisitor& visitor, const JSCell* cell
 #endif
 
     ASSERT(Heap::isMarked(cell));
-
+    
     if (isJSString(cell)) {
         JSString::visitChildren(const_cast<JSCell*>(cell), visitor);
         return;
index 16207f6..1c6af77 100644 (file)
@@ -8,6 +8,7 @@ namespace JSC {
 
 class Heap;
 class MarkedSpace;
+class LLIntOffsetsExtractor;
 
 namespace DFG {
 class SpeculativeJIT;
@@ -33,6 +34,8 @@ public:
     void init(Heap*, MarkedSpace*, size_t cellSize, bool cellsNeedDestruction);
     
 private:
+    friend class LLIntOffsetsExtractor;
+    
     JS_EXPORT_PRIVATE void* allocateSlowCase();
     void* tryAllocate();
     void* tryAllocateHelper();
index 7df68f0..cfcf3f8 100644 (file)
@@ -41,6 +41,7 @@ namespace JSC {
 class Heap;
 class JSCell;
 class LiveObjectIterator;
+class LLIntOffsetsExtractor;
 class WeakGCHandle;
 class SlotVisitor;
 
@@ -51,6 +52,7 @@ public:
 
     MarkedSpace(Heap*);
 
+    MarkedAllocator& firstAllocator();
     MarkedAllocator& allocatorFor(size_t);
     MarkedAllocator& allocatorFor(MarkedBlock*);
     MarkedAllocator& destructorAllocatorFor(size_t);
@@ -79,6 +81,8 @@ public:
     void didConsumeFreeList(MarkedBlock*);
 
 private:
+    friend class LLIntOffsetsExtractor;
+    
     // [ 32... 256 ]
     static const size_t preciseStep = MarkedBlock::atomSize;
     static const size_t preciseCutoff = 256;
@@ -129,6 +133,11 @@ template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forE
     return forEachCell(functor);
 }
 
+inline MarkedAllocator& MarkedSpace::firstAllocator()
+{
+    return m_normalSpace.preciseAllocators[0];
+}
+
 inline MarkedAllocator& MarkedSpace::allocatorFor(size_t bytes)
 {
     ASSERT(bytes && bytes <= maxCellSize);
index bad6424..b0e5ea0 100644 (file)
@@ -50,6 +50,29 @@ RegisterFile* CallFrame::registerFile()
 
 #endif
 
+#if USE(JSVALUE32_64)
+unsigned CallFrame::bytecodeOffsetForNonDFGCode() const
+{
+    ASSERT(codeBlock());
+    return currentVPC() - codeBlock()->instructions().begin();
+}
+
+void CallFrame::setBytecodeOffsetForNonDFGCode(unsigned offset)
+{
+    ASSERT(codeBlock());
+    setCurrentVPC(codeBlock()->instructions().begin() + offset);
+}
+#else
+Instruction* CallFrame::currentVPC() const
+{
+    return codeBlock()->instructions().begin() + bytecodeOffsetForNonDFGCode();
+}
+void CallFrame::setCurrentVPC(Instruction* vpc)
+{
+    setBytecodeOffsetForNonDFGCode(vpc - codeBlock()->instructions().begin());
+}
+#endif
+    
 #if ENABLE(DFG_JIT)
 bool CallFrame::isInlineCallFrameSlow()
 {
@@ -142,7 +165,7 @@ CallFrame* CallFrame::trueCallerFrame()
     //    more frames above the true caller due to inlining.
 
     // Am I an inline call frame? If so, we're done.
-    if (isInlineCallFrame() || !hasReturnPC())
+    if (isInlineCallFrame())
         return callerFrame()->removeHostCallFrameFlag();
     
     // I am a machine call frame, so the question is: is my caller a machine call frame
@@ -153,7 +176,7 @@ CallFrame* CallFrame::trueCallerFrame()
     ASSERT(!machineCaller->isInlineCallFrame());
     
     // Figure out how we want to get the current code location.
-    if (hasHostCallFrameFlag() || returnAddressIsInCtiTrampoline(returnPC()))
+    if (!hasReturnPC() || returnAddressIsInCtiTrampoline(returnPC()))
         return machineCaller->trueCallFrameFromVMCode()->removeHostCallFrameFlag();
     
     return machineCaller->trueCallFrame(returnPC())->removeHostCallFrameFlag();
index 9ef41c9..5bf2b94 100644 (file)
@@ -103,11 +103,16 @@ namespace JSC  {
 
         CallFrame* callerFrame() const { return this[RegisterFile::CallerFrame].callFrame(); }
 #if ENABLE(JIT)
-        bool hasReturnPC() const { return this[RegisterFile::ReturnPC].vPC(); }
         ReturnAddressPtr returnPC() const { return ReturnAddressPtr(this[RegisterFile::ReturnPC].vPC()); }
+        bool hasReturnPC() const { return !!this[RegisterFile::ReturnPC].vPC(); }
+        void clearReturnPC() { registers()[RegisterFile::ReturnPC] = static_cast<Instruction*>(0); }
 #endif
         AbstractPC abstractReturnPC(JSGlobalData& globalData) { return AbstractPC(globalData, this); }
-        unsigned bytecodeOffsetForNonDFGCode()
+#if USE(JSVALUE32_64)
+        unsigned bytecodeOffsetForNonDFGCode() const;
+        void setBytecodeOffsetForNonDFGCode(unsigned offset);
+#else
+        unsigned bytecodeOffsetForNonDFGCode() const
         {
             ASSERT(codeBlock());
             return this[RegisterFile::ArgumentCount].tag();
@@ -118,6 +123,7 @@ namespace JSC  {
             ASSERT(codeBlock());
             this[RegisterFile::ArgumentCount].tag() = static_cast<int32_t>(offset);
         }
+#endif
 
 #if ENABLE(DFG_JIT)
         InlineCallFrame* inlineCallFrame() const { return this[RegisterFile::ReturnPC].asInlineCallFrame(); }
@@ -135,6 +141,19 @@ namespace JSC  {
 #if ENABLE(CLASSIC_INTERPRETER)
         Instruction* returnVPC() const { return this[RegisterFile::ReturnPC].vPC(); }
 #endif
+#if USE(JSVALUE32_64)
+        Instruction* currentVPC() const
+        {
+            return bitwise_cast<Instruction*>(this[RegisterFile::ArgumentCount].tag());
+        }
+        void setCurrentVPC(Instruction* vpc)
+        {
+            this[RegisterFile::ArgumentCount].tag() = bitwise_cast<int32_t>(vpc);
+        }
+#else
+        Instruction* currentVPC() const;
+        void setCurrentVPC(Instruction* vpc);
+#endif
 
         void setCallerFrame(CallFrame* callerFrame) { static_cast<Register*>(this)[RegisterFile::CallerFrame] = callerFrame; }
         void setScopeChain(ScopeChainNode* scopeChain) { static_cast<Register*>(this)[RegisterFile::ScopeChain] = scopeChain; }
index e1bfe7f..eb6a29d 100644 (file)
@@ -69,7 +69,7 @@
 #include "JIT.h"
 #endif
 
-#define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND (ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) && !defined(__llvm__))
+#define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND ((ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)) && !defined(__llvm__))
 
 using namespace std;
 
@@ -543,34 +543,59 @@ Interpreter::Interpreter()
 #if !ASSERT_DISABLED
     , m_initialized(false)
 #endif
-    , m_enabled(false)
+    , m_classicEnabled(false)
 {
 }
 
-void Interpreter::initialize(bool canUseJIT)
+Interpreter::~Interpreter()
 {
-#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
+#if ENABLE(LLINT)
+    if (m_classicEnabled)
+        delete[] m_opcodeTable;
+#endif
+}
+
+void Interpreter::initialize(LLInt::Data* llintData, bool canUseJIT)
+{
+    UNUSED_PARAM(llintData);
+    UNUSED_PARAM(canUseJIT);
+#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)
+#if !ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
+    // Having LLInt enabled, but not being able to use the JIT, and not having
+    // a computed goto interpreter, is not supported. Not because we cannot
+    // support it, but because I decided to draw the line at the number of
+    // permutations of execution engines that I wanted this code to grok.
+    ASSERT(canUseJIT);
+#endif
     if (canUseJIT) {
+#if ENABLE(LLINT)
+        m_opcodeTable = llintData->opcodeMap();
+        for (int i = 0; i < numOpcodeIDs; ++i)
+            m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
+#else
         // If the JIT is present, don't use jump destinations for opcodes.
         
         for (int i = 0; i < numOpcodeIDs; ++i) {
             Opcode opcode = bitwise_cast<void*>(static_cast<uintptr_t>(i));
             m_opcodeTable[i] = opcode;
         }
+#endif
     } else {
+#if ENABLE(LLINT)
+        m_opcodeTable = new Opcode[numOpcodeIDs];
+#endif
         privateExecute(InitializeAndReturn, 0, 0);
         
         for (int i = 0; i < numOpcodeIDs; ++i)
             m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
         
-        m_enabled = true;
+        m_classicEnabled = true;
     }
 #else
-    UNUSED_PARAM(canUseJIT);
 #if ENABLE(CLASSIC_INTERPRETER)
-    m_enabled = true;
+    m_classicEnabled = true;
 #else
-    m_enabled = false;
+    m_classicEnabled = false;
 #endif
 #endif // ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
 #if !ASSERT_DISABLED
@@ -667,9 +692,11 @@ void Interpreter::dumpRegisters(CallFrame* callFrame)
 
 bool Interpreter::isOpcode(Opcode opcode)
 {
-#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
-    if (!m_enabled)
+#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)
+#if !ENABLE(LLINT)
+    if (!m_classicEnabled)
         return opcode >= 0 && static_cast<OpcodeID>(bitwise_cast<uintptr_t>(opcode)) <= op_end;
+#endif
     return opcode != HashTraits<Opcode>::emptyValue()
         && !HashTraits<Opcode>::isDeletedValue(opcode)
         && m_opcodeIDTable.contains(opcode);
@@ -726,11 +753,11 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue ex
     // have to subtract 1.
 #if ENABLE(JIT) && ENABLE(CLASSIC_INTERPRETER)
     if (callerFrame->globalData().canUseJIT())
-        bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnPC());
+        bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
     else
         bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1;
 #elif ENABLE(JIT)
-    bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnPC());
+    bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
 #else
     bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1;
 #endif
@@ -857,7 +884,7 @@ static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame,
             }
         } else
     #endif
-            bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
+            bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
 #endif
     }
 
@@ -1815,7 +1842,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
     }
     
     ASSERT(m_initialized);
-    ASSERT(m_enabled);
+    ASSERT(m_classicEnabled);
     
 #if ENABLE(JIT)
 #if ENABLE(CLASSIC_INTERPRETER)
@@ -3466,6 +3493,8 @@ skip_id_custom_self:
 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
       skip_put_by_id:
 #endif
+    DEFINE_OPCODE(op_put_by_id_transition_direct)
+    DEFINE_OPCODE(op_put_by_id_transition_normal)
     DEFINE_OPCODE(op_put_by_id_transition) {
         /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n) direct(b)
          
@@ -5299,10 +5328,10 @@ void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intp
         bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnVPC());
 #if ENABLE(JIT)
     else
-        bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
+        bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
 #endif
 #else
-    bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
+    bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
 #endif
     lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
     sourceID = callerCodeBlock->ownerExecutable()->sourceID();
index 6920eb2..51881a5 100644 (file)
@@ -34,6 +34,7 @@
 #include "JSFunction.h"
 #include "JSValue.h"
 #include "JSObject.h"
+#include "LLIntData.h"
 #include "Opcode.h"
 #include "RegisterFile.h"
 
@@ -46,6 +47,7 @@ namespace JSC {
     class ExecutableBase;
     class FunctionExecutable;
     class JSGlobalObject;
+    class LLIntOffsetsExtractor;
     class ProgramExecutable;
     class Register;
     class ScopeChainNode;
@@ -158,19 +160,21 @@ namespace JSC {
 
     class Interpreter {
         WTF_MAKE_FAST_ALLOCATED;
-        friend class JIT;
         friend class CachedCall;
+        friend class LLIntOffsetsExtractor;
+        friend class JIT;
     public:
         Interpreter();
+        ~Interpreter();
         
-        void initialize(bool canUseJIT);
+        void initialize(LLInt::Data*, bool canUseJIT);
 
         RegisterFile& registerFile() { return m_registerFile; }
         
         Opcode getOpcode(OpcodeID id)
         {
             ASSERT(m_initialized);
-#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
+#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)
             return m_opcodeTable[id];
 #else
             return id;
@@ -180,9 +184,12 @@ namespace JSC {
         OpcodeID getOpcodeID(Opcode opcode)
         {
             ASSERT(m_initialized);
-#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
+#if ENABLE(LLINT)
+            ASSERT(isOpcode(opcode));
+            return m_opcodeIDTable.get(opcode);
+#elif ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
             ASSERT(isOpcode(opcode));
-            if (!m_enabled)
+            if (!m_classicEnabled)
                 return static_cast<OpcodeID>(bitwise_cast<uintptr_t>(opcode));
 
             return m_opcodeIDTable.get(opcode);
@@ -190,6 +197,11 @@ namespace JSC {
             return opcode;
 #endif
         }
+        
+        bool classicEnabled()
+        {
+            return m_classicEnabled;
+        }
 
         bool isOpcode(Opcode);
 
@@ -259,7 +271,10 @@ namespace JSC {
 
         RegisterFile m_registerFile;
         
-#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
+#if ENABLE(LLINT)
+        Opcode* m_opcodeTable; // Maps OpcodeID => Opcode for compiling
+        HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
+#elif ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
         Opcode m_opcodeTable[numOpcodeIDs]; // Maps OpcodeID => Opcode for compiling
         HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
 #endif
@@ -267,7 +282,7 @@ namespace JSC {
 #if !ASSERT_DISABLED
         bool m_initialized;
 #endif
-        bool m_enabled;
+        bool m_classicEnabled;
     };
 
     // This value must not be an object that would require this conversion (WebCore's global object).
index e45b869..21ad7fb 100644 (file)
@@ -39,6 +39,7 @@ namespace JSC {
 
     class ConservativeRoots;
     class DFGCodeBlocks;
+    class LLIntOffsetsExtractor;
 
     class RegisterFile {
         WTF_MAKE_NONCOPYABLE(RegisterFile);
@@ -81,6 +82,8 @@ namespace JSC {
         }
 
     private:
+        friend class LLIntOffsetsExtractor;
+        
         bool growSlowCase(Register*);
         void releaseExcessCapacity();
         void addToCommittedByteCount(long);
index bc8b816..7520913 100644 (file)
@@ -89,12 +89,12 @@ inline size_t roundUpAllocationSize(size_t request, size_t granularity)
 
 }
 
-#if ENABLE(JIT) && ENABLE(ASSEMBLER)
-
 namespace JSC {
 
 typedef WTF::MetaAllocatorHandle ExecutableMemoryHandle;
 
+#if ENABLE(JIT) && ENABLE(ASSEMBLER)
+
 class ExecutableAllocator {
     enum ProtectionSetting { Writable, Executable };
 
@@ -235,8 +235,8 @@ private:
 #endif
 };
 
-} // namespace JSC
-
 #endif // ENABLE(JIT) && ENABLE(ASSEMBLER)
 
+} // namespace JSC
+
 #endif // !defined(ExecutableAllocator)
diff --git a/Source/JavaScriptCore/jit/HostCallReturnValue.cpp b/Source/JavaScriptCore/jit/HostCallReturnValue.cpp
new file mode 100644 (file)
index 0000000..ff627c8
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2012 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 "HostCallReturnValue.h"
+
+#include "CallFrame.h"
+#include "InlineASM.h"
+#include "JSObject.h"
+#include "JSValueInlineMethods.h"
+#include "ScopeChain.h"
+
+namespace JSC {
+
+#if COMPILER(GCC)
+
+#if CPU(X86_64)
+asm (
+".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
+HIDE_SYMBOL(getHostCallReturnValue) "\n"
+SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
+    "mov -40(%r13), %r13\n"
+    "mov %r13, %rdi\n"
+    "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
+);
+#elif CPU(X86)
+asm (
+".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
+HIDE_SYMBOL(getHostCallReturnValue) "\n"
+SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
+    "mov -40(%edi), %edi\n"
+    "mov %edi, 4(%esp)\n"
+    "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
+);
+#elif CPU(ARM_THUMB2)
+asm (
+".text" "\n"
+".align 2" "\n"
+".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
+HIDE_SYMBOL(getHostCallReturnValue) "\n"
+".thumb" "\n"
+".thumb_func " THUMB_FUNC_PARAM(getHostCallReturnValue) "\n"
+SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
+    "ldr r5, [r5, #-40]" "\n"
+    "cpy r0, r5" "\n"
+    "b " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
+);
+#endif
+
+extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWithExecState(ExecState* exec)
+{
+    if (!exec)
+        return JSValue::encode(JSValue());
+    return JSValue::encode(exec->globalData().hostCallReturnValue);
+}
+
+#endif // COMPILER(GCC)
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/jit/HostCallReturnValue.h b/Source/JavaScriptCore/jit/HostCallReturnValue.h
new file mode 100644 (file)
index 0000000..12fe10b
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 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 HostCallReturnValue_h
+#define HostCallReturnValue_h
+
+#include "JSValue.h"
+#include "MacroAssemblerCodeRef.h"
+#include <wtf/Platform.h>
+
+// Unfortunately this only works on GCC-like compilers. And it's currently only used
+// by LLInt and DFG, which also are restricted to GCC-like compilers. We should
+// probably fix that at some point.
+#if COMPILER(GCC)
+
+#if CALLING_CONVENTION_IS_STDCALL
+#define HOST_CALL_RETURN_VALUE_OPTION CDECL
+#else
+#define HOST_CALL_RETURN_VALUE_OPTION
+#endif
+
+namespace JSC {
+
+extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValue();
+
+// This is a public declaration only to convince CLANG not to elide it.
+extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWithExecState(ExecState*);
+
+inline void initializeHostCallReturnValue()
+{
+    getHostCallReturnValueWithExecState(0);
+}
+
+}
+
+#else // COMPILER(GCC)
+
+namespace JSC {
+inline void initializeHostCallReturnValue() { }
+}
+
+#endif // COMPILER(GCC)
+
+#endif // HostCallReturnValue_h
+
index f3f833a..2adc596 100644 (file)
@@ -325,6 +325,8 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_profile_will_call)
         DEFINE_OP(op_push_new_scope)
         DEFINE_OP(op_push_scope)
+        case op_put_by_id_transition_direct:
+        case op_put_by_id_transition_normal:
         DEFINE_OP(op_put_by_id)
         DEFINE_OP(op_put_by_index)
         DEFINE_OP(op_put_by_val)
@@ -486,6 +488,8 @@ void JIT::privateCompileSlowCases()
         DEFINE_SLOWCASE_OP(op_post_inc)
         DEFINE_SLOWCASE_OP(op_pre_dec)
         DEFINE_SLOWCASE_OP(op_pre_inc)
+        case op_put_by_id_transition_direct:
+        case op_put_by_id_transition_normal:
         DEFINE_SLOWCASE_OP(op_put_by_id)
         DEFINE_SLOWCASE_OP(op_put_by_val)
         DEFINE_SLOWCASE_OP(op_resolve_global)
@@ -525,6 +529,10 @@ void JIT::privateCompileSlowCases()
 
 JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck)
 {
+#if ENABLE(JIT_VERBOSE_OSR)
+    printf("Compiling JIT code!\n");
+#endif
+    
 #if ENABLE(VALUE_PROFILER)
     m_canBeOptimized = m_codeBlock->canCompileWithDFG();
 #endif
@@ -693,8 +701,12 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck)
         info.callReturnLocation = m_codeBlock->structureStubInfo(m_methodCallCompilationInfo[i].propertyAccessIndex).callReturnLocation;
     }
 
-#if ENABLE(DFG_JIT)
-    if (m_canBeOptimized) {
+#if ENABLE(DFG_JIT) || ENABLE(LLINT)
+    if (m_canBeOptimized
+#if ENABLE(LLINT)
+        || true
+#endif
+        ) {
         CompactJITCodeMap::Encoder jitCodeMapEncoder;
         for (unsigned bytecodeOffset = 0; bytecodeOffset < m_labels.size(); ++bytecodeOffset) {
             if (m_labels[bytecodeOffset].isSet())
index f63c4a1..3ae5ff2 100644 (file)
@@ -48,7 +48,7 @@ namespace JSC {
         JITCode() { }
 #endif
     public:
-        enum JITType { HostCallThunk, BaselineJIT, DFGJIT };
+        enum JITType { None, HostCallThunk, InterpreterThunk, BaselineJIT, DFGJIT };
         
         static JITType bottomTierJIT()
         {
@@ -66,8 +66,19 @@ namespace JSC {
             return DFGJIT;
         }
         
+        static bool isOptimizingJIT(JITType jitType)
+        {
+            return jitType == DFGJIT;
+        }
+        
+        static bool isBaselineCode(JITType jitType)
+        {
+            return jitType == InterpreterThunk || jitType == BaselineJIT;
+        }
+        
 #if ENABLE(JIT)
         JITCode()
+            : m_jitType(None)
         {
         }
 
@@ -75,6 +86,7 @@ namespace JSC {
             : m_ref(ref)
             , m_jitType(jitType)
         {
+            ASSERT(jitType != None);
         }
         
         bool operator !() const
index 4b8df47..b204c77 100644 (file)
 #include "BytecodeGenerator.h"
 #include "DFGDriver.h"
 #include "JIT.h"
+#include "LLIntEntrypoints.h"
 
 namespace JSC {
 
 template<typename CodeBlockType>
 inline bool jitCompileIfAppropriate(JSGlobalData& globalData, OwnPtr<CodeBlockType>& codeBlock, JITCode& jitCode, JITCode::JITType jitType)
 {
+    if (jitType == codeBlock->getJITType())
+        return true;
+    
     if (!globalData.canUseJIT())
         return true;
     
+    codeBlock->unlinkIncomingCalls();
+    
     bool dfgCompiled = false;
     if (jitType == JITCode::DFGJIT)
         dfgCompiled = DFG::tryCompile(globalData, codeBlock.get(), jitCode);
@@ -62,9 +68,14 @@ inline bool jitCompileIfAppropriate(JSGlobalData& globalData, OwnPtr<CodeBlockTy
 
 inline bool jitCompileFunctionIfAppropriate(JSGlobalData& globalData, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType)
 {
+    if (jitType == codeBlock->getJITType())
+        return true;
+    
     if (!globalData.canUseJIT())
         return true;
     
+    codeBlock->unlinkIncomingCalls();
+    
     bool dfgCompiled = false;
     if (jitType == JITCode::DFGJIT)
         dfgCompiled = DFG::tryCompileFunction(globalData, codeBlock.get(), jitCode, jitCodeWithArityCheck);
@@ -79,7 +90,6 @@ inline bool jitCompileFunctionIfAppropriate(JSGlobalData& globalData, OwnPtr<Fun
         }
         jitCode = JIT::compile(&globalData, codeBlock.get(), &jitCodeWithArityCheck);
     }
-    
     codeBlock->setJITCode(jitCode, jitCodeWithArityCheck);
     
     return true;
index 24baca4..2edd340 100644 (file)
@@ -64,7 +64,7 @@ ExceptionHandler genericThrow(JSGlobalData* globalData, ExecState* callFrame, JS
 
 ExceptionHandler jitThrow(JSGlobalData* globalData, ExecState* callFrame, JSValue exceptionValue, ReturnAddressPtr faultLocation)
 {
-    return genericThrow(globalData, callFrame, exceptionValue, callFrame->codeBlock()->bytecodeOffset(faultLocation));
+    return genericThrow(globalData, callFrame, exceptionValue, callFrame->codeBlock()->bytecodeOffset(callFrame, faultLocation));
 }
 
 }
index 36643d0..e031056 100644 (file)
@@ -265,8 +265,13 @@ ALWAYS_INLINE void JIT::restoreArgumentReference()
 ALWAYS_INLINE void JIT::updateTopCallFrame()
 {
     ASSERT(static_cast<int>(m_bytecodeOffset) >= 0);
-    if (m_bytecodeOffset)
+    if (m_bytecodeOffset) {
+#if USE(JSVALUE32_64)
+        storePtr(TrustedImmPtr(m_codeBlock->instructions().begin() + m_bytecodeOffset + 1), intTagFor(RegisterFile::ArgumentCount));
+#else
         store32(Imm32(m_bytecodeOffset + 1), intTagFor(RegisterFile::ArgumentCount));
+#endif
+    }
     storePtr(callFrameRegister, &m_globalData->topCallFrame);
 }
 
index ad2f94b..a0a8165 100644 (file)
@@ -1446,6 +1446,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_direct)
     PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
     JSValue baseValue = stackFrame.args[0].jsValue();
     ASSERT(baseValue.isObject());
+    
     asObject(baseValue)->putDirect(callFrame->globalData(), ident, stackFrame.args[2].jsValue(), slot);
     
     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
@@ -1931,7 +1932,7 @@ DEFINE_STUB_FUNCTION(void, optimize_from_loop)
     unsigned bytecodeIndex = stackFrame.args[0].int32();
 
 #if ENABLE(JIT_VERBOSE_OSR)
-    dataLog("Entered optimize_from_loop with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
+    dataLog("%p: Entered optimize_from_loop with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock, codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
 #endif
 
     if (codeBlock->hasOptimizedReplacement()) {
@@ -2186,45 +2187,13 @@ DEFINE_STUB_FUNCTION(void*, op_construct_jitCompile)
     return result;
 }
 
-inline CallFrame* arityCheckFor(CallFrame* callFrame, RegisterFile* registerFile, CodeSpecializationKind kind)
-{
-    JSFunction* callee = asFunction(callFrame->callee());
-    ASSERT(!callee->isHostFunction());
-    CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecodeFor(kind);
-    int argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
-
-    // This ensures enough space for the worst case scenario of zero arguments passed by the caller.
-    if (!registerFile->grow(callFrame->registers() + newCodeBlock->numParameters() + newCodeBlock->m_numCalleeRegisters))
-        return 0;
-
-    ASSERT(argumentCountIncludingThis < newCodeBlock->numParameters());
-
-    // Too few arguments -- copy call frame and arguments, then fill in missing arguments with undefined.
-    size_t delta = newCodeBlock->numParameters() - argumentCountIncludingThis;
-    Register* src = callFrame->registers();
-    Register* dst = callFrame->registers() + delta;
-
-    int i;
-    int end = -CallFrame::offsetFor(argumentCountIncludingThis);
-    for (i = -1; i >= end; --i)
-        dst[i] = src[i];
-
-    end -= delta;
-    for ( ; i >= end; --i)
-        dst[i] = jsUndefined();
-
-    CallFrame* newCallFrame = CallFrame::create(dst);
-    ASSERT((void*)newCallFrame <= registerFile->end());
-    return newCallFrame;
-}
-
 DEFINE_STUB_FUNCTION(void*, op_call_arityCheck)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
 
-    CallFrame* newCallFrame = arityCheckFor(callFrame, stackFrame.registerFile, CodeForCall);
+    CallFrame* newCallFrame = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.registerFile, CodeForCall);
     if (!newCallFrame)
         return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createStackOverflowError(callFrame->callerFrame()));
 
@@ -2237,7 +2206,7 @@ DEFINE_STUB_FUNCTION(void*, op_construct_arityCheck)
 
     CallFrame* callFrame = stackFrame.callFrame;
 
-    CallFrame* newCallFrame = arityCheckFor(callFrame, stackFrame.registerFile, CodeForConstruct);
+    CallFrame* newCallFrame = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.registerFile, CodeForConstruct);
     if (!newCallFrame)
         return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createStackOverflowError(callFrame->callerFrame()));
 
@@ -2314,6 +2283,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_NotJSFunction)
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
+    
     JSValue callee = callFrame->calleeAsValue();
 
     CallData callData;
index fe5f522..890d997 100644 (file)
@@ -37,8 +37,6 @@
 #include "ThunkGenerators.h"
 #include <wtf/HashMap.h>
 
-#if ENABLE(JIT)
-
 namespace JSC {
 
     struct StructureStubInfo;
@@ -263,6 +261,8 @@ namespace JSC {
 
 #define JITSTACKFRAME_ARGS_INDEX (OBJECT_OFFSETOF(JITStackFrame, args) / sizeof(void*))
 
+#if ENABLE(JIT)
+
 #define STUB_ARGS_DECLARATION void** args
 #define STUB_ARGS (args)
 
@@ -456,8 +456,8 @@ extern "C" {
     void* JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION);
 } // extern "C"
 
-} // namespace JSC
-
 #endif // ENABLE(JIT)
 
+} // namespace JSC
+
 #endif // JITStubs_h
index d54dedc..05d1ce5 100644 (file)
 #ifndef JSInterfaceJIT_h
 #define JSInterfaceJIT_h
 
+#include "BytecodeConventions.h"
 #include "JITCode.h"
 #include "JITStubs.h"
+#include "JSString.h"
 #include "JSValue.h"
 #include "MacroAssembler.h"
 #include "RegisterFile.h"
diff --git a/Source/JavaScriptCore/llint/LLIntCommon.h b/Source/JavaScriptCore/llint/LLIntCommon.h
new file mode 100644 (file)
index 0000000..6b908ea
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 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 LLIntCommon_h
+#define LLIntCommon_h
+
+// Print every instruction executed.
+#define LLINT_EXECUTION_TRACING 0
+
+// Print some information for some of the more subtle slow paths.
+#define LLINT_SLOW_PATH_TRACING 0
+
+// Disable inline allocation in the interpreter. This is great if you're changing
+// how the GC allocates.
+#define LLINT_ALWAYS_ALLOCATE_SLOW 0
+
+// Enable OSR into the JIT. Disabling this while the LLInt is enabled effectively
+// turns off all JIT'ing, since in LLInt's parlance, OSR subsumes any form of JIT
+// invocation.
+#if ENABLE(JIT)
+#define LLINT_OSR_TO_JIT 1
+#else
+#define LLINT_OSR_TO_JIT 0
+#endif
+
+#endif // LLIntCommon_h
+
diff --git a/Source/JavaScriptCore/llint/LLIntData.cpp b/Source/JavaScriptCore/llint/LLIntData.cpp
new file mode 100644 (file)
index 0000000..c0fe781
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2011 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 "LLIntData.h"
+
+#if ENABLE(LLINT)
+
+#include "BytecodeConventions.h"
+#include "CodeType.h"
+#include "Instruction.h"
+#include "LowLevelInterpreter.h"
+#include "Opcode.h"
+
+namespace JSC { namespace LLInt {
+
+Data::Data()
+    : m_exceptionInstructions(new Instruction[maxOpcodeLength + 1])
+    , m_opcodeMap(new Opcode[numOpcodeIDs])
+{
+    for (int i = 0; i < maxOpcodeLength + 1; ++i)
+        m_exceptionInstructions[i].u.pointer = bitwise_cast<void*>(&llint_throw_from_slow_path_trampoline);
+#define OPCODE_ENTRY(opcode, length) m_opcodeMap[opcode] = bitwise_cast<void*>(&llint_##opcode);
+    FOR_EACH_OPCODE_ID(OPCODE_ENTRY);
+#undef OPCODE_ENTRY
+}
+
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmissing-noreturn"
+#endif
+void Data::performAssertions(JSGlobalData& globalData)
+{
+    UNUSED_PARAM(globalData);
+    
+    // Assertions to match LowLevelInterpreter.asm.  If you change any of this code, be
+    // prepared to change LowLevelInterpreter.asm as well!!
+    ASSERT(RegisterFile::CallFrameHeaderSize * 8 == 48);
+    ASSERT(RegisterFile::ArgumentCount * 8 == -48);
+    ASSERT(RegisterFile::CallerFrame * 8 == -40);
+    ASSERT(RegisterFile::Callee * 8 == -32);
+    ASSERT(RegisterFile::ScopeChain * 8 == -24);
+    ASSERT(RegisterFile::ReturnPC * 8 == -16);
+    ASSERT(RegisterFile::CodeBlock * 8 == -8);
+    ASSERT(CallFrame::argumentOffsetIncludingThis(0) == -RegisterFile::CallFrameHeaderSize - 1);
+#if CPU(BIG_ENDIAN)
+    ASSERT(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag) == 0);
+    ASSERT(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload) == 4);
+#else
+    ASSERT(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag) == 4);
+    ASSERT(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload) == 0);
+#endif
+    ASSERT(JSValue::Int32Tag == -1);
+    ASSERT(JSValue::BooleanTag == -2);
+    ASSERT(JSValue::NullTag == -3);
+    ASSERT(JSValue::UndefinedTag == -4);
+    ASSERT(JSValue::CellTag == -5);
+    ASSERT(JSValue::EmptyValueTag == -6);
+    ASSERT(JSValue::DeletedValueTag == -7);
+    ASSERT(JSValue::LowestTag == -7);
+    ASSERT(StringType == 5);
+    ASSERT(ObjectType == 13);
+    ASSERT(MasqueradesAsUndefined == 1);
+    ASSERT(ImplementsHasInstance == 2);
+    ASSERT(ImplementsDefaultHasInstance == 8);
+    ASSERT(&globalData.heap.allocatorForObjectWithoutDestructor(sizeof(JSFinalObject)) - &globalData.heap.firstAllocatorWithoutDestructors() == 3);
+    ASSERT(FirstConstantRegisterIndex == 0x40000000);
+    ASSERT(GlobalCode == 0);
+    ASSERT(EvalCode == 1);
+    ASSERT(FunctionCode == 2);
+    
+    // FIXME: make these assertions less horrible.
+#if !ASSERT_DISABLED
+    Vector<int> testVector;
+    testVector.resize(42);
+    ASSERT(bitwise_cast<size_t*>(&testVector)[0] == 42);
+    ASSERT(bitwise_cast<int**>(&testVector)[1] == testVector.begin());
+#endif
+
+    ASSERT(StringImpl::s_hashFlag8BitBuffer == 64);
+}
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
+
+Data::~Data()
+{
+    delete[] m_exceptionInstructions;
+    delete[] m_opcodeMap;
+}
+
+} } // namespace JSC::LLInt
+
+#endif // ENABLE(LLINT)
diff --git a/Source/JavaScriptCore/llint/LLIntData.h b/Source/JavaScriptCore/llint/LLIntData.h
new file mode 100644 (file)
index 0000000..ba8daed
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2011 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 LLIntData_h
+#define LLIntData_h
+
+#include "Opcode.h"
+#include <wtf/Platform.h>
+
+namespace JSC {
+
+class JSGlobalData;
+struct Instruction;
+
+namespace LLInt {
+
+#if ENABLE(LLINT)
+class Data {
+public:
+    Data();
+    ~Data();
+    
+    void performAssertions(JSGlobalData&);
+    
+    Instruction* exceptionInstructions()
+    {
+        return m_exceptionInstructions;
+    }
+    
+    Opcode* opcodeMap()
+    {
+        return m_opcodeMap;
+    }
+private:
+    Instruction* m_exceptionInstructions;
+    Opcode* m_opcodeMap;
+};
+#else // ENABLE(LLINT)
+
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmissing-noreturn"
+#endif
+
+class Data {
+public:
+    void performAssertions(JSGlobalData&) { }
+
+    Instruction* exceptionInstructions()
+    {
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+    
+    Opcode* opcodeMap()
+    {
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+};
+
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
+
+#endif // ENABLE(LLINT)
+
+} } // namespace JSC::LLInt
+
+#endif // LLIntData_h
+
diff --git a/Source/JavaScriptCore/llint/LLIntEntrypoints.cpp b/Source/JavaScriptCore/llint/LLIntEntrypoints.cpp
new file mode 100644 (file)
index 0000000..f610f4b
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 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 "LLIntEntrypoints.h"
+
+#if ENABLE(LLINT)
+
+#include "JITCode.h"
+#include "JSGlobalData.h"
+#include "LLIntThunks.h"
+#include "LowLevelInterpreter.h"
+
+namespace JSC { namespace LLInt {
+
+void getFunctionEntrypoint(JSGlobalData& globalData, CodeSpecializationKind kind, JITCode& jitCode, MacroAssemblerCodePtr& arityCheck)
+{
+    if (!globalData.canUseJIT()) {
+        if (kind == CodeForCall) {
+            jitCode = JITCode::HostFunction(MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_function_for_call_prologue))));
+            arityCheck = MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_function_for_call_arity_check));
+            return;
+        }
+
+        ASSERT(kind == CodeForConstruct);
+        jitCode = JITCode::HostFunction(MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_function_for_construct_prologue))));
+        arityCheck = MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_function_for_construct_arity_check));
+        return;
+    }
+    
+    if (kind == CodeForCall) {
+        jitCode = JITCode(globalData.getCTIStub(functionForCallEntryThunkGenerator), JITCode::InterpreterThunk);
+        arityCheck = globalData.getCTIStub(functionForCallArityCheckThunkGenerator).code();
+        return;
+    }
+
+    ASSERT(kind == CodeForConstruct);
+    jitCode = JITCode(globalData.getCTIStub(functionForConstructEntryThunkGenerator), JITCode::InterpreterThunk);
+    arityCheck = globalData.getCTIStub(functionForConstructArityCheckThunkGenerator).code();
+}
+
+void getEvalEntrypoint(JSGlobalData& globalData, JITCode& jitCode)
+{
+    if (!globalData.canUseJIT()) {
+        jitCode = JITCode::HostFunction(MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_eval_prologue))));
+        return;
+    }
+    
+    jitCode = JITCode(globalData.getCTIStub(evalEntryThunkGenerator), JITCode::InterpreterThunk);
+}
+
+void getProgramEntrypoint(JSGlobalData& globalData, JITCode& jitCode)
+{
+    if (!globalData.canUseJIT()) {
+        jitCode = JITCode::HostFunction(MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_program_prologue))));
+        return;
+    }
+    
+    jitCode = JITCode(globalData.getCTIStub(programEntryThunkGenerator), JITCode::InterpreterThunk);
+}
+
+} } // namespace JSC::LLInt
+
+#endif // ENABLE(LLINT)
diff --git a/Source/JavaScriptCore/llint/LLIntEntrypoints.h b/Source/JavaScriptCore/llint/LLIntEntrypoints.h
new file mode 100644 (file)
index 0000000..dd7c277
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 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 LLIntEntrypoints_h
+#define LLIntEntrypoints_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(LLINT)
+
+#include "CodeSpecializationKind.h"
+
+namespace JSC {
+
+class EvalCodeBlock;
+class JITCode;
+class JSGlobalData;
+class MacroAssemblerCodePtr;
+class MacroAssemblerCodeRef;
+class ProgramCodeBlock;
+
+namespace LLInt {
+
+void getFunctionEntrypoint(JSGlobalData&, CodeSpecializationKind, JITCode&, MacroAssemblerCodePtr& arityCheck);
+void getEvalEntrypoint(JSGlobalData&, JITCode&);
+void getProgramEntrypoint(JSGlobalData&, JITCode&);
+
+inline void getEntrypoint(JSGlobalData& globalData, EvalCodeBlock*, JITCode& jitCode)
+{
+    getEvalEntrypoint(globalData, jitCode);
+}
+
+inline void getEntrypoint(JSGlobalData& globalData, ProgramCodeBlock*, JITCode& jitCode)
+{
+    getProgramEntrypoint(globalData, jitCode);
+}
+
+} } // namespace JSC::LLInt
+
+#endif // ENABLE(LLINT)
+
+#endif // LLIntEntrypoints_h
diff --git a/Source/JavaScriptCore/llint/LLIntExceptions.cpp b/Source/JavaScriptCore/llint/LLIntExceptions.cpp
new file mode 100644 (file)
index 0000000..a7d1a96
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2011 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 "LLIntExceptions.h"
+
+#if ENABLE(LLINT)
+
+#include "CallFrame.h"
+#include "CodeBlock.h"
+#include "Instruction.h"
+#include "JITExceptions.h"
+#include "LLIntCommon.h"
+#include "LowLevelInterpreter.h"
+
+namespace JSC { namespace LLInt {
+
+void interpreterThrowInCaller(ExecState* exec, ReturnAddressPtr pc)
+{
+    JSGlobalData* globalData = &exec->globalData();
+#if LLINT_SLOW_PATH_TRACING
+    dataLog("Throwing exception %s.\n", globalData->exception.description());
+#endif
+    genericThrow(
+        globalData, exec, globalData->exception,
+        exec->codeBlock()->bytecodeOffset(exec, pc));
+}
+
+Instruction* returnToThrowForThrownException(ExecState* exec)
+{
+    return exec->globalData().llintData.exceptionInstructions();
+}
+
+Instruction* returnToThrow(ExecState* exec, Instruction* pc)
+{
+    JSGlobalData* globalData = &exec->globalData();
+#if LLINT_SLOW_PATH_TRACING
+    dataLog("Throwing exception %s (returnToThrow).\n", globalData->exception.description());
+#endif
+    genericThrow(globalData, exec, globalData->exception, pc - exec->codeBlock()->instructions().begin());
+    
+    return globalData->llintData.exceptionInstructions();
+}
+
+void* callToThrow(ExecState* exec, Instruction* pc)
+{
+    JSGlobalData* globalData = &exec->globalData();
+#if LLINT_SLOW_PATH_TRACING
+    dataLog("Throwing exception %s (callToThrow).\n", globalData->exception.description());
+#endif
+    genericThrow(globalData, exec, globalData->exception, pc - exec->codeBlock()->instructions().begin());
+    
+    return bitwise_cast<void*>(&llint_throw_during_call_trampoline);
+}
+
+} } // namespace JSC::LLInt
+
+#endif // ENABLE(LLINT)
diff --git a/Source/JavaScriptCore/llint/LLIntExceptions.h b/Source/JavaScriptCore/llint/LLIntExceptions.h
new file mode 100644 (file)
index 0000000..3baa3f4
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2011 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 LLIntExceptions_h
+#define LLIntExceptions_h
+
+#include <wtf/Platform.h>
+#include <wtf/StdLibExtras.h>
+
+#if ENABLE(LLINT)
+
+#include "MacroAssemblerCodeRef.h"
+
+namespace JSC {
+
+class ExecState;
+struct Instruction;
+
+namespace LLInt {
+
+// Throw the currently active exception in the context of the caller's call frame.
+void interpreterThrowInCaller(ExecState* callerFrame, ReturnAddressPtr);
+
+// Tells you where to jump to if you want to return-to-throw, after you've already
+// set up all information needed to throw the exception.
+Instruction* returnToThrowForThrownException(ExecState*);
+
+// Saves the current PC in the global data for safe-keeping, and gives you a PC
+// that you can tell the interpreter to go to, which when advanced between 1
+// and 9 slots will give you an "instruction" that threads to the interpreter's
+// exception handler. Note that if you give it the PC for exception handling,
+// it's smart enough to just return that PC without doing anything else; this
+// lets you thread exception handling through common helper functions used by
+// other helpers.
+Instruction* returnToThrow(ExecState*, Instruction*);
+
+// Use this when you're throwing to a call thunk.
+void* callToThrow(ExecState*, Instruction*);
+
+} } // namespace JSC::LLInt
+
+#endif // ENABLE(LLINT)
+
+#endif // LLIntExceptions_h
diff --git a/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h b/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h
new file mode 100644 (file)
index 0000000..f140701
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 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 LLIntOfflineAsmConfig_h
+#define LLIntOfflineAsmConfig_h
+
+#include "LLIntCommon.h"
+#include <wtf/Assertions.h>
+#include <wtf/InlineAsm.h>
+#include <wtf/Platform.h>
+
+#if CPU(X86)
+#define OFFLINE_ASM_X86 1
+#else
+#define OFFLINE_ASM_X86 0
+#endif
+
+#if CPU(ARM_THUMB2)
+#define OFFLINE_ASM_ARMv7 1
+#else
+#define OFFLINE_ASM_ARMv7 0
+#endif
+
+#if !ASSERT_DISABLED
+#define OFFLINE_ASM_ASSERT_ENABLED 1
+#else
+#define OFFLINE_ASM_ASSERT_ENABLED 0
+#endif
+
+#if CPU(BIG_ENDIAN)
+#define OFFLINE_ASM_BIG_ENDIAN 1
+#else
+#define OFFLINE_ASM_BIG_ENDIAN 0
+#endif
+
+#if LLINT_OSR_TO_JIT
+#define OFFLINE_ASM_JIT_ENABLED 1
+#else
+#define OFFLINE_ASM_JIT_ENABLED 0
+#endif
+
+#if LLINT_EXECUTION_TRACING
+#define OFFLINE_ASM_EXECUTION_TRACING 1
+#else
+#define OFFLINE_ASM_EXECUTION_TRACING 0
+#endif
+
+#if LLINT_ALWAYS_ALLOCATE_SLOW
+#define OFFLINE_ASM_ALWAYS_ALLOCATE_SLOW 1
+#else
+#define OFFLINE_ASM_ALWAYS_ALLOCATE_SLOW 0
+#endif
+
+#if CPU(ARM_THUMB2)
+#define OFFLINE_ASM_GLOBAL_LABEL(label)          \
+    ".globl " SYMBOL_STRING(label) "\n"          \
+    HIDE_SYMBOL(name) "\n"                       \
+    ".thumb\n"                                   \
+    ".thumb_func " THUMB_FUNC_PARAM(label) "\n"  \
+    SYMBOL_STRING(label) ":\n"
+#else
+#define OFFLINE_ASM_GLOBAL_LABEL(label)         \
+    ".globl " SYMBOL_STRING(label) "\n"         \
+    HIDE_SYMBOL(name) "\n"                      \
+    SYMBOL_STRING(label) ":\n"
+#endif
+
+#endif // LLIntOfflineAsmConfig_h
diff --git a/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp b/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp
new file mode 100644 (file)
index 0000000..e8bb378
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2012 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 "CodeBlock.h"
+#include "Executable.h"
+#include "Heap.h"
+#include "Interpreter.h"
+#include "JITStubs.h"
+#include "JSArray.h"
+#include "JSCell.h"
+#include "JSFunction.h"
+#include "JSGlobalData.h"
+#include "JSGlobalObject.h"
+#include "JSObject.h"
+#include "JSPropertyNameIterator.h"
+#include "JSString.h"
+#include "JSTypeInfo.h"
+#include "JSVariableObject.h"
+#include "JumpTable.h"
+#include "LLIntOfflineAsmConfig.h"
+#include "MarkedSpace.h"
+#include "RegisterFile.h"
+#include "ScopeChain.h"
+#include "Structure.h"
+#include "StructureChain.h"
+#include "ValueProfile.h"
+#include <wtf/text/StringImpl.h>
+
+namespace JSC {
+
+#define OFFLINE_ASM_OFFSETOF(clazz, field) OBJECT_OFFSETOF(clazz, field)
+
+class LLIntOffsetsExtractor {
+public:
+    static const unsigned* dummy();
+};
+
+const unsigned* LLIntOffsetsExtractor::dummy()
+{
+// This is a file generated by offlineasm/generate_offsets_extractor.rb, and contains code
+// to create a table of offsets, sizes, and a header identifying what combination of
+// Platform.h macros we have set. We include it inside of a method on LLIntOffsetsExtractor
+// because the fields whose offsets we're extracting are mostly private. So we make their
+// classes friends with LLIntOffsetsExtractor, and include the header here, to get the C++
+// compiler to kindly step aside and yield to our best intentions.
+#include "LLIntDesiredOffsets.h"
+    return extractorTable;
+}
+
+} // namespace JSC
+
+int main(int, char**)
+{
+    // Out of an abundance of caution, make sure that LLIntOffsetsExtractor::dummy() is live,
+    // and the extractorTable is live, too.
+    printf("%p\n", JSC::LLIntOffsetsExtractor::dummy());
+    return 0;
+}
diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
new file mode 100644 (file)
index 0000000..3203d25
--- /dev/null
@@ -0,0 +1,1558 @@
+/*
+ * Copyright (C) 2011, 2012 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 "LLIntSlowPaths.h"
+
+#if ENABLE(LLINT)
+
+#include "Arguments.h"
+#include "CallFrame.h"
+#include "CommonSlowPaths.h"
+#include "GetterSetter.h"
+#include "HostCallReturnValue.h"
+#include "Interpreter.h"
+#include "JIT.h"
+#include "JITDriver.h"
+#include "JSActivation.h"
+#include "JSByteArray.h"
+#include "JSGlobalObjectFunctions.h"
+#include "JSPropertyNameIterator.h"
+#include "JSStaticScopeObject.h"
+#include "JSString.h"
+#include "JSValue.h"
+#include "LLIntCommon.h"
+#include "LLIntExceptions.h"
+#include "LowLevelInterpreter.h"
+#include "Operations.h"
+
+namespace JSC { namespace LLInt {
+
+#define LLINT_BEGIN_NO_SET_PC() \
+    JSGlobalData& globalData = exec->globalData();      \
+    NativeCallFrameTracer tracer(&globalData, exec)
+
+#define LLINT_SET_PC_FOR_STUBS() \
+    exec->setCurrentVPC(pc + 1)
+
+#define LLINT_BEGIN()                           \
+    LLINT_BEGIN_NO_SET_PC();                    \
+    LLINT_SET_PC_FOR_STUBS()
+
+#define LLINT_OP(index) (exec->uncheckedR(pc[index].u.operand))
+#define LLINT_OP_C(index) (exec->r(pc[index].u.operand))
+
+#define LLINT_RETURN_TWO(first, second) do {       \
+        union {                                    \
+            struct {                               \
+                void* a;                           \
+                void* b;                           \
+            } pair;                                \
+            int64_t i;                             \
+        } __rt_u;                                  \
+        __rt_u.pair.a = first;                     \
+        __rt_u.pair.b = second;                    \
+        return __rt_u.i;                           \
+    } while (false)
+
+#define LLINT_END_IMPL() LLINT_RETURN_TWO(pc, exec)
+
+#define LLINT_THROW(exceptionToThrow) do {                        \
+        globalData.exception = (exceptionToThrow);                \
+        pc = returnToThrow(exec, pc);                             \
+        LLINT_END_IMPL();                                         \
+    } while (false)
+
+#define LLINT_CHECK_EXCEPTION() do {                    \
+        if (UNLIKELY(globalData.exception)) {           \
+            pc = returnToThrow(exec, pc);               \
+            LLINT_END_IMPL();                           \
+        }                                               \
+    } while (false)
+
+#define LLINT_END() do {                        \
+        LLINT_CHECK_EXCEPTION();                \
+        LLINT_END_IMPL();                       \
+    } while (false)
+
+#define LLINT_BRANCH(opcode, condition) do {                      \
+        bool __b_condition = (condition);                         \
+        LLINT_CHECK_EXCEPTION();                                  \
+        if (__b_condition)                                        \
+            pc += pc[OPCODE_LENGTH(opcode) - 1].u.operand;        \
+        else                                                      \
+            pc += OPCODE_LENGTH(opcode);                          \
+        LLINT_END_IMPL();                                         \
+    } while (false)
+
+#define LLINT_RETURN(value) do {                \
+        JSValue __r_returnValue = (value);      \
+        LLINT_CHECK_EXCEPTION();                \
+        LLINT_OP(1) = __r_returnValue;          \
+        LLINT_END_IMPL();                       \
+    } while (false)
+
+#define LLINT_RETURN_PROFILED(opcode, value) do {               \
+        JSValue __rp_returnValue = (value);                     \
+        LLINT_CHECK_EXCEPTION();                                \
+        LLINT_OP(1) = __rp_returnValue;                         \
+        pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \
+            JSValue::encode(__rp_returnValue);                  \
+        LLINT_END_IMPL();                                       \
+    } while (false)
+
+#define LLINT_CALL_END_IMPL(exec, callTarget) LLINT_RETURN_TWO((callTarget), (exec))
+
+#define LLINT_CALL_THROW(exec, pc, exceptionToThrow) do {               \
+        ExecState* __ct_exec = (exec);                                  \
+        Instruction* __ct_pc = (pc);                                    \
+        globalData.exception = (exceptionToThrow);                      \
+        LLINT_CALL_END_IMPL(__ct_exec, callToThrow(__ct_exec, __ct_pc)); \
+    } while (false)
+
+#define LLINT_CALL_CHECK_EXCEPTION(exec, pc) do {                       \
+        ExecState* __cce_exec = (exec);                                 \
+        Instruction* __cce_pc = (pc);                                   \
+        if (UNLIKELY(globalData.exception))                              \
+            LLINT_CALL_END_IMPL(__cce_exec, callToThrow(__cce_exec, __cce_pc)); \
+    } while (false)
+
+#define LLINT_CALL_RETURN(exec, pc, callTarget) do {                    \
+        ExecState* __cr_exec = (exec);                                  \
+        Instruction* __cr_pc = (pc);                                    \
+        void* __cr_callTarget = (callTarget);                           \
+        LLINT_CALL_CHECK_EXCEPTION(__cr_exec->callerFrame(), __cr_pc);  \
+        LLINT_CALL_END_IMPL(__cr_exec, __cr_callTarget);                \
+    } while (false)
+
+extern "C" SlowPathReturnType llint_trace_operand(ExecState* exec, Instruction* pc, int fromWhere, int operand)
+{
+    LLINT_BEGIN();
+    dataLog("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d\n",
+            exec->codeBlock(),
+            exec,
+            static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
+            exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode),
+            fromWhere,
+            operand,
+            pc[operand].u.operand);
+    LLINT_END();
+}
+
+extern "C" SlowPathReturnType llint_trace_value(ExecState* exec, Instruction* pc, int fromWhere, int operand)
+{
+    LLINT_BEGIN();
+    JSValue value = LLINT_OP_C(operand).jsValue();
+    union {
+        struct {
+            uint32_t tag;
+            uint32_t payload;
+        } bits;
+        EncodedJSValue asValue;
+    } u;
+    u.asValue = JSValue::encode(value);
+    dataLog("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d: %08x:%08x: %s\n",
+            exec->codeBlock(),
+            exec,
+            static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
+            exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode),
+            fromWhere,
+            operand,
+            pc[operand].u.operand,
+            u.bits.tag,
+            u.bits.payload,
+            value.description());
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(trace_prologue)
+{
+    LLINT_BEGIN();
+    dataLog("%p / %p: in prologue.\n", exec->codeBlock(), exec);
+    LLINT_END();
+}
+
+static void traceFunctionPrologue(ExecState* exec, const char* comment, CodeSpecializationKind kind)
+{
+    JSFunction* callee = asFunction(exec->callee());
+    FunctionExecutable* executable = callee->jsExecutable();
+    CodeBlock* codeBlock = &executable->generatedBytecodeFor(kind);
+    dataLog("%p / %p: in %s of function %p, executable %p; numVars = %u, numParameters = %u, numCalleeRegisters = %u, caller = %p.\n",
+            codeBlock, exec, comment, callee, executable,
+            codeBlock->m_numVars, codeBlock->numParameters(), codeBlock->m_numCalleeRegisters,
+            exec->callerFrame());
+}
+
+LLINT_SLOW_PATH_DECL(trace_prologue_function_for_call)
+{
+    LLINT_BEGIN();
+    traceFunctionPrologue(exec, "call prologue", CodeForCall);
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(trace_prologue_function_for_construct)
+{
+    LLINT_BEGIN();
+    traceFunctionPrologue(exec, "construct prologue", CodeForConstruct);
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(trace_arityCheck_for_call)
+{
+    LLINT_BEGIN();
+    traceFunctionPrologue(exec, "call arity check", CodeForCall);
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(trace_arityCheck_for_construct)
+{
+    LLINT_BEGIN();
+    traceFunctionPrologue(exec, "construct arity check", CodeForConstruct);
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(trace)
+{
+    LLINT_BEGIN();
+    dataLog("%p / %p: executing bc#%zu, %s, scope %p\n",
+            exec->codeBlock(),
+            exec,
+            static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
+            opcodeNames[exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode)],
+            exec->scopeChain());
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(special_trace)
+{
+    LLINT_BEGIN();
+    dataLog("%p / %p: executing special case bc#%zu, op#%u, return PC is %p\n",
+            exec->codeBlock(),
+            exec,
+            static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
+            exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode),
+            exec->returnPC().value());
+    LLINT_END();
+}
+
+inline bool shouldJIT(ExecState* exec)
+{
+    // You can modify this to turn off JITting without rebuilding the world.
+    return exec->globalData().canUseJIT();
+}
+
+enum EntryKind { Prologue, ArityCheck };
+static SlowPathReturnType entryOSR(ExecState* exec, Instruction* pc, CodeBlock* codeBlock, const char *name, EntryKind kind)
+{
+#if ENABLE(JIT_VERBOSE_OSR)
+    dataLog("%p: Entered %s with executeCounter = %d\n", codeBlock, name, codeBlock->llintExecuteCounter());
+#endif
+    
+    if (!shouldJIT(exec)) {
+        codeBlock->dontJITAnytimeSoon();
+        LLINT_RETURN_TWO(0, exec);
+    }
+    if (!codeBlock->jitCompile(exec->globalData())) {
+#if ENABLE(JIT_VERBOSE_OSR)
+        dataLog("    Code was already compiled.\n");
+#endif
+    }
+    codeBlock->jitSoon();
+    if (kind == Prologue)
+        LLINT_RETURN_TWO(codeBlock->getJITCode().executableAddressAtOffset(0), exec);
+    ASSERT(kind == ArityCheck);
+    LLINT_RETURN_TWO(codeBlock->getJITCodeWithArityCheck().executableAddress(), exec);
+}
+
+LLINT_SLOW_PATH_DECL(entry_osr)
+{
+    return entryOSR(exec, pc, exec->codeBlock(), "entry_osr", Prologue);
+}
+
+LLINT_SLOW_PATH_DECL(entry_osr_function_for_call)
+{
+    return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall), "entry_osr_function_for_call", Prologue);
+}
+
+LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct)
+{
+    return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct), "entry_osr_function_for_construct", Prologue);
+}
+
+LLINT_SLOW_PATH_DECL(entry_osr_function_for_call_arityCheck)
+{
+    return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall), "entry_osr_function_for_call_arityCheck", ArityCheck);
+}
+
+LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct_arityCheck)
+{
+    return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct), "entry_osr_function_for_construct_arityCheck", ArityCheck);
+}
+
+LLINT_SLOW_PATH_DECL(loop_osr)
+{
+    CodeBlock* codeBlock = exec->codeBlock();
+    
+#if ENABLE(JIT_VERBOSE_OSR)
+    dataLog("%p: Entered loop_osr with executeCounter = %d\n", codeBlock, codeBlock->llintExecuteCounter());
+#endif
+    
+    if (!shouldJIT(exec)) {
+        codeBlock->dontJITAnytimeSoon();
+        LLINT_RETURN_TWO(0, exec);
+    }
+    
+    if (!codeBlock->jitCompile(exec->globalData())) {
+#if ENABLE(JIT_VERBOSE_OSR)
+        dataLog("    Code was already compiled.\n");
+#endif
+    }
+    codeBlock->jitSoon();
+    
+    ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT);
+    
+    Vector<BytecodeAndMachineOffset> map;
+    codeBlock->jitCodeMap()->decode(map);
+    BytecodeAndMachineOffset* mapping = binarySearch<BytecodeAndMachineOffset, unsigned, BytecodeAndMachineOffset::getBytecodeIndex>(map.begin(), map.size(), pc - codeBlock->instructions().begin());
+    ASSERT(mapping);
+    ASSERT(mapping->m_bytecodeIndex == static_cast<unsigned>(pc - codeBlock->instructions().begin()));
+    
+    void* jumpTarget = codeBlock->getJITCode().executableAddressAtOffset(mapping->m_machineCodeOffset);
+    ASSERT(jumpTarget);
+    
+    LLINT_RETURN_TWO(jumpTarget, exec);
+}
+
+LLINT_SLOW_PATH_DECL(replace)
+{
+    CodeBlock* codeBlock = exec->codeBlock();
+    
+#if ENABLE(JIT_VERBOSE_OSR)
+    dataLog("%p: Entered replace with executeCounter = %d\n", codeBlock, codeBlock->llintExecuteCounter());
+#endif
+    
+    if (shouldJIT(exec)) {
+        if (!codeBlock->jitCompile(exec->globalData())) {
+#if ENABLE(JIT_VERBOSE_OSR)
+            dataLog("    Code was already compiled.\n");
+#endif
+        }
+        codeBlock->jitSoon();
+    } else
+        codeBlock->dontJITAnytimeSoon();
+    LLINT_END_IMPL();
+}
+
+LLINT_SLOW_PATH_DECL(register_file_check)
+{
+    LLINT_BEGIN();
+#if LLINT_SLOW_PATH_TRACING
+    dataLog("Checking stack height with exec = %p.\n", exec);
+    dataLog("CodeBlock = %p.\n", exec->codeBlock());
+    dataLog("Num callee registers = %u.\n", exec->codeBlock()->m_numCalleeRegisters);
+    dataLog("Num vars = %u.\n", exec->codeBlock()->m_numVars);
+    dataLog("Current end is at %p.\n", exec->globalData().interpreter->registerFile().end());
+#endif
+    ASSERT(&exec->registers()[exec->codeBlock()->m_numCalleeRegisters] > exec->globalData().interpreter->registerFile().end());
+    if (UNLIKELY(!globalData.interpreter->registerFile().grow(&exec->registers()[exec->codeBlock()->m_numCalleeRegisters]))) {
+        ReturnAddressPtr returnPC = exec->returnPC();
+        exec = exec->callerFrame();
+        globalData.exception = createStackOverflowError(exec);
+        interpreterThrowInCaller(exec, returnPC);
+        pc = returnToThrowForThrownException(exec);
+    }
+    LLINT_END_IMPL();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_call_arityCheck)
+{
+    LLINT_BEGIN();
+    ExecState* newExec = CommonSlowPaths::arityCheckFor(exec, &globalData.interpreter->registerFile(), CodeForCall);
+    if (!newExec) {
+        ReturnAddressPtr returnPC = exec->returnPC();
+        exec = exec->callerFrame();
+        globalData.exception = createStackOverflowError(exec);
+        interpreterThrowInCaller(exec, returnPC);
+        LLINT_RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
+    }
+    LLINT_RETURN_TWO(0, newExec);
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_construct_arityCheck)
+{
+    LLINT_BEGIN();
+    ExecState* newExec = CommonSlowPaths::arityCheckFor(exec, &globalData.interpreter->registerFile(), CodeForConstruct);
+    if (!newExec) {
+        ReturnAddressPtr returnPC = exec->returnPC();
+        exec = exec->callerFrame();
+        globalData.exception = createStackOverflowError(exec);
+        interpreterThrowInCaller(exec, returnPC);
+        LLINT_RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
+    }
+    LLINT_RETURN_TWO(0, newExec);
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_create_activation)
+{
+    LLINT_BEGIN();
+#if LLINT_SLOW_PATH_TRACING
+    dataLog("Creating an activation, exec = %p!\n", exec);
+#endif
+    JSActivation* activation = JSActivation::create(globalData, exec, static_cast<FunctionExecutable*>(exec->codeBlock()->ownerExecutable()));
+    exec->setScopeChain(exec->scopeChain()->push(activation));
+    LLINT_RETURN(JSValue(activation));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_create_arguments)
+{
+    LLINT_BEGIN();
+    JSValue arguments = JSValue(Arguments::create(globalData, exec));
+    LLINT_CHECK_EXCEPTION();
+    exec->uncheckedR(pc[1].u.operand) = arguments;
+    exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)) = arguments;
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_create_this)
+{
+    LLINT_BEGIN();
+    JSFunction* constructor = asFunction(exec->callee());
+    
+#if !ASSERT_DISABLED
+    ConstructData constructData;
+    ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
+#endif
+    
+    Structure* structure;
+    JSValue proto = LLINT_OP(2).jsValue();
+    if (proto.isObject())
+        structure = asObject(proto)->inheritorID(globalData);
+    else
+        structure = constructor->scope()->globalObject->emptyObjectStructure();
+    
+    LLINT_RETURN(constructEmptyObject(exec, structure));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_convert_this)
+{
+    LLINT_BEGIN();
+    JSValue v1 = LLINT_OP(1).jsValue();
+    ASSERT(v1.isPrimitive());
+    LLINT_RETURN(v1.toThisObject(exec));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_new_object)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(constructEmptyObject(exec));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_new_array)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(constructArray(exec, bitwise_cast<JSValue*>(&LLINT_OP(2)), pc[3].u.operand));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_new_array_buffer)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(constructArray(exec, exec->codeBlock()->constantBuffer(pc[2].u.operand), pc[3].u.operand));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_new_regexp)
+{
+    LLINT_BEGIN();
+    RegExp* regExp = exec->codeBlock()->regexp(pc[2].u.operand);
+    if (!regExp->isValid())
+        LLINT_THROW(createSyntaxError(exec, "Invalid flag supplied to RegExp constructor."));
+    LLINT_RETURN(RegExpObject::create(globalData, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regExp));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_not)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(!LLINT_OP_C(2).jsValue().toBoolean(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_eq)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(JSValue::equal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_neq)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(!JSValue::equal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_stricteq)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(JSValue::strictEqual(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_nstricteq)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(!JSValue::strictEqual(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_less)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(jsLess<true>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_lesseq)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(jsLessEq<true>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_greater)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(jsLess<false>(exec, LLINT_OP_C(3).jsValue(), LLINT_OP_C(2).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_greatereq)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(jsLessEq<false>(exec, LLINT_OP_C(3).jsValue(), LLINT_OP_C(2).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_pre_inc)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP(1).jsValue().toNumber(exec) + 1));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_pre_dec)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP(1).jsValue().toNumber(exec) - 1));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_post_inc)
+{
+    LLINT_BEGIN();
+    double result = LLINT_OP(2).jsValue().toNumber(exec);
+    LLINT_OP(2) = jsNumber(result + 1);
+    LLINT_RETURN(jsNumber(result));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_post_dec)
+{
+    LLINT_BEGIN();
+    double result = LLINT_OP(2).jsValue().toNumber(exec);
+    LLINT_OP(2) = jsNumber(result - 1);
+    LLINT_RETURN(jsNumber(result));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_to_jsnumber)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_negate)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(-LLINT_OP_C(2).jsValue().toNumber(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_add)
+{
+    LLINT_BEGIN();
+    JSValue v1 = LLINT_OP_C(2).jsValue();
+    JSValue v2 = LLINT_OP_C(3).jsValue();
+    
+#if LLINT_SLOW_PATH_TRACING
+    dataLog("Trying to add %s", v1.description());
+    dataLog(" to %s.\n", v2.description());
+#endif
+    
+    if (v1.isString() && !v2.isObject())
+        LLINT_RETURN(jsString(exec, asString(v1), v2.toString(exec)));
+    
+    if (v1.isNumber() && v2.isNumber())
+        LLINT_RETURN(jsNumber(v1.asNumber() + v2.asNumber()));
+    
+    LLINT_RETURN(jsAddSlowCase(exec, v1, v2));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_mul)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) * LLINT_OP_C(3).jsValue().toNumber(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_sub)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) - LLINT_OP_C(3).jsValue().toNumber(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_div)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) / LLINT_OP_C(3).jsValue().toNumber(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_mod)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(fmod(LLINT_OP_C(2).jsValue().toNumber(exec), LLINT_OP_C(3).jsValue().toNumber(exec))));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_lshift)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) << (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_rshift)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) >> (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_urshift)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toUInt32(exec) >> (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_bitand)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) & LLINT_OP_C(3).jsValue().toInt32(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_bitor)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) | LLINT_OP_C(3).jsValue().toInt32(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_bitxor)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) ^ LLINT_OP_C(3).jsValue().toInt32(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_bitnot)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(~LLINT_OP_C(2).jsValue().toInt32(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_check_has_instance)
+{
+    LLINT_BEGIN();
+    JSValue baseVal = LLINT_OP_C(1).jsValue();
+#ifndef NDEBUG
+    TypeInfo typeInfo(UnspecifiedType);
+    ASSERT(!baseVal.isObject()
+           || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance());
+#endif
+    LLINT_THROW(createInvalidParamError(exec, "instanceof", baseVal));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_instanceof)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(CommonSlowPaths::opInstanceOfSlow(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_typeof)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsTypeStringForValue(exec, LLINT_OP_C(2).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_is_undefined)
+{
+    LLINT_BEGIN();
+    JSValue v = LLINT_OP_C(2).jsValue();
+    LLINT_RETURN(jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_is_boolean)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(LLINT_OP_C(2).jsValue().isBoolean()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_is_number)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(LLINT_OP_C(2).jsValue().isNumber()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_is_string)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(isJSString(LLINT_OP_C(2).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_is_object)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(jsIsObjectType(LLINT_OP_C(2).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_is_function)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(jsIsFunctionType(LLINT_OP_C(2).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_in)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(CommonSlowPaths::opIn(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_resolve)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN_PROFILED(op_resolve, CommonSlowPaths::opResolve(exec, exec->codeBlock()->identifier(pc[2].u.operand)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_resolve_skip)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN_PROFILED(
+        op_resolve_skip,
+        CommonSlowPaths::opResolveSkip(
+            exec,
+            exec->codeBlock()->identifier(pc[2].u.operand),
+            pc[3].u.operand));
+}
+
+static JSValue resolveGlobal(ExecState* exec, Instruction* pc)
+{
+    CodeBlock* codeBlock = exec->codeBlock();
+    JSGlobalObject* globalObject = codeBlock->globalObject();
+    ASSERT(globalObject->isGlobalObject());
+    int property = pc[2].u.operand;
+    Structure* structure = pc[3].u.structure.get();
+    
+    ASSERT_UNUSED(structure, structure != globalObject->structure());
+    
+    Identifier& ident = codeBlock->identifier(property);
+    PropertySlot slot(globalObject);
+    
+    if (globalObject->getPropertySlot(exec, ident, slot)) {
+        JSValue result = slot.getValue(exec, ident);
+        if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary()
+            && slot.slotBase() == globalObject) {
+            pc[3].u.structure.set(
+                exec->globalData(), codeBlock->ownerExecutable(), globalObject->structure());
+            pc[4] = slot.cachedOffset();
+        }
+        
+        return result;
+    }
+    
+    exec->globalData().exception = createUndefinedVariableError(exec, ident);
+    return JSValue();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_resolve_global)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN_PROFILED(op_resolve_global, resolveGlobal(exec, pc));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_resolve_global_dynamic)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN_PROFILED(op_resolve_global_dynamic, resolveGlobal(exec, pc));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_resolve_for_resolve_global_dynamic)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN_PROFILED(op_resolve_global_dynamic, CommonSlowPaths::opResolve(exec, exec->codeBlock()->identifier(pc[2].u.operand)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_resolve_base)
+{
+    LLINT_BEGIN();
+    Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
+    if (pc[3].u.operand) {
+        JSValue base = JSC::resolveBase(exec, ident, exec->scopeChain(), true);
+        if (!base)
+            LLINT_THROW(createErrorForInvalidGlobalAssignment(exec, ident.ustring()));
+        LLINT_RETURN(base);
+    }
+    
+    LLINT_RETURN_PROFILED(op_resolve_base, JSC::resolveBase(exec, ident, exec->scopeChain(), false));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_ensure_property_exists)
+{
+    LLINT_BEGIN();
+    JSObject* object = asObject(LLINT_OP(1).jsValue());
+    PropertySlot slot(object);
+    Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
+    if (!object->getPropertySlot(exec, ident, slot))
+        LLINT_THROW(createErrorForInvalidGlobalAssignment(exec, ident.ustring()));
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_resolve_with_base)
+{
+    LLINT_BEGIN();
+    JSValue result = CommonSlowPaths::opResolveWithBase(exec, exec->codeBlock()->identifier(pc[3].u.operand), LLINT_OP(1));
+    LLINT_CHECK_EXCEPTION();
+    LLINT_OP(2) = result;
+    // FIXME: technically should have profiling, but we don't do it because the DFG won't use it.
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_resolve_with_this)
+{
+    LLINT_BEGIN();
+    JSValue result = CommonSlowPaths::opResolveWithThis(exec, exec->codeBlock()->identifier(pc[3].u.operand), LLINT_OP(1));
+    LLINT_CHECK_EXCEPTION();
+    LLINT_OP(2) = result;
+    // FIXME: technically should have profiling, but we don't do it because the DFG won't use it.
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_get_by_id)
+{
+    LLINT_BEGIN();
+    CodeBlock* codeBlock = exec->codeBlock();
+    Identifier& ident = codeBlock->identifier(pc[3].u.operand);
+    JSValue baseValue = LLINT_OP_C(2).jsValue();
+    PropertySlot slot(baseValue);
+
+    JSValue result = baseValue.get(exec, ident, slot);
+    LLINT_CHECK_EXCEPTION();
+    LLINT_OP(1) = result;
+
+    if (baseValue.isCell()
+        && slot.isCacheable()
+        && slot.slotBase() == baseValue
+        && slot.cachedPropertyType() == PropertySlot::Value) {
+        
+        JSCell* baseCell = baseValue.asCell();
+        Structure* structure = baseCell->structure();
+        
+        if (!structure->isUncacheableDictionary()
+            && !structure->typeInfo().prohibitsPropertyCaching()) {
+            pc[4].u.structure.set(
+                globalData, codeBlock->ownerExecutable(), structure);
+            pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue);
+        }
+    }
+    
+    pc[OPCODE_LENGTH(op_get_by_id) - 1].u.profile->m_buckets[0] = JSValue::encode(result);
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_get_arguments_length)
+{
+    LLINT_BEGIN();
+    CodeBlock* codeBlock = exec->codeBlock();
+    Identifier& ident = codeBlock->identifier(pc[3].u.operand);
+    JSValue baseValue = LLINT_OP(2).jsValue();
+    PropertySlot slot(baseValue);
+    LLINT_RETURN(baseValue.get(exec, ident, slot));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_put_by_id)
+{
+    LLINT_BEGIN();
+    CodeBlock* codeBlock = exec->codeBlock();
+    Identifier& ident = codeBlock->identifier(pc[2].u.operand);
+    
+    JSValue baseValue = LLINT_OP_C(1).jsValue();
+    PutPropertySlot slot(codeBlock->isStrictMode());
+    if (pc[8].u.operand)
+        asObject(baseValue)->putDirect(globalData, ident, LLINT_OP_C(3).jsValue(), slot);
+    else
+        baseValue.put(exec, ident, LLINT_OP_C(3).jsValue(), slot);
+    LLINT_CHECK_EXCEPTION();
+    
+    if (baseValue.isCell()
+        && slot.isCacheable()) {
+        
+        JSCell* baseCell = baseValue.asCell();
+        Structure* structure = baseCell->structure();
+        
+        if (!structure->isUncacheableDictionary()
+            && !structure->typeInfo().prohibitsPropertyCaching()
+            && baseCell == slot.base()) {
+            
+            if (slot.type() == PutPropertySlot::NewProperty) {
+                if (!structure->isDictionary() && structure->previousID()->propertyStorageCapacity() == structure->propertyStorageCapacity()) {
+                    // This is needed because some of the methods we call
+                    // below may GC.
+                    pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id);
+
+                    normalizePrototypeChain(exec, baseCell);
+                    
+                    ASSERT(structure->previousID()->isObject());
+                    pc[4].u.structure.set(
+                        globalData, codeBlock->ownerExecutable(), structure->previousID());
+                    pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue);
+                    pc[6].u.structure.set(
+                        globalData, codeBlock->ownerExecutable(), structure);
+                    StructureChain* chain = structure->prototypeChain(exec);
+                    ASSERT(chain);
+                    pc[7].u.structureChain.set(
+                        globalData, codeBlock->ownerExecutable(), chain);
+                    
+                    if (pc[8].u.operand)
+                        pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id_transition_direct);
+                    else
+                        pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id_transition_normal);
+                }
+            } else {
+                pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id);
+                pc[4].u.structure.set(
+                    globalData, codeBlock->ownerExecutable(), structure);
+                pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue);
+            }
+        }
+    }
+    
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_del_by_id)
+{
+    LLINT_BEGIN();
+    CodeBlock* codeBlock = exec->codeBlock();
+    JSObject* baseObject = LLINT_OP_C(2).jsValue().toObject(exec);
+    bool couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, codeBlock->identifier(pc[3].u.operand));
+    LLINT_CHECK_EXCEPTION();
+    if (!couldDelete && codeBlock->isStrictMode())
+        LLINT_THROW(createTypeError(exec, "Unable to delete property."));
+    LLINT_RETURN(jsBoolean(couldDelete));
+}
+
+inline JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript)
+{
+    if (LIKELY(baseValue.isCell() && subscript.isString())) {
+        if (JSValue result = baseValue.asCell()->fastGetOwnProperty(exec, asString(subscript)->value(exec)))
+            return result;
+    }
+    
+    if (subscript.isUInt32()) {
+        uint32_t i = subscript.asUInt32();
+        if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
+            return asString(baseValue)->getIndex(exec, i);
+        
+        if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i))
+            return asByteArray(baseValue)->getIndex(exec, i);
+        
+        return baseValue.get(exec, i);
+    }
+    
+    Identifier property(exec, subscript.toString(exec)->value(exec));
+    return baseValue.get(exec, property);
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_get_by_val)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN_PROFILED(op_get_by_val, getByVal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_get_argument_by_val)
+{
+    LLINT_BEGIN();
+    JSValue arguments = LLINT_OP(2).jsValue();
+    if (!arguments) {
+        arguments = Arguments::create(globalData, exec);
+        LLINT_CHECK_EXCEPTION();
+        LLINT_OP(2) = arguments;
+        exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)) = arguments;
+    }
+    
+    LLINT_RETURN(getByVal(exec, arguments, LLINT_OP_C(3).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_get_by_pname)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(getByVal(exec, LLINT_OP(2).jsValue(), LLINT_OP(3).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_put_by_val)
+{
+    LLINT_BEGIN();
+    
+    JSValue baseValue = LLINT_OP_C(1).jsValue();
+    JSValue subscript = LLINT_OP_C(2).jsValue();
+    JSValue value = LLINT_OP_C(3).jsValue();
+    
+    if (LIKELY(subscript.isUInt32())) {
+        uint32_t i = subscript.asUInt32();
+        if (isJSArray(baseValue)) {
+            JSArray* jsArray = asArray(baseValue);
+            if (jsArray->canSetIndex(i))
+                jsArray->setIndex(globalData, i, value);
+            else
+                JSArray::putByIndex(jsArray, exec, i, value);
+            LLINT_END();
+        }
+        if (isJSByteArray(baseValue)
+            && asByteArray(baseValue)->canAccessIndex(i)) {
+            JSByteArray* jsByteArray = asByteArray(baseValue);
+            if (value.isInt32()) {
+                jsByteArray->setIndex(i, value.asInt32());
+                LLINT_END();
+            }
+            if (value.isNumber()) {
+                jsByteArray->setIndex(i, value.asNumber());
+                LLINT_END();
+            }
+        }
+        baseValue.put(exec, i, value);
+        LLINT_END();
+    }
+    
+    Identifier property(exec, subscript.toString(exec)->value(exec));
+    LLINT_CHECK_EXCEPTION();
+    PutPropertySlot slot(exec->codeBlock()->isStrictMode());
+    baseValue.put(exec, property, value, slot);
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_del_by_val)
+{
+    LLINT_BEGIN();
+    JSValue baseValue = LLINT_OP_C(2).jsValue();
+    JSObject* baseObject = baseValue.toObject(exec);
+    
+    JSValue subscript = LLINT_OP_C(3).jsValue();
+    
+    bool couldDelete;
+    
+    uint32_t i;
+    if (subscript.getUInt32(i))
+        couldDelete = baseObject->methodTable()->deletePropertyByIndex(baseObject, exec, i);
+    else {
+        LLINT_CHECK_EXCEPTION();
+        Identifier property(exec, subscript.toString(exec)->value(exec));
+        LLINT_CHECK_EXCEPTION();
+        couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, property);
+    }
+    
+    if (!couldDelete && exec->codeBlock()->isStrictMode())
+        LLINT_THROW(createTypeError(exec, "Unable to delete property."));
+    
+    LLINT_RETURN(jsBoolean(couldDelete));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_put_by_index)
+{
+    LLINT_BEGIN();
+    LLINT_OP_C(1).jsValue().put(exec, pc[2].u.operand, LLINT_OP_C(3).jsValue());
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_put_getter_setter)
+{
+    LLINT_BEGIN();
+    ASSERT(LLINT_OP(1).jsValue().isObject());
+    JSObject* baseObj = asObject(LLINT_OP(1).jsValue());
+    
+    GetterSetter* accessor = GetterSetter::create(exec);
+    LLINT_CHECK_EXCEPTION();
+    
+    JSValue getter = LLINT_OP(3).jsValue();
+    JSValue setter = LLINT_OP(4).jsValue();
+    ASSERT(getter.isObject() || getter.isUndefined());
+    ASSERT(setter.isObject() || setter.isUndefined());
+    ASSERT(getter.isObject() || setter.isObject());
+    
+    if (!getter.isUndefined())
+        accessor->setGetter(globalData, asObject(getter));
+    if (!setter.isUndefined())
+        accessor->setSetter(globalData, asObject(setter));
+    baseObj->putDirectAccessor(
+        globalData,
+        exec->codeBlock()->identifier(pc[2].u.operand),
+        accessor, Accessor);
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jmp_scopes)
+{
+    LLINT_BEGIN();
+    unsigned count = pc[1].u.operand;
+    ScopeChainNode* tmp = exec->scopeChain();
+    while (count--)
+        tmp = tmp->pop();
+    exec->setScopeChain(tmp);
+    pc += pc[2].u.operand;
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jtrue)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jtrue, LLINT_OP_C(1).jsValue().toBoolean(exec));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jfalse)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jfalse, !LLINT_OP_C(1).jsValue().toBoolean(exec));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jless)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jless, jsLess<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jnless)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jnless, !jsLess<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jgreater)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jgreater, jsLess<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jngreater)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jngreater, !jsLess<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jlesseq)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jlesseq, jsLessEq<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jnlesseq)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jnlesseq, !jsLessEq<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jgreatereq)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jgreatereq, jsLessEq<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jngreatereq)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jngreatereq, !jsLessEq<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_switch_imm)
+{
+    LLINT_BEGIN();
+    JSValue scrutinee = LLINT_OP_C(3).jsValue();
+    ASSERT(scrutinee.isDouble());
+    double value = scrutinee.asDouble();
+    int32_t intValue = static_cast<int32_t>(value);
+    int defaultOffset = pc[2].u.operand;
+    if (value == intValue) {
+        CodeBlock* codeBlock = exec->codeBlock();
+        pc += codeBlock->immediateSwitchJumpTable(pc[1].u.operand).offsetForValue(intValue, defaultOffset);
+    } else
+        pc += defaultOffset;
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_switch_string)
+{
+    LLINT_BEGIN();
+    JSValue scrutinee = LLINT_OP_C(3).jsValue();
+    int defaultOffset = pc[2].u.operand;
+    if (!scrutinee.isString())
+        pc += defaultOffset;
+    else {
+        CodeBlock* codeBlock = exec->codeBlock();
+        pc += codeBlock->stringSwitchJumpTable(pc[1].u.operand).offsetForValue(asString(scrutinee)->value(exec).impl(), defaultOffset);
+    }
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_new_func)
+{
+    LLINT_BEGIN();
+    CodeBlock* codeBlock = exec->codeBlock();
+    ASSERT(codeBlock->codeType() != FunctionCode
+           || !codeBlock->needsFullScopeChain()
+           || exec->uncheckedR(codeBlock->activationRegister()).jsValue());
+#if LLINT_SLOW_PATH_TRACING
+    dataLog("Creating function!\n");
+#endif
+    LLINT_RETURN(codeBlock->functionDecl(pc[2].u.operand)->make(exec, exec->scopeChain()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_new_func_exp)
+{
+    LLINT_BEGIN();
+    CodeBlock* codeBlock = exec->codeBlock();
+    FunctionExecutable* function = codeBlock->functionExpr(pc[2].u.operand);
+    JSFunction* func = function->make(exec, exec->scopeChain());
+    
+    if (!function->name().isNull()) {
+        JSStaticScopeObject* functionScopeObject = JSStaticScopeObject::create(exec, function->name(), func, ReadOnly | DontDelete);
+        func->setScope(globalData, func->scope()->push(functionScopeObject));
+    }
+    
+    LLINT_RETURN(func);
+}
+
+static SlowPathReturnType handleHostCall(ExecState* execCallee, Instruction* pc, JSValue callee, CodeSpecializationKind kind)
+{
+    ExecState* exec = execCallee->callerFrame();
+    JSGlobalData& globalData = exec->globalData();
+    
+    execCallee->setScopeChain(exec->scopeChain());
+    execCallee->setCodeBlock(0);
+    execCallee->clearReturnPC();
+
+    if (kind == CodeForCall) {
+        CallData callData;
+        CallType callType = getCallData(callee, callData);
+    
+        ASSERT(callType != CallTypeJS);
+    
+        if (callType == CallTypeHost) {
+            globalData.hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
+            
+            LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
+        }
+        
+#if LLINT_SLOW_PATH_TRACING
+        dataLog("Call callee is not a function: %s\n", callee.description());
+#endif
+
+        ASSERT(callType == CallTypeNone);
+        LLINT_CALL_THROW(exec, pc, createNotAFunctionError(exec, callee));
+    }
+
+    ASSERT(kind == CodeForConstruct);
+    
+    ConstructData constructData;
+    ConstructType constructType = getConstructData(callee, constructData);
+    
+    ASSERT(constructType != ConstructTypeJS);
+    
+    if (constructType == ConstructTypeHost) {
+        globalData.hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
+
+        LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
+    }
+    
+#if LLINT_SLOW_PATH_TRACING
+    dataLog("Constructor callee is not a function: %s\n", callee.description());
+#endif
+
+    ASSERT(constructType == ConstructTypeNone);
+    LLINT_CALL_THROW(exec, pc, createNotAConstructorError(exec, callee));
+}
+
+inline SlowPathReturnType setUpCall(ExecState* execCallee, Instruction* pc, CodeSpecializationKind kind, JSValue calleeAsValue, LLIntCallLinkInfo* callLinkInfo = 0)
+{
+#if LLINT_SLOW_PATH_TRACING
+    dataLog("Performing call with recorded PC = %p\n", execCallee->callerFrame()->currentVPC());
+#endif
+
+    JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
+    if (!calleeAsFunctionCell)
+        return handleHostCall(execCallee, pc, calleeAsValue, kind);
+    
+    JSFunction* callee = asFunction(calleeAsFunctionCell);
+    ScopeChainNode* scope = callee->scopeUnchecked();
+    JSGlobalData& globalData = *scope->globalData;
+    execCallee->setScopeChain(scope);
+    ExecutableBase* executable = callee->executable();
+    
+    MacroAssemblerCodePtr codePtr;
+    CodeBlock* codeBlock = 0;
+    if (executable->isHostFunction())
+        codePtr = executable->generatedJITCodeFor(kind).addressForCall();
+    else {
+        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
+        JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind);
+        if (error)
+            LLINT_CALL_THROW(execCallee->callerFrame(), pc, error);
+        codeBlock = &functionExecutable->generatedBytecodeFor(kind);
+        ASSERT(codeBlock);
+        if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
+            codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
+        else
+            codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
+    }
+    
+    if (callLinkInfo) {
+        if (callLinkInfo->isOnList())
+            callLinkInfo->remove();
+        ExecState* execCaller = execCallee->callerFrame();
+        callLinkInfo->callee.set(globalData, execCaller->codeBlock()->ownerExecutable(), callee);
+        callLinkInfo->lastSeenCallee.set(globalData, execCaller->codeBlock()->ownerExecutable(), callee);
+        callLinkInfo->machineCodeTarget = codePtr;
+        if (codeBlock)
+            codeBlock->linkIncomingCall(callLinkInfo);
+    }
+    
+    LLINT_CALL_RETURN(execCallee, pc, codePtr.executableAddress());
+}
+
+inline SlowPathReturnType genericCall(ExecState* exec, Instruction* pc, CodeSpecializationKind kind)
+{
+    // This needs to:
+    // - Set up a call frame.
+    // - Figure out what to call and compile it if necessary.
+    // - If possible, link the call's inline cache.
+    // - Return a tuple of machine code address to call and the new call frame.
+    
+    JSValue calleeAsValue = LLINT_OP_C(1).jsValue();
+    
+    ExecState* execCallee = exec + pc[3].u.operand;
+    
+    execCallee->setArgumentCountIncludingThis(pc[2].u.operand);
+    execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue;
+    execCallee->setCallerFrame(exec);
+    
+    ASSERT(pc[4].u.callLinkInfo);
+    return setUpCall(execCallee, pc, kind, calleeAsValue, pc[4].u.callLinkInfo);
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_call)
+{
+    LLINT_BEGIN_NO_SET_PC();
+    return genericCall(exec, pc, CodeForCall);
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_construct)
+{
+    LLINT_BEGIN_NO_SET_PC();
+    return genericCall(exec, pc, CodeForConstruct);
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_call_varargs)
+{
+    LLINT_BEGIN();
+    // This needs to:
+    // - Set up a call frame while respecting the variable arguments.
+    // - Figure out what to call and compile it if necessary.
+    // - Return a tuple of machine code address to call and the new call frame.
+    
+    JSValue calleeAsValue = LLINT_OP_C(1).jsValue();
+    
+    ExecState* execCallee = loadVarargs(
+        exec, &globalData.interpreter->registerFile(),
+        LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue(), pc[4].u.operand);
+    LLINT_CALL_CHECK_EXCEPTION(exec, pc);
+    
+    execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue;
+    execCallee->setCallerFrame(exec);
+    exec->uncheckedR(RegisterFile::ArgumentCount).tag() = bitwise_cast<int32_t>(pc + OPCODE_LENGTH(op_call_varargs));
+    
+    return setUpCall(execCallee, pc, CodeForCall, calleeAsValue);
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_call_eval)
+{
+    LLINT_BEGIN_NO_SET_PC();
+    JSValue calleeAsValue = LLINT_OP(1).jsValue();
+    
+    ExecState* execCallee = exec + pc[3].u.operand;
+    
+    execCallee->setArgumentCountIncludingThis(pc[2].u.operand);
+    execCallee->setCallerFrame(exec);
+    execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue;
+    execCallee->setScopeChain(exec->scopeChain());
+    execCallee->setReturnPC(bitwise_cast<Instruction*>(&llint_generic_return_point));
+    execCallee->setCodeBlock(0);
+    exec->uncheckedR(RegisterFile::ArgumentCount).tag() = bitwise_cast<int32_t>(pc + OPCODE_LENGTH(op_call_eval));
+    
+    if (!isHostFunction(calleeAsValue, globalFuncEval))
+        return setUpCall(execCallee, pc, CodeForCall, calleeAsValue);
+    
+    globalData.hostCallReturnValue = eval(execCallee);
+    LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_tear_off_activation)
+{
+    LLINT_BEGIN();
+    ASSERT(exec->codeBlock()->needsFullScopeChain());
+    JSValue activationValue = LLINT_OP(1).jsValue();
+    if (!activationValue) {
+        if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)).jsValue()) {
+            if (!exec->codeBlock()->isStrictMode())
+                asArguments(v)->tearOff(exec);
+        }
+        LLINT_END();
+    }
+    JSActivation* activation = asActivation(activationValue);
+    activation->tearOff(globalData);
+    if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)).jsValue())
+        asArguments(v)->didTearOffActivation(globalData, activation);
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_tear_off_arguments)
+{
+    LLINT_BEGIN();
+    ASSERT(exec->codeBlock()->usesArguments() && !exec->codeBlock()->needsFullScopeChain());
+    asArguments(exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)).jsValue())->tearOff(exec);
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_strcat)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsString(exec, &LLINT_OP(2), pc[3].u.operand));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_to_primitive)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(LLINT_OP_C(2).jsValue().toPrimitive(exec));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_get_pnames)
+{
+    LLINT_BEGIN();
+    JSValue v = LLINT_OP(2).jsValue();
+    if (v.isUndefinedOrNull()) {
+        pc += pc[5].u.operand;
+        LLINT_END();
+    }
+    
+    JSObject* o = v.toObject(exec);
+    Structure* structure = o->structure();
+    JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
+    if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(exec))
+        jsPropertyNameIterator = JSPropertyNameIterator::create(exec, o);
+    
+    LLINT_OP(1) = JSValue(jsPropertyNameIterator);
+    LLINT_OP(2) = JSValue(o);
+    LLINT_OP(3) = Register::withInt(0);
+    LLINT_OP(4) = Register::withInt(jsPropertyNameIterator->size());
+    
+    pc += OPCODE_LENGTH(op_get_pnames);
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_next_pname)
+{
+    LLINT_BEGIN();
+    JSObject* base = asObject(LLINT_OP(2).jsValue());
+    JSString* property = asString(LLINT_OP(1).jsValue());
+    if (base->hasProperty(exec, Identifier(exec, property->value(exec)))) {
+        // Go to target.
+        pc += pc[6].u.operand;
+    } // Else, don't change the PC, so the interpreter will reloop.
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_push_scope)
+{
+    LLINT_BEGIN();
+    JSValue v = LLINT_OP(1).jsValue();
+    JSObject* o = v.toObject(exec);
+    LLINT_CHECK_EXCEPTION();
+    
+    LLINT_OP(1) = o;
+    exec->setScopeChain(exec->scopeChain()->push(o));
+    
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_pop_scope)
+{
+    LLINT_BEGIN();
+    exec->setScopeChain(exec->scopeChain()->pop());
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_push_new_scope)
+{
+    LLINT_BEGIN();
+    CodeBlock* codeBlock = exec->codeBlock();
+    JSObject* scope = JSStaticScopeObject::create(exec, codeBlock->identifier(pc[2].u.operand), LLINT_OP(3).jsValue(), DontDelete);
+    exec->setScopeChain(exec->scopeChain()->push(scope));
+    LLINT_RETURN(scope);
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_throw)
+{
+    LLINT_BEGIN();
+    LLINT_THROW(LLINT_OP_C(1).jsValue());
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_throw_reference_error)
+{
+    LLINT_BEGIN();
+    LLINT_THROW(createReferenceError(exec, LLINT_OP_C(1).jsValue().toString(exec)->value(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_debug)
+{
+    LLINT_BEGIN();
+    int debugHookID = pc[1].u.operand;
+    int firstLine = pc[2].u.operand;
+    int lastLine = pc[3].u.operand;
+    
+    globalData.interpreter->debug(exec, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
+    
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_profile_will_call)
+{
+    LLINT_BEGIN();
+    (*Profiler::enabledProfilerReference())->willExecute(exec, LLINT_OP(1).jsValue());
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_profile_did_call)
+{
+    LLINT_BEGIN();
+    (*Profiler::enabledProfilerReference())->didExecute(exec, LLINT_OP(1).jsValue());
+    LLINT_END();
+}
+
+} } // namespace JSC::LLInt
+
+#endif // ENABLE(LLINT)
diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.h b/Source/JavaScriptCore/llint/LLIntSlowPaths.h
new file mode 100644 (file)
index 0000000..fe684d3
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2011 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 LLIntSlowPaths_h
+#define LLIntSlowPaths_h
+
+#include <wtf/Platform.h>
+#include <wtf/StdLibExtras.h>
+
+#if ENABLE(LLINT)
+
+namespace JSC {
+
+class ExecState;
+struct Instruction;
+
+namespace LLInt {
+
+typedef int64_t SlowPathReturnType;
+
+extern "C" SlowPathReturnType llint_trace_operand(ExecState*, Instruction*, int fromWhere, int operand);
+extern "C" SlowPathReturnType llint_trace_value(ExecState*, Instruction*, int fromWhere, int operand);
+
+#define LLINT_SLOW_PATH_DECL(name) \
+    extern "C" SlowPathReturnType llint_##name(ExecState* exec, Instruction* pc)
+
+LLINT_SLOW_PATH_DECL(trace_prologue);
+LLINT_SLOW_PATH_DECL(trace_prologue_function_for_call);
+LLINT_SLOW_PATH_DECL(trace_prologue_function_for_construct);
+LLINT_SLOW_PATH_DECL(trace_arityCheck_for_call);
+LLINT_SLOW_PATH_DECL(trace_arityCheck_for_construct);
+LLINT_SLOW_PATH_DECL(trace);
+LLINT_SLOW_PATH_DECL(special_trace);
+LLINT_SLOW_PATH_DECL(entry_osr);
+LLINT_SLOW_PATH_DECL(entry_osr_function_for_call);
+LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct);
+LLINT_SLOW_PATH_DECL(entry_osr_function_for_call_arityCheck);
+LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct_arityCheck);
+LLINT_SLOW_PATH_DECL(loop_osr);
+LLINT_SLOW_PATH_DECL(replace);
+LLINT_SLOW_PATH_DECL(register_file_check);
+LLINT_SLOW_PATH_DECL(slow_path_call_arityCheck);
+LLINT_SLOW_PATH_DECL(slow_path_construct_arityCheck);
+LLINT_SLOW_PATH_DECL(slow_path_create_activation);
+LLINT_SLOW_PATH_DECL(slow_path_create_arguments);
+LLINT_SLOW_PATH_DECL(slow_path_create_this);
+LLINT_SLOW_PATH_DECL(slow_path_convert_this);
+LLINT_SLOW_PATH_DECL(slow_path_new_object);
+LLINT_SLOW_PATH_DECL(slow_path_new_array);
+LLINT_SLOW_PATH_DECL(slow_path_new_array_buffer);
+LLINT_SLOW_PATH_DECL(slow_path_new_regexp);
+LLINT_SLOW_PATH_DECL(slow_path_not);
+LLINT_SLOW_PATH_DECL(slow_path_eq);
+LLINT_SLOW_PATH_DECL(slow_path_neq);
+LLINT_SLOW_PATH_DECL(slow_path_stricteq);
+LLINT_SLOW_PATH_DECL(slow_path_nstricteq);
+LLINT_SLOW_PATH_DECL(slow_path_less);
+LLINT_SLOW_PATH_DECL(slow_path_lesseq);
+LLINT_SLOW_PATH_DECL(slow_path_greater);
+LLINT_SLOW_PATH_DECL(slow_path_greatereq);
+LLINT_SLOW_PATH_DECL(slow_path_pre_inc);
+LLINT_SLOW_PATH_DECL(slow_path_pre_dec);
+LLINT_SLOW_PATH_DECL(slow_path_post_inc);
+LLINT_SLOW_PATH_DECL(slow_path_post_dec);
+LLINT_SLOW_PATH_DECL(slow_path_to_jsnumber);
+LLINT_SLOW_PATH_DECL(slow_path_negate);
+LLINT_SLOW_PATH_DECL(slow_path_add);
+LLINT_SLOW_PATH_DECL(slow_path_mul);
+LLINT_SLOW_PATH_DECL(slow_path_sub);
+LLINT_SLOW_PATH_DECL(slow_path_div);
+LLINT_SLOW_PATH_DECL(slow_path_mod);
+LLINT_SLOW_PATH_DECL(slow_path_lshift);
+LLINT_SLOW_PATH_DECL(slow_path_rshift);
+LLINT_SLOW_PATH_DECL(slow_path_urshift);
+LLINT_SLOW_PATH_DECL(slow_path_bitand);
+LLINT_SLOW_PATH_DECL(slow_path_bitor);
+LLINT_SLOW_PATH_DECL(slow_path_bitxor);
+LLINT_SLOW_PATH_DECL(slow_path_bitnot);
+LLINT_SLOW_PATH_DECL(slow_path_check_has_instance);
+LLINT_SLOW_PATH_DECL(slow_path_instanceof);
+LLINT_SLOW_PATH_DECL(slow_path_typeof);
+LLINT_SLOW_PATH_DECL(slow_path_is_undefined);
+LLINT_SLOW_PATH_DECL(slow_path_is_boolean);
+LLINT_SLOW_PATH_DECL(slow_path_is_number);
+LLINT_SLOW_PATH_DECL(slow_path_is_string);
+LLINT_SLOW_PATH_DECL(slow_path_is_object);
+LLINT_SLOW_PATH_DECL(slow_path_is_function);
+LLINT_SLOW_PATH_DECL(slow_path_in);
+LLINT_SLOW_PATH_DECL(slow_path_resolve);
+LLINT_SLOW_PATH_DECL(slow_path_resolve_skip);
+LLINT_SLOW_PATH_DECL(slow_path_resolve_global);
+LLINT_SLOW_PATH_DECL(slow_path_resolve_global_dynamic);
+LLINT_SLOW_PATH_DECL(slow_path_resolve_for_resolve_global_dynamic);
+LLINT_SLOW_PATH_DECL(slow_path_resolve_base);
+LLINT_SLOW_PATH_DECL(slow_path_ensure_property_exists);
+LLINT_SLOW_PATH_DECL(slow_path_resolve_with_base);
+LLINT_SLOW_PATH_DECL(slow_path_resolve_with_this);
+LLINT_SLOW_PATH_DECL(slow_path_get_by_id);
+LLINT_SLOW_PATH_DECL(slow_path_get_arguments_length);
+LLINT_SLOW_PATH_DECL(slow_path_put_by_id);
+LLINT_SLOW_PATH_DECL(slow_path_del_by_id);
+LLINT_SLOW_PATH_DECL(slow_path_get_by_val);
+LLINT_SLOW_PATH_DECL(slow_path_get_argument_by_val);
+LLINT_SLOW_PATH_DECL(slow_path_get_by_pname);
+LLINT_SLOW_PATH_DECL(slow_path_put_by_val);
+LLINT_SLOW_PATH_DECL(slow_path_del_by_val);
+LLINT_SLOW_PATH_DECL(slow_path_put_by_index);
+LLINT_SLOW_PATH_DECL(slow_path_put_getter_setter);
+LLINT_SLOW_PATH_DECL(slow_path_jmp_scopes);
+LLINT_SLOW_PATH_DECL(slow_path_jtrue);
+LLINT_SLOW_PATH_DECL(slow_path_jfalse);
+LLINT_SLOW_PATH_DECL(slow_path_jless);
+LLINT_SLOW_PATH_DECL(slow_path_jnless);
+LLINT_SLOW_PATH_DECL(slow_path_jgreater);
+LLINT_SLOW_PATH_DECL(slow_path_jngreater);
+LLINT_SLOW_PATH_DECL(slow_path_jlesseq);
+LLINT_SLOW_PATH_DECL(slow_path_jnlesseq);
+LLINT_SLOW_PATH_DECL(slow_path_jgreatereq);
+LLINT_SLOW_PATH_DECL(slow_path_jngreatereq);
+LLINT_SLOW_PATH_DECL(slow_path_switch_imm);
+LLINT_SLOW_PATH_DECL(slow_path_switch_char);
+LLINT_SLOW_PATH_DECL(slow_path_switch_string);
+LLINT_SLOW_PATH_DECL(slow_path_new_func);
+LLINT_SLOW_PATH_DECL(slow_path_new_func_exp);
+LLINT_SLOW_PATH_DECL(slow_path_call);
+LLINT_SLOW_PATH_DECL(slow_path_construct);
+LLINT_SLOW_PATH_DECL(slow_path_call_varargs);
+LLINT_SLOW_PATH_DECL(slow_path_call_eval);
+LLINT_SLOW_PATH_DECL(slow_path_tear_off_activation);
+LLINT_SLOW_PATH_DECL(slow_path_tear_off_arguments);
+LLINT_SLOW_PATH_DECL(slow_path_strcat);
+LLINT_SLOW_PATH_DECL(slow_path_to_primitive);
+LLINT_SLOW_PATH_DECL(slow_path_get_pnames);
+LLINT_SLOW_PATH_DECL(slow_path_next_pname);
+LLINT_SLOW_PATH_DECL(slow_path_push_scope);
+LLINT_SLOW_PATH_DECL(slow_path_pop_scope);
+LLINT_SLOW_PATH_DECL(slow_path_push_new_scope);
+LLINT_SLOW_PATH_DECL(slow_path_throw);
+LLINT_SLOW_PATH_DECL(slow_path_throw_reference_error);
+LLINT_SLOW_PATH_DECL(slow_path_debug);
+LLINT_SLOW_PATH_DECL(slow_path_profile_will_call);
+LLINT_SLOW_PATH_DECL(slow_path_profile_did_call);
+
+} } // namespace JSC::LLInt
+
+#endif // ENABLE(LLINT)
+
+#endif // LLIntSlowPaths_h
+
diff --git a/Source/JavaScriptCore/llint/LLIntThunks.cpp b/Source/JavaScriptCore/llint/LLIntThunks.cpp
new file mode 100644 (file)
index 0000000..ddb0c46
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2012 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 "LLIntThunks.h"
+
+#if ENABLE(LLINT)
+
+#include "JSInterfaceJIT.h"
+#include "LinkBuffer.h"
+#include "LowLevelInterpreter.h"
+
+namespace JSC { namespace LLInt {
+
+static MacroAssemblerCodeRef generateThunkWithJumpTo(JSGlobalData* globalData, void (*target)())
+{
+    JSInterfaceJIT jit;
+    
+    // FIXME: there's probably a better way to do it on X86, but I'm not sure I care.
+    jit.move(JSInterfaceJIT::TrustedImmPtr(bitwise_cast<void*>(target)), JSInterfaceJIT::regT0);
+    jit.jump(JSInterfaceJIT::regT0);
+    
+    LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
+    return patchBuffer.finalizeCode();
+}
+
+MacroAssemblerCodeRef functionForCallEntryThunkGenerator(JSGlobalData* globalData)
+{
+    return generateThunkWithJumpTo(globalData, llint_function_for_call_prologue);
+}
+
+MacroAssemblerCodeRef functionForConstructEntryThunkGenerator(JSGlobalData* globalData)
+{
+    return generateThunkWithJumpTo(globalData, llint_function_for_construct_prologue);
+}
+
+MacroAssemblerCodeRef functionForCallArityCheckThunkGenerator(JSGlobalData* globalData)
+{
+    return generateThunkWithJumpTo(globalData, llint_function_for_call_arity_check);
+}
+
+MacroAssemblerCodeRef functionForConstructArityCheckThunkGenerator(JSGlobalData* globalData)
+{
+    return generateThunkWithJumpTo(globalData, llint_function_for_construct_arity_check);
+}
+
+MacroAssemblerCodeRef evalEntryThunkGenerator(JSGlobalData* globalData)
+{
+    return generateThunkWithJumpTo(globalData, llint_eval_prologue);
+}
+
+MacroAssemblerCodeRef programEntryThunkGenerator(JSGlobalData* globalData)
+{
+    return generateThunkWithJumpTo(globalData, llint_program_prologue);
+}
+
+} } // namespace JSC::LLInt
+
+#endif // ENABLE(LLINT)
diff --git a/Source/JavaScriptCore/llint/LLIntThunks.h b/Source/JavaScriptCore/llint/LLIntThunks.h
new file mode 100644 (file)
index 0000000..ee119e0
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 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 LLIntThunks_h
+#define LLIntThunks_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(LLINT)
+
+#include "MacroAssemblerCodeRef.h"
+
+namespace JSC {
+
+class JSGlobalData;
+
+namespace LLInt {
+
+MacroAssemblerCodeRef functionForCallEntryThunkGenerator(JSGlobalData*);
+MacroAssemblerCodeRef functionForConstructEntryThunkGenerator(JSGlobalData*);
+MacroAssemblerCodeRef functionForCallArityCheckThunkGenerator(JSGlobalData*);
+MacroAssemblerCodeRef functionForConstructArityCheckThunkGenerator(JSGlobalData*);
+MacroAssemblerCodeRef evalEntryThunkGenerator(JSGlobalData*);
+MacroAssemblerCodeRef programEntryThunkGenerator(JSGlobalData*);
+
+} } // namespace JSC::LLInt
+
+#endif // ENABLE(LLINT)
+
+#endif // LLIntThunks_h
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
new file mode 100644 (file)
index 0000000..a9f83f6
--- /dev/null
@@ -0,0 +1,2390 @@
+# Copyright (C) 2011, 2012 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+
+
+# Crash course on the language that this is written in (which I just call
+# "assembly" even though it's more than that):
+#
+# - Mostly gas-style operand ordering. The last operand tends to be the
+#   destination. So "a := b" is written as "mov b, a". But unlike gas,
+#   comparisons are in-order, so "if (a < b)" is written as
+#   "bilt a, b, ...".
+#
+# - "b" = byte, "h" = 16-bit word, "i" = 32-bit word, "p" = pointer.
+#   Currently this is just 32-bit so "i" and "p" are interchangeable
+#   except when an op supports one but not the other.
+#
+# - In general, valid operands for macro invocations and instructions are
+#   registers (eg "t0"), addresses (eg "4[t0]"), base-index addresses
+#   (eg "7[t0, t1, 2]"), absolute addresses (eg "0xa0000000[]"), or labels
+#   (eg "_foo" or ".foo"). Macro invocations can also take anonymous
+#   macros as operands. Instructions cannot take anonymous macros.
+#
+# - Labels must have names that begin with either "_" or ".".  A "." label
+#   is local and gets renamed before code gen to minimize namespace
+#   pollution. A "_" label is an extern symbol (i.e. ".globl"). The "_"
+#   may or may not be removed during code gen depending on whether the asm
+#   conventions for C name mangling on the target platform mandate a "_"
+#   prefix.
+#
+# - A "macro" is a lambda expression, which may be either anonymous or
+#   named. But this has caveats. "macro" can take zero or more arguments,
+#   which may be macros or any valid operands, but it can only return
+#   code. But you can do Turing-complete things via continuation passing
+#   style: "macro foo (a, b) b(a) end foo(foo, foo)". Actually, don't do
+#   that, since you'll just crash the assembler.
+#
+# - An "if" is a conditional on settings. Any identifier supplied in the
+#   predicate of an "if" is assumed to be a #define that is available
+#   during code gen. So you can't use "if" for computation in a macro, but
+#   you can use it to select different pieces of code for different
+#   platforms.
+#
+# - Arguments to macros follow lexical scoping rather than dynamic scoping.
+#   Const's also follow lexical scoping and may override (hide) arguments
+#   or other consts. All variables (arguments and constants) can be bound
+#   to operands. Additionally, arguments (but not constants) can be bound
+#   to macros.
+
+
+# Below we have a bunch of constant declarations. Each constant must have
+# a corresponding ASSERT() in LLIntData.cpp.
+
+# These declarations must match interpreter/RegisterFile.h.
+const CallFrameHeaderSize = 48
+const ArgumentCount = -48
+const CallerFrame = -40
+const Callee = -32
+const ScopeChain = -24
+const ReturnPC = -16
+const CodeBlock = -8
+
+const ThisArgumentOffset = -CallFrameHeaderSize - 8
+
+# Declare some aliases for the registers we will use.
+const PC = t4
+
+# Offsets needed for reasoning about value representation.
+if BIG_ENDIAN
+    const TagOffset = 0
+    const PayloadOffset = 4
+else
+    const TagOffset = 4
+    const PayloadOffset = 0
+end
+
+# Value representation constants.
+const Int32Tag = -1
+const BooleanTag = -2
+const NullTag = -3
+const UndefinedTag = -4
+const CellTag = -5
+const EmptyValueTag = -6
+const DeletedValueTag = -7
+const LowestTag = DeletedValueTag
+
+# Type constants.
+const StringType = 5
+const ObjectType = 13
+
+# Type flags constants.
+const MasqueradesAsUndefined = 1
+const ImplementsHasInstance = 2
+const ImplementsDefaultHasInstance = 8
+
+# Heap allocation constants.
+const JSFinalObjectSizeClassIndex = 3
+
+# Bytecode operand constants.
+const FirstConstantRegisterIndex = 0x40000000
+
+# Code type constants.
+const GlobalCode = 0
+const EvalCode = 1
+const FunctionCode = 2
+
+# The interpreter steals the tag word of the argument count.
+const LLIntReturnPC = ArgumentCount + TagOffset
+
+# This must match wtf/Vector.h.
+const VectorSizeOffset = 0
+const VectorBufferOffset = 4
+
+# String flags.
+const HashFlags8BitBuffer = 64
+
+# Utilities
+macro crash()
+    storei 0, 0xbbadbeef[]
+    move 0, t0
+    call t0
+end
+
+macro assert(assertion)
+    if ASSERT_ENABLED
+        assertion(.ok)
+        crash()
+    .ok:
+    end
+end
+
+macro preserveReturnAddressAfterCall(destinationRegister)
+    if ARMv7
+        move lr, destinationRegister
+    elsif X86
+        pop destinationRegister
+    else
+        error
+    end
+end
+
+macro restoreReturnAddressBeforeReturn(sourceRegister)
+    if ARMv7
+        move sourceRegister, lr
+    elsif X86
+        push sourceRegister
+    else
+        error
+    end
+end
+
+macro dispatch(advance)
+    addp advance * 4, PC
+    jmp [PC]
+end
+
+macro dispatchBranchWithOffset(pcOffset)
+    lshifti 2, pcOffset
+    addp pcOffset, PC
+    jmp [PC]
+end
+
+macro dispatchBranch(pcOffset)
+    loadi pcOffset, t0
+    dispatchBranchWithOffset(t0)
+end
+
+macro dispatchAfterCall()
+    loadi ArgumentCount + TagOffset[cfr], PC
+    jmp [PC]
+end
+
+macro cCall2(function, arg1, arg2)
+    if ARMv7
+        move arg1, t0
+        move arg2, t1
+    elsif X86
+        poke arg1, 0
+        poke arg2, 1
+    else
+        error
+    end
+    call function
+end
+
+# This barely works. arg3 and arg4 should probably be immediates.
+macro cCall4(function, arg1, arg2, arg3, arg4)
+    if ARMv7
+        move arg1, t0
+        move arg2, t1
+        move arg3, t2
+        move arg4, t3
+    elsif X86
+        poke arg1, 0
+        poke arg2, 1
+        poke arg3, 2
+        poke arg4, 3
+    else
+        error
+    end
+    call function
+end
+
+macro callSlowPath(slow_path)
+    cCall2(slow_path, cfr, PC)
+    move t0, PC
+    move t1, cfr
+end
+
+# Debugging operation if you'd like to print an operand in the instruction stream. fromWhere
+# should be an immediate integer - any integer you like; use it to identify the place you're
+# debugging from. operand should likewise be an immediate, and should identify the operand
+# in the instruction stream you'd like to print out.
+macro traceOperand(fromWhere, operand)
+    cCall4(_llint_trace_operand, cfr, PC, fromWhere, operand)
+    move t0, PC
+    move t1, cfr
+end
+
+# Debugging operation if you'd like to print the value of an operand in the instruction
+# stream. Same as traceOperand(), but assumes that the operand is a register, and prints its
+# value.
+macro traceValue(fromWhere, operand)
+    cCall4(_llint_trace_value, cfr, PC, fromWhere, operand)
+    move t0, PC
+    move t1, cfr
+end
+
+macro traceExecution()
+    if EXECUTION_TRACING
+        callSlowPath(_llint_trace)
+    end
+end
+
+# Call a slow_path for call opcodes.
+macro callCallSlowPath(advance, slow_path, action)
+    addp advance * 4, PC, t0
+    storep t0, ArgumentCount + TagOffset[cfr]
+    cCall2(slow_path, cfr, PC)
+    move t1, cfr
+    action(t0)
+end
+
+macro slowPathForCall(advance, slow_path)
+    callCallSlowPath(
+        advance,
+        slow_path,
+        macro (callee)
+            call callee
+            dispatchAfterCall()
+        end)
+end
+
+macro checkSwitchToJIT(increment, action)
+    if JIT_ENABLED
+        loadp CodeBlock[cfr], t0
+        baddis increment, CodeBlock::m_llintExecuteCounter[t0], .continue
+        action()
+    .continue:
+    end
+end
+
+macro checkSwitchToJITForLoop()
+    checkSwitchToJIT(
+        1,
+        macro ()
+            storei PC, ArgumentCount + TagOffset[cfr]
+            cCall2(_llint_loop_osr, cfr, PC)
+            move t1, cfr
+            btpz t0, .recover
+            jmp t0
+        .recover:
+            loadi ArgumentCount + TagOffset[cfr], PC
+        end)
+end
+
+macro checkSwitchToJITForEpilogue()
+    checkSwitchToJIT(
+        10,
+        macro ()
+            callSlowPath(_llint_replace)
+        end)
+end
+
+macro assertNotConstant(index)
+    assert(macro (ok) bilt index, FirstConstantRegisterIndex, ok end)
+end
+
+# Index, tag, and payload must be different registers. Index is not
+# changed.
+macro loadConstantOrVariable(index, tag, payload)
+    bigteq index, FirstConstantRegisterIndex, .constant
+    loadi TagOffset[cfr, index, 8], tag
+    loadi PayloadOffset[cfr, index, 8], payload
+    jmp .done
+.constant:
+    loadp CodeBlock[cfr], payload
+    loadp CodeBlock::m_constantRegisters + VectorBufferOffset[payload], payload
+    # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex,
+    # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3.
+    loadp TagOffset[payload, index, 8], tag
+    loadp PayloadOffset[payload, index, 8], payload
+.done:
+end
+
+# Index and payload may be the same register. Index may be clobbered.
+macro loadConstantOrVariable2Reg(index, tag, payload)
+    bigteq index, FirstConstantRegisterIndex, .constant
+    loadi TagOffset[cfr, index, 8], tag
+    loadi PayloadOffset[cfr, index, 8], payload
+    jmp .done
+.constant:
+    loadp CodeBlock[cfr], tag
+    loadp CodeBlock::m_constantRegisters + VectorBufferOffset[tag], tag
+    # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex,
+    # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3.
+    lshifti 3, index
+    addp index, tag
+    loadp PayloadOffset[tag], payload
+    loadp TagOffset[tag], tag
+.done:
+end
+
+macro loadConstantOrVariablePayloadTagCustom(index, tagCheck, payload)
+    bigteq index, FirstConstantRegisterIndex, .constant
+    tagCheck(TagOffset[cfr, index, 8])
+    loadi PayloadOffset[cfr, index, 8], payload
+    jmp .done
+.constant:
+    loadp CodeBlock[cfr], payload
+    loadp CodeBlock::m_constantRegisters + VectorBufferOffset[payload], payload
+    # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex,
+    # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3.
+    tagCheck(TagOffset[payload, index, 8])
+    loadp PayloadOffset[payload, index, 8], payload
+.done:
+end
+
+# Index and payload must be different registers. Index is not mutated. Use
+# this if you know what the tag of the variable should be. Doing the tag
+# test as part of loading the variable reduces register use, but may not
+# be faster than doing loadConstantOrVariable followed by a branch on the
+# tag.
+macro loadConstantOrVariablePayload(index, expectedTag, payload, slow)
+    loadConstantOrVariablePayloadTagCustom(
+        index,
+        macro (actualTag) bineq actualTag, expectedTag, slow end,
+        payload)
+end
+
+macro loadConstantOrVariablePayloadUnchecked(index, payload)
+    loadConstantOrVariablePayloadTagCustom(
+        index,
+        macro (actualTag) end,
+        payload)
+end
+
+macro writeBarrier(tag, payload)
+    # Nothing to do, since we don't have a generational or incremental collector.
+end
+
+macro valueProfile(tag, payload, profile)
+    if JIT_ENABLED
+        storei tag, ValueProfile::m_buckets + TagOffset[profile]
+        storei payload, ValueProfile::m_buckets + PayloadOffset[profile]
+    end
+end
+
+
+# Indicate the beginning of LLInt.
+_llint_begin:
+    crash()
+
+
+# Entrypoints into the interpreter
+
+macro functionForCallCodeBlockGetter(targetRegister)
+    loadp Callee[cfr], targetRegister
+    loadp JSFunction::m_executable[targetRegister], targetRegister
+    loadp FunctionExecutable::m_codeBlockForCall[targetRegister], targetRegister
+end
+
+macro functionForConstructCodeBlockGetter(targetRegister)
+    loadp Callee[cfr], targetRegister
+    loadp JSFunction::m_executable[targetRegister], targetRegister
+    loadp FunctionExecutable::m_codeBlockForConstruct[targetRegister], targetRegister
+end
+
+macro notFunctionCodeBlockGetter(targetRegister)
+    loadp CodeBlock[cfr], targetRegister
+end
+
+macro functionCodeBlockSetter(sourceRegister)
+    storep sourceRegister, CodeBlock[cfr]
+end
+
+macro notFunctionCodeBlockSetter(sourceRegister)
+    # Nothing to do!
+end
+
+# Do the bare minimum required to execute code. Sets up the PC, leave the CodeBlock*
+# in t1. May also trigger prologue entry OSR.
+macro prologue(codeBlockGetter, codeBlockSetter, osrSlowPath, traceSlowPath)
+    preserveReturnAddressAfterCall(t2)
+    
+    # Set up the call frame and check if we should OSR.
+    storep t2, ReturnPC[cfr]
+    if EXECUTION_TRACING
+        callSlowPath(traceSlowPath)
+    end
+    codeBlockGetter(t1)
+    if JIT_ENABLED
+        baddis 5, CodeBlock::m_llintExecuteCounter[t1], .continue
+        cCall2(osrSlowPath, cfr, PC)
+        move t1, cfr
+        btpz t0, .recover
+        loadp ReturnPC[cfr], t2
+        restoreReturnAddressBeforeReturn(t2)
+        jmp t0
+    .recover:
+        codeBlockGetter(t1)
+    .continue:
+    end
+    codeBlockSetter(t1)
+    
+    # Set up the PC.
+    loadp CodeBlock::m_instructions[t1], t0
+    loadp CodeBlock::Instructions::m_instructions + VectorBufferOffset[t0], PC
+end
+
+# Expects that CodeBlock is in t1, which is what prologue() leaves behind.
+# Must call dispatch(0) after calling this.
+macro functionInitialization(profileArgSkip)
+    if JIT_ENABLED
+        # Profile the arguments. Unfortunately, we have no choice but to do this. This
+        # code is pretty horrendous because of the difference in ordering between
+        # arguments and value profiles, the desire to have a simple loop-down-to-zero
+        # loop, and the desire to use only three registers so as to preserve the PC and
+        # the code block. It is likely that this code should be rewritten in a more
+        # optimal way for architectures that have more than five registers available
+        # for arbitrary use in the interpreter.
+        loadi CodeBlock::m_numParameters[t1], t0
+        addi -profileArgSkip, t0 # Use addi because that's what has the peephole
+        assert(macro (ok) bigteq t0, 0, ok end)
+        btiz t0, .argumentProfileDone
+        loadp CodeBlock::m_argumentValueProfiles + VectorBufferOffset[t1], t3
+        muli sizeof ValueProfile, t0, t2 # Aaaaahhhh! Need strength reduction!
+        negi t0
+        lshifti 3, t0
+        addp t2, t3
+    .argumentProfileLoop:
+        loadi ThisArgumentOffset + TagOffset + 8 - profileArgSkip * 8[cfr, t0], t2
+        subp sizeof ValueProfile, t3
+        storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + TagOffset[t3]
+        loadi ThisArgumentOffset + PayloadOffset + 8 - profileArgSkip * 8[cfr, t0], t2
+        storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + PayloadOffset[t3]
+        baddinz 8, t0, .argumentProfileLoop
+    .argumentProfileDone:
+    end
+        
+    # Check stack height.
+    loadi CodeBlock::m_numCalleeRegisters[t1], t0
+    loadp CodeBlock::m_globalData[t1], t2
+    loadp JSGlobalData::interpreter[t2], t2   # FIXME: Can get to the RegisterFile from the JITStackFrame
+    lshifti 3, t0
+    addp t0, cfr, t0
+    bpaeq Interpreter::m_registerFile + RegisterFile::m_end[t2], t0, .stackHeightOK
+
+    # Stack height check failed - need to call a slow_path.
+    callSlowPath(_llint_register_file_check)
+.stackHeightOK:
+end
+
+# Expects that CodeBlock is in t1, which is what prologue() leaves behind.
+macro functionArityCheck(doneLabel, slow_path)
+    loadi PayloadOffset + ArgumentCount[cfr], t0
+    biaeq t0, CodeBlock::m_numParameters[t1], doneLabel
+    cCall2(slow_path, cfr, PC)   # This slow_path has a simple protocol: t0 = 0 => no error, t0 != 0 => error
+    move t1, cfr
+    btiz t0, .continue
+    loadp JITStackFrame::globalData[sp], t1
+    loadp JSGlobalData::callFrameForThrow[t1], t0
+    jmp JSGlobalData::targetMachinePCForThrow[t1]
+.continue:
+    # Reload CodeBlock and PC, since the slow_path clobbered it.
+    loadp CodeBlock[cfr], t1
+    loadp CodeBlock::m_instructions[t1], t0
+    loadp CodeBlock::Instructions::m_instructions + VectorBufferOffset[t0], PC
+    jmp doneLabel
+end
+
+_llint_program_prologue:
+    prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
+    dispatch(0)
+
+
+_llint_eval_prologue:
+    prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
+    dispatch(0)
+
+
+_llint_function_for_call_prologue:
+    prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call, _llint_trace_prologue_function_for_call)
+.functionForCallBegin:
+    functionInitialization(0)
+    dispatch(0)
+    
+
+_llint_function_for_construct_prologue:
+    prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct, _llint_trace_prologue_function_for_construct)
+.functionForConstructBegin:
+    functionInitialization(1)
+    dispatch(0)
+    
+
+_llint_function_for_call_arity_check:
+    prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call_arityCheck, _llint_trace_arityCheck_for_call)
+    functionArityCheck(.functionForCallBegin, _llint_slow_path_call_arityCheck)
+
+
+_llint_function_for_construct_arity_check:
+    prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct_arityCheck, _llint_trace_arityCheck_for_construct)
+    functionArityCheck(.functionForConstructBegin, _llint_slow_path_construct_arityCheck)
+
+# Instruction implementations
+
+_llint_op_enter:
+    traceExecution()
+    loadp CodeBlock[cfr], t2
+    loadi CodeBlock::m_numVars[t2], t2
+    btiz t2, .opEnterDone
+    move UndefinedTag, t0
+    move 0, t1
+.opEnterLoop:
+    subi 1, t2
+    storei t0, TagOffset[cfr, t2, 8]
+    storei t1, PayloadOffset[cfr, t2, 8]
+    btinz t2, .opEnterLoop
+.opEnterDone:
+    dispatch(1)
+
+
+_llint_op_create_activation:
+    traceExecution()
+    loadi 4[PC], t0
+    bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opCreateActivationDone
+    callSlowPath(_llint_slow_path_create_activation)
+.opCreateActivationDone:
+    dispatch(2)
+
+
+_llint_op_init_lazy_reg:
+    traceExecution()
+    loadi 4[PC], t0
+    storei EmptyValueTag, TagOffset[cfr, t0, 8]
+    storei 0, PayloadOffset[cfr, t0, 8]
+    dispatch(2)
+
+
+_llint_op_create_arguments:
+    traceExecution()
+    loadi 4[PC], t0
+    bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opCreateArgumentsDone
+    callSlowPath(_llint_slow_path_create_arguments)
+.opCreateArgumentsDone:
+    dispatch(2)
+
+
+macro allocateBasicJSObject(sizeClassIndex, classInfoOffset, structure, result, scratch1, scratch2, slowCase)
+    if ALWAYS_ALLOCATE_SLOW
+        jmp slowCase
+    else
+        const offsetOfMySizeClass =
+            JSGlobalData::heap +
+            Heap::m_objectSpace +
+            MarkedSpace::m_normalSpace +
+            MarkedSpace::Subspace::preciseAllocators +
+            sizeClassIndex * sizeof MarkedAllocator
+        
+        # FIXME: we can get the global data in one load from the stack.
+        loadp CodeBlock[cfr], scratch1
+        loadp CodeBlock::m_globalData[scratch1], scratch1
+        
+        # Get the object from the free list.    
+        loadp offsetOfMySizeClass + MarkedAllocator::m_firstFreeCell[scratch1], result
+        btpz result, slowCase
+        
+        # Remove the object from the free list.
+        loadp [result], scratch2
+        storep scratch2, offsetOfMySizeClass + MarkedAllocator::m_firstFreeCell[scratch1]
+    
+        # Initialize the object.
+        loadp classInfoOffset[scratch1], scratch2
+        storep scratch2, [result]
+        storep structure, JSCell::m_structure[result]
+        storep 0, JSObject::m_inheritorID[result]
+        addp sizeof JSObject, result, scratch1
+        storep scratch1, JSObject::m_propertyStorage[result]
+    end
+end
+
+_llint_op_create_this:
+    traceExecution()
+    loadi 8[PC], t0
+    assertNotConstant(t0)
+    bineq TagOffset[cfr, t0, 8], CellTag, .opCreateThisSlow
+    loadi PayloadOffset[cfr, t0, 8], t0
+    loadp JSCell::m_structure[t0], t1
+    bbb Structure::m_typeInfo + TypeInfo::m_type[t1], ObjectType, .opCreateThisSlow
+    loadp JSObject::m_inheritorID[t0], t2
+    btpz t2, .opCreateThisSlow
+    allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t2, t0, t1, t3, .opCreateThisSlow)
+    loadi 4[PC], t1
+    storei CellTag, TagOffset[cfr, t1, 8]
+    storei t0, PayloadOffset[cfr, t1, 8]
+    dispatch(3)
+
+.opCreateThisSlow:
+    callSlowPath(_llint_slow_path_create_this)
+    dispatch(3)
+
+
+_llint_op_get_callee:
+    traceExecution()
+    loadi 4[PC], t0
+    loadp PayloadOffset + Callee[cfr], t1
+    storei CellTag, TagOffset[cfr, t0, 8]
+    storei t1, PayloadOffset[cfr, t0, 8]
+    dispatch(2)
+
+
+_llint_op_convert_this:
+    traceExecution()
+    loadi 4[PC], t0
+    bineq TagOffset[cfr, t0, 8], CellTag, .opConvertThisSlow
+    loadi PayloadOffset[cfr, t0, 8], t0
+    loadp JSCell::m_structure[t0], t0
+    bbb Structure::m_typeInfo + TypeInfo::m_type[t0], ObjectType, .opConvertThisSlow
+    dispatch(2)
+
+.opConvertThisSlow:
+    callSlowPath(_llint_slow_path_convert_this)
+    dispatch(2)
+
+
+_llint_op_new_object:
+    traceExecution()
+    loadp CodeBlock[cfr], t0
+    loadp CodeBlock::m_globalObject[t0], t0
+    loadp JSGlobalObject::m_emptyObjectStructure[t0], t1
+    allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t1, t0, t2, t3, .opNewObjectSlow)
+    loadi 4[PC], t1
+    storei CellTag, TagOffset[cfr, t1, 8]
+    storei t0, PayloadOffset[cfr, t1, 8]
+    dispatch(2)
+
+.opNewObjectSlow:
+    callSlowPath(_llint_slow_path_new_object)
+    dispatch(2)
+
+
+_llint_op_new_array:
+    traceExecution()
+    callSlowPath(_llint_slow_path_new_array)
+    dispatch(4)
+
+
+_llint_op_new_array_buffer:
+    traceExecution()
+    callSlowPath(_llint_slow_path_new_array_buffer)
+    dispatch(4)
+
+
+_llint_op_new_regexp:
+    traceExecution()
+    callSlowPath(_llint_slow_path_new_regexp)
+    dispatch(3)
+
+
+_llint_op_mov:
+    traceExecution()
+    loadi 8[PC], t1
+    loadi 4[PC], t0
+    loadConstantOrVariable(t1, t2, t3)
+    storei t2, TagOffset[cfr, t0, 8]
+    storei t3, PayloadOffset[cfr, t0, 8]
+    dispatch(3)
+
+
+_llint_op_not:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 4[PC], t1
+    loadConstantOrVariable(t0, t2, t3)
+    bineq t2, BooleanTag, .opNotSlow
+    xori 1, t3
+    storei t2, TagOffset[cfr, t1, 8]
+    storei t3, PayloadOffset[cfr, t1, 8]
+    dispatch(3)
+
+.opNotSlow:
+    callSlowPath(_llint_slow_path_not)
+    dispatch(3)
+
+
+_llint_op_eq:
+    traceExecution()
+    loadi 12[PC], t2
+    loadi 8[PC], t0
+    loadConstantOrVariable(t2, t3, t1)
+    loadConstantOrVariable2Reg(t0, t2, t0)
+    bineq t2, t3, .opEqSlow
+    bieq t2, CellTag, .opEqSlow
+    bib t2, LowestTag, .opEqSlow
+    loadi 4[PC], t2
+    cieq t0, t1, t0
+    storei BooleanTag, TagOffset[cfr, t2, 8]
+    storei t0, PayloadOffset[cfr, t2, 8]
+    dispatch(4)
+
+.opEqSlow:
+    callSlowPath(_llint_slow_path_eq)
+    dispatch(4)
+
+
+_llint_op_eq_null:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 4[PC], t3
+    assertNotConstant(t0)
+    loadi TagOffset[cfr, t0, 8], t1
+    loadi PayloadOffset[cfr, t0, 8], t0
+    bineq t1, CellTag, .opEqNullImmediate
+    loadp JSCell::m_structure[t0], t1
+    tbnz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1
+    jmp .opEqNullNotImmediate
+.opEqNullImmediate:
+    cieq t1, NullTag, t2
+    cieq t1, UndefinedTag, t1
+    ori t2, t1
+.opEqNullNotImmediate:
+    storei BooleanTag, TagOffset[cfr, t3, 8]
+    storei t1, PayloadOffset[cfr, t3, 8]
+    dispatch(3)
+
+
+_llint_op_neq:
+    traceExecution()
+    loadi 12[PC], t2
+    loadi 8[PC], t0
+    loadConstantOrVariable(t2, t3, t1)
+    loadConstantOrVariable2Reg(t0, t2, t0)
+    bineq t2, t3, .opNeqSlow
+    bieq t2, CellTag, .opNeqSlow
+    bib t2, LowestTag, .opNeqSlow
+    loadi 4[PC], t2
+    cineq t0, t1, t0
+    storei BooleanTag, TagOffset[cfr, t2, 8]
+    storei t0, PayloadOffset[cfr, t2, 8]
+    dispatch(4)
+
+.opNeqSlow:
+    callSlowPath(_llint_slow_path_neq)
+    dispatch(4)
+    
+
+_llint_op_neq_null:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 4[PC], t3
+    assertNotConstant(t0)
+    loadi TagOffset[cfr, t0, 8], t1
+    loadi PayloadOffset[cfr, t0, 8], t0
+    bineq t1, CellTag, .opNeqNullImmediate
+    loadp JSCell::m_structure[t0], t1
+    tbz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1
+    jmp .opNeqNullNotImmediate
+.opNeqNullImmediate:
+    cineq t1, NullTag, t2
+    cineq t1, UndefinedTag, t1
+    andi t2, t1
+.opNeqNullNotImmediate:
+    storei BooleanTag, TagOffset[cfr, t3, 8]
+    storei t1, PayloadOffset[cfr, t3, 8]
+    dispatch(3)
+
+
+macro strictEq(equalityOperation, slow_path)
+    loadi 12[PC], t2
+    loadi 8[PC], t0
+    loadConstantOrVariable(t2, t3, t1)
+    loadConstantOrVariable2Reg(t0, t2, t0)
+    bineq t2, t3, .slow
+    bib t2, LowestTag, .slow
+    bineq t2, CellTag, .notString
+    loadp JSCell::m_structure[t0], t2
+    loadp JSCell::m_structure[t1], t3
+    bbneq Structure::m_typeInfo + TypeInfo::m_type[t2], StringType, .notString
+    bbeq Structure::m_typeInfo + TypeInfo::m_type[t3], StringType, .slow
+.notString:
+    loadi 4[PC], t2
+    equalityOperation(t0, t1, t0)
+    storei BooleanTag, TagOffset[cfr, t2, 8]
+    storei t0, PayloadOffset[cfr, t2, 8]
+    dispatch(4)
+
+.slow:
+    callSlowPath(slow_path)
+    dispatch(4)
+end
+
+_llint_op_stricteq:
+    traceExecution()
+    strictEq(macro (left, right, result) cieq left, right, result end, _llint_slow_path_stricteq)
+
+
+_llint_op_nstricteq:
+    traceExecution()
+    strictEq(macro (left, right, result) cineq left, right, result end, _llint_slow_path_nstricteq)
+
+
+_llint_op_less:
+    traceExecution()
+    callSlowPath(_llint_slow_path_less)
+    dispatch(4)
+
+
+_llint_op_lesseq:
+    traceExecution()
+    callSlowPath(_llint_slow_path_lesseq)
+    dispatch(4)
+
+
+_llint_op_greater:
+    traceExecution()
+    callSlowPath(_llint_slow_path_greater)
+    dispatch(4)
+
+
+_llint_op_greatereq:
+    traceExecution()
+    callSlowPath(_llint_slow_path_greatereq)
+    dispatch(4)
+
+
+_llint_op_pre_inc:
+    traceExecution()
+    loadi 4[PC], t0
+    bineq TagOffset[cfr, t0, 8], Int32Tag, .opPreIncSlow
+    loadi PayloadOffset[cfr, t0, 8], t1
+    baddio 1, t1, .opPreIncSlow
+    storei t1, PayloadOffset[cfr, t0, 8]
+    dispatch(2)
+
+.opPreIncSlow:
+    callSlowPath(_llint_slow_path_pre_inc)
+    dispatch(2)
+
+
+_llint_op_pre_dec:
+    traceExecution()
+    loadi 4[PC], t0
+    bineq TagOffset[cfr, t0, 8], Int32Tag, .opPreDecSlow
+    loadi PayloadOffset[cfr, t0, 8], t1
+    bsubio 1, t1, .opPreDecSlow
+    storei t1, PayloadOffset[cfr, t0, 8]
+    dispatch(2)
+
+.opPreDecSlow:
+    callSlowPath(_llint_slow_path_pre_dec)
+    dispatch(2)
+
+
+_llint_op_post_inc:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 4[PC], t1
+    bineq TagOffset[cfr, t0, 8], Int32Tag, .opPostIncSlow
+    bieq t0, t1, .opPostIncDone
+    loadi PayloadOffset[cfr, t0, 8], t2
+    move t2, t3
+    baddio 1, t3, .opPostIncSlow
+    storei Int32Tag, TagOffset[cfr, t1, 8]
+    storei t2, PayloadOffset[cfr, t1, 8]
+    storei t3, PayloadOffset[cfr, t0, 8]
+.opPostIncDone:
+    dispatch(3)
+
+.opPostIncSlow:
+    callSlowPath(_llint_slow_path_post_inc)
+    dispatch(3)
+
+
+_llint_op_post_dec:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 4[PC], t1
+    bineq TagOffset[cfr, t0, 8], Int32Tag, .opPostDecSlow
+    bieq t0, t1, .opPostDecDone
+    loadi PayloadOffset[cfr, t0, 8], t2
+    move t2, t3
+    bsubio 1, t3, .opPostDecSlow
+    storei Int32Tag, TagOffset[cfr, t1, 8]
+    storei t2, PayloadOffset[cfr, t1, 8]
+    storei t3, PayloadOffset[cfr, t0, 8]
+.opPostDecDone:
+    dispatch(3)
+
+.opPostDecSlow:
+    callSlowPath(_llint_slow_path_post_dec)
+    dispatch(3)
+
+
+_llint_op_to_jsnumber:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 4[PC], t1
+    loadConstantOrVariable(t0, t2, t3)
+    bieq t2, Int32Tag, .opToJsnumberIsInt
+    biaeq t2, EmptyValueTag, .opToJsnumberSlow
+.opToJsnumberIsInt:
+    storei t2, TagOffset[cfr, t1, 8]
+    storei t3, PayloadOffset[cfr, t1, 8]
+    dispatch(3)
+
+.opToJsnumberSlow:
+    callSlowPath(_llint_slow_path_to_jsnumber)
+    dispatch(3)
+
+
+_llint_op_negate:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 4[PC], t3
+    loadConstantOrVariable(t0, t1, t2)
+    bineq t1, Int32Tag, .opNegateSrcNotInt
+    btiz t2, 0x7fffffff, .opNegateSlow
+    negi t2
+    storei Int32Tag, TagOffset[cfr, t3, 8]
+    storei t2, PayloadOffset[cfr, t3, 8]
+    dispatch(3)
+.opNegateSrcNotInt:
+    bia t1, LowestTag, .opNegateSlow
+    xori 0x80000000, t1
+    storei t1, TagOffset[cfr, t3, 8]
+    storei t2, PayloadOffset[cfr, t3, 8]
+    dispatch(3)
+
+.opNegateSlow:
+    callSlowPath(_llint_slow_path_negate)
+    dispatch(3)
+
+
+macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, slow_path)
+    loadi 12[PC], t2
+    loadi 8[PC], t0
+    loadConstantOrVariable(t2, t3, t1)
+    loadConstantOrVariable2Reg(t0, t2, t0)
+    bineq t2, Int32Tag, .op1NotInt
+    bineq t3, Int32Tag, .op2NotInt
+    loadi 4[PC], t2
+    integerOperationAndStore(t3, t1, t0, .slow, t2)
+    dispatch(5)
+
+.op1NotInt:
+    # First operand is definitely not an int, the second operand could be anything.
+    bia t2, LowestTag, .slow
+    bib t3, LowestTag, .op1NotIntOp2Double
+    bineq t3, Int32Tag, .slow
+    ci2d t1, ft1
+    jmp .op1NotIntReady
+.op1NotIntOp2Double:
+    fii2d t1, t3, ft1
+.op1NotIntReady:
+    loadi 4[PC], t1
+    fii2d t0, t2, ft0
+    doubleOperation(ft1, ft0)
+    stored ft0, [cfr, t1, 8]
+    dispatch(5)
+
+.op2NotInt:
+    # First operand is definitely an int, the second operand is definitely not.
+    loadi 4[PC], t2
+    bia t3, LowestTag, .slow
+    ci2d t0, ft0
+    fii2d t1, t3, ft1
+    doubleOperation(ft1, ft0)
+    stored ft0, [cfr, t2, 8]
+    dispatch(5)
+
+.slow:
+    callSlowPath(slow_path)
+    dispatch(5)
+end
+
+macro binaryOp(integerOperation, doubleOperation, slow_path)
+    binaryOpCustomStore(
+        macro (int32Tag, left, right, slow, index)
+            integerOperation(left, right, slow)
+            storei int32Tag, TagOffset[cfr, index, 8]
+            storei right, PayloadOffset[cfr, index, 8]
+        end,
+        doubleOperation, slow_path)
+end
+
+_llint_op_add:
+    traceExecution()
+    binaryOp(
+        macro (left, right, slow) baddio left, right, slow end,
+        macro (left, right) addd left, right end,
+        _llint_slow_path_add)
+
+
+_llint_op_mul:
+    traceExecution()
+    binaryOpCustomStore(
+        macro (int32Tag, left, right, slow, index)
+            const scratch = int32Tag   # We know that we can reuse the int32Tag register since it has a constant.
+            move right, scratch
+            bmulio left, scratch, slow
+            btinz scratch, .done
+            bilt left, 0, slow
+            bilt right, 0, slow
+        .done:
+            storei Int32Tag, TagOffset[cfr, index, 8]
+            storei scratch, PayloadOffset[cfr, index, 8]
+        end,
+        macro (left, right) muld left, right end,
+        _llint_slow_path_mul)
+
+
+_llint_op_sub:
+    traceExecution()
+    binaryOp(
+        macro (left, right, slow) bsubio left, right, slow end,
+        macro (left, right) subd left, right end,
+        _llint_slow_path_sub)
+
+
+_llint_op_div:
+    traceExecution()
+    binaryOpCustomStore(
+        macro (int32Tag, left, right, slow, index)
+            ci2d left, ft0
+            ci2d right, ft1
+            divd ft0, ft1
+            bcd2i ft1, right, .notInt
+            storei int32Tag, TagOffset[cfr, index, 8]
+            storei right, PayloadOffset[cfr, index, 8]
+            jmp .done
+        .notInt:
+            stored ft1, [cfr, index, 8]
+        .done:
+        end,
+        macro (left, right) divd left, right end,
+        _llint_slow_path_div)
+
+
+_llint_op_mod:
+    traceExecution()
+    callSlowPath(_llint_slow_path_mod)
+    dispatch(4)
+
+
+macro bitOp(operation, slow_path, advance)
+    loadi 12[PC], t2
+    loadi 8[PC], t0
+    loadConstantOrVariable(t2, t3, t1)
+    loadConstantOrVariable2Reg(t0, t2, t0)
+    bineq t3, Int32Tag, .slow
+    bineq t2, Int32Tag, .slow
+    loadi 4[PC], t2
+    operation(t1, t0, .slow)
+    storei t3, TagOffset[cfr, t2, 8]
+    storei t0, PayloadOffset[cfr, t2, 8]
+    dispatch(advance)
+
+.slow:
+    callSlowPath(slow_path)
+    dispatch(advance)
+end
+
+_llint_op_lshift:
+    traceExecution()
+    bitOp(
+        macro (left, right, slow) lshifti left, right end,
+        _llint_slow_path_lshift,
+        4)
+
+
+_llint_op_rshift:
+    traceExecution()
+    bitOp(
+        macro (left, right, slow) rshifti left, right end,
+        _llint_slow_path_rshift,
+        4)
+
+
+_llint_op_urshift:
+    traceExecution()
+    bitOp(
+        macro (left, right, slow)
+            urshifti left, right
+            bilt right, 0, slow
+        end,
+        _llint_slow_path_urshift,
+        4)
+
+
+_llint_op_bitand:
+    traceExecution()
+    bitOp(
+        macro (left, right, slow) andi left, right end,
+        _llint_slow_path_bitand,
+        5)
+
+
+_llint_op_bitxor:
+    traceExecution()
+    bitOp(
+        macro (left, right, slow) xori left, right end,
+        _llint_slow_path_bitxor,
+        5)
+
+
+_llint_op_bitor:
+    traceExecution()
+    bitOp(
+        macro (left, right, slow) ori left, right end,
+        _llint_slow_path_bitor,
+        5)
+
+
+_llint_op_bitnot:
+    traceExecution()
+    loadi 8[PC], t1
+    loadi 4[PC], t0
+    loadConstantOrVariable(t1, t2, t3)
+    bineq t2, Int32Tag, .opBitnotSlow
+    noti t3
+    storei t2, TagOffset[cfr, t0, 8]
+    storei t3, PayloadOffset[cfr, t0, 8]
+    dispatch(3)
+