Source/JavaScriptCore/ChangeLog

 12012-02-02 Filip Pizlo <fpizlo@apple.com>
 2
 3 JSC should be a triple-tier VM
 4 https://bugs.webkit.org/show_bug.cgi?id=75812
 5 <rdar://problem/10079694>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 Implemented an interpreter that uses the JIT's calling convention. This
 10 interpreter is called LLInt, or the Low Level Interpreter. JSC will now
 11 will start by executing code in LLInt and will only tier up to the old
 12 JIT after the code is proven hot.
 13
 14 LLInt is written in a modified form of our macro assembly. This new macro
 15 assembly is compiled by an offline assembler (see offlineasm), which
 16 implements many modern conveniences such as a Turing-complete CPS-based
 17 macro language and direct access to relevant C++ type information
 18 (basically offsets of fields and sizes of structs/classes).
 19
 20 Code executing in LLInt appears to the rest of the JSC world "as if" it
 21 were executing in the old JIT. Hence, things like exception handling and
 22 cross-execution-engine calls just work and require pretty much no
 23 additional overhead.
 24
 25 This interpreter is 2-2.5x faster than our old interpreter on SunSpider,
 26 V8, and Kraken. With triple-tiering turned on, we're neutral on SunSpider,
 27 V8, and Kraken, but appear to get a double-digit improvement on real-world
 28 websites due to a huge reduction in the amount of JIT'ing.
 29
 30 * CMakeLists.txt:
 31 * GNUmakefile.am:
 32 * GNUmakefile.list.am:
 33 * JavaScriptCore.pri:
 34 * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
 35 * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops:
 36 * JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd:
 37 * JavaScriptCore.xcodeproj/project.pbxproj:
 38 * Target.pri:
 39 * assembler/LinkBuffer.h:
 40 * assembler/MacroAssemblerCodeRef.h:
 41 (MacroAssemblerCodePtr):
 42 (JSC::MacroAssemblerCodePtr::createFromExecutableAddress):
 43 * bytecode/BytecodeConventions.h: Added.
 44 * bytecode/CallLinkStatus.cpp:
 45 (JSC::CallLinkStatus::computeFromLLInt):
 46 (JSC):
 47 (JSC::CallLinkStatus::computeFor):
 48 * bytecode/CallLinkStatus.h:
 49 (JSC::CallLinkStatus::isSet):
 50 (JSC::CallLinkStatus::operator!):
 51 (CallLinkStatus):
 52 * bytecode/CodeBlock.cpp:
 53 (JSC::CodeBlock::dump):
 54 (JSC::CodeBlock::CodeBlock):
 55 (JSC::CodeBlock::~CodeBlock):
 56 (JSC::CodeBlock::finalizeUnconditionally):
 57 (JSC::CodeBlock::stronglyVisitStrongReferences):
 58 (JSC::CodeBlock::unlinkCalls):
 59 (JSC::CodeBlock::unlinkIncomingCalls):
 60 (JSC):
 61 (JSC::CodeBlock::bytecodeOffset):
 62 (JSC::ProgramCodeBlock::jettison):
 63 (JSC::EvalCodeBlock::jettison):
 64 (JSC::FunctionCodeBlock::jettison):
 65 (JSC::ProgramCodeBlock::jitCompileImpl):
 66 (JSC::EvalCodeBlock::jitCompileImpl):
 67 (JSC::FunctionCodeBlock::jitCompileImpl):
 68 (JSC::CodeBlock::handleBytecodeDiscardingOpportunity):
 69 * bytecode/CodeBlock.h:
 70 (JSC):
 71 (CodeBlock):
 72 (JSC::CodeBlock::baselineVersion):
 73 (JSC::CodeBlock::linkIncomingCall):
 74 (JSC::CodeBlock::bytecodeOffset):
 75 (JSC::CodeBlock::jitCompile):
 76 (JSC::CodeBlock::hasOptimizedReplacement):
 77 (JSC::CodeBlock::addPropertyAccessInstruction):
 78 (JSC::CodeBlock::addGlobalResolveInstruction):
 79 (JSC::CodeBlock::addLLIntCallLinkInfo):
 80 (JSC::CodeBlock::addGlobalResolveInfo):
 81 (JSC::CodeBlock::numberOfMethodCallLinkInfos):
 82 (JSC::CodeBlock::valueProfilePredictionForBytecodeOffset):
 83 (JSC::CodeBlock::likelyToTakeSlowCase):
 84 (JSC::CodeBlock::couldTakeSlowCase):
 85 (JSC::CodeBlock::likelyToTakeSpecialFastCase):
 86 (JSC::CodeBlock::likelyToTakeDeepestSlowCase):
 87 (JSC::CodeBlock::likelyToTakeAnySlowCase):
 88 (JSC::CodeBlock::addFrequentExitSite):
 89 (JSC::CodeBlock::dontJITAnytimeSoon):
 90 (JSC::CodeBlock::jitAfterWarmUp):
 91 (JSC::CodeBlock::jitSoon):
 92 (JSC::CodeBlock::llintExecuteCounter):
 93 (ProgramCodeBlock):
 94 (EvalCodeBlock):
 95 (FunctionCodeBlock):
 96 * bytecode/GetByIdStatus.cpp:
 97 (JSC::GetByIdStatus::computeFromLLInt):
 98 (JSC):
 99 (JSC::GetByIdStatus::computeFor):
 100 * bytecode/GetByIdStatus.h:
 101 (JSC::GetByIdStatus::GetByIdStatus):
 102 (JSC::GetByIdStatus::wasSeenInJIT):
 103 (GetByIdStatus):
 104 * bytecode/Instruction.h:
 105 (JSC):
 106 (JSC::Instruction::Instruction):
 107 (Instruction):
 108 * bytecode/LLIntCallLinkInfo.h: Added.
 109 (JSC):
 110 (JSC::LLIntCallLinkInfo::LLIntCallLinkInfo):
 111 (LLIntCallLinkInfo):
 112 (JSC::LLIntCallLinkInfo::~LLIntCallLinkInfo):
 113 (JSC::LLIntCallLinkInfo::isLinked):
 114 (JSC::LLIntCallLinkInfo::unlink):
 115 * bytecode/MethodCallLinkStatus.cpp:
 116 (JSC::MethodCallLinkStatus::computeFor):
 117 * bytecode/Opcode.h:
 118 (JSC):
 119 (JSC::padOpcodeName):
 120 * bytecode/PutByIdStatus.cpp:
 121 (JSC::PutByIdStatus::computeFromLLInt):
 122 (JSC):
 123 (JSC::PutByIdStatus::computeFor):
 124 * bytecode/PutByIdStatus.h:
 125 (PutByIdStatus):
 126 * bytecompiler/BytecodeGenerator.cpp:
 127 (JSC::BytecodeGenerator::emitResolve):
 128 (JSC::BytecodeGenerator::emitResolveWithBase):
 129 (JSC::BytecodeGenerator::emitGetById):
 130 (JSC::BytecodeGenerator::emitPutById):
 131 (JSC::BytecodeGenerator::emitDirectPutById):
 132 (JSC::BytecodeGenerator::emitCall):
 133 (JSC::BytecodeGenerator::emitConstruct):
 134 (JSC::BytecodeGenerator::emitCatch):
 135 * dfg/DFGByteCodeParser.cpp:
 136 (JSC::DFG::ByteCodeParser::getPredictionWithoutOSRExit):
 137 (JSC::DFG::ByteCodeParser::handleInlining):
 138 (JSC::DFG::ByteCodeParser::parseBlock):
 139 * dfg/DFGCapabilities.h:
 140 (JSC::DFG::canCompileOpcode):
 141 * dfg/DFGOSRExitCompiler.cpp:
 142 * dfg/DFGOperations.cpp:
 143 * heap/Heap.cpp:
 144 (JSC::Heap::collect):
 145 * heap/Heap.h:
 146 (JSC):
 147 (Heap):
 148 * heap/MarkStack.cpp:
 149 (JSC::visitChildren):
 150 * heap/MarkedSpace.h:
 151 (JSC):
 152 (MarkedSpace):
 153 * interpreter/CallFrame.h:
 154 (ExecState):
 155 (JSC::ExecState::currentVPC):
 156 * interpreter/Interpreter.cpp:
 157 (JSC::Interpreter::~Interpreter):
 158 (JSC):
 159 (JSC::Interpreter::initialize):
 160 (JSC::Interpreter::isOpcode):
 161 (JSC::Interpreter::unwindCallFrame):
 162 (JSC::Interpreter::privateExecute):
 163 (JSC::Interpreter::retrieveLastCaller):
 164 * interpreter/Interpreter.h:
 165 (JSC):
 166 (Interpreter):
 167 (JSC::Interpreter::getOpcode):
 168 (JSC::Interpreter::getOpcodeID):
 169 (JSC::Interpreter::enabled):
 170 * interpreter/RegisterFile.h:
 171 (JSC):
 172 (RegisterFile):
 173 * jit/HostCallReturnValue.cpp: Added.
 174 (JSC):
 175 (JSC::getHostCallReturnValueWithExecState):
 176 * jit/HostCallReturnValue.h: Added.
 177 (JSC):
 178 (JSC::initializeHostCallReturnValue):
 179 * jit/JIT.cpp:
 180 (JSC::JIT::privateCompileMainPass):
 181 (JSC::JIT::privateCompileSlowCases):
 182 (JSC::JIT::privateCompile):
 183 * jit/JITCode.h:
 184 (JSC::JITCode::isOptimizingJIT):
 185 (JITCode):
 186 (JSC::JITCode::isBaselineCode):
 187 (JSC::JITCode::JITCode):
 188 * jit/JITDriver.h:
 189 (JSC::jitCompileIfAppropriate):
 190 (JSC::jitCompileFunctionIfAppropriate):
 191 * jit/JITExceptions.cpp:
 192 (JSC::jitThrow):
 193 * jit/JITStubs.cpp:
 194 (JSC::DEFINE_STUB_FUNCTION):
 195 (JSC):
 196 * jit/JSInterfaceJIT.h:
 197 * llint: Added.
 198 * llint/LLIntCommon.h: Added.
 199 * llint/LLIntData.cpp: Added.
 200 (LLInt):
 201 (JSC::LLInt::Data::Data):
 202 (JSC::LLInt::Data::~Data):
 203 * llint/LLIntData.h: Added.
 204 (JSC):
 205 (LLInt):
 206 (Data):
 207 (JSC::LLInt::Data::exceptionInstructions):
 208 (JSC::LLInt::Data::opcodeMap):
 209 * llint/LLIntEntrypoints.cpp: Added.
 210 (LLInt):
 211 (JSC::LLInt::getFunctionEntrypoint):
 212 (JSC::LLInt::getEvalEntrypoint):
 213 (JSC::LLInt::getProgramEntrypoint):
 214 * llint/LLIntEntrypoints.h: Added.
 215 (JSC):
 216 (LLInt):
 217 (JSC::LLInt::getEntrypoint):
 218 * llint/LLIntExceptions.cpp: Added.
 219 (LLInt):
 220 (JSC::LLInt::interpreterThrowInCaller):
 221 (JSC::LLInt::returnToThrowForThrownException):
 222 (JSC::LLInt::returnToThrow):
 223 (JSC::LLInt::callToThrow):
 224 * llint/LLIntExceptions.h: Added.
 225 (JSC):
 226 (LLInt):
 227 * llint/LLIntHelpers.cpp: Added.
 228 (LLInt):
 229 (JSC::LLInt::llint_trace_operand):
 230 (JSC::LLInt::llint_trace_value):
 231 (JSC::LLInt::LLINT_HELPER_DECL):
 232 (JSC::LLInt::traceFunctionPrologue):
 233 (JSC::LLInt::shouldJIT):
 234 (JSC::LLInt::entryOSR):
 235 (JSC::LLInt::resolveGlobal):
 236 (JSC::LLInt::getByVal):
 237 (JSC::LLInt::handleHostCall):
 238 (JSC::LLInt::setUpCall):
 239 (JSC::LLInt::genericCall):
 240 * llint/LLIntHelpers.h: Added.
 241 (JSC):
 242 (LLInt):
 243 * llint/LLIntOfflineAsmConfig.h: Added.
 244 * llint/LLIntOffsetsExtractor.cpp: Added.
 245 (JSC):
 246 (LLIntOffsetsExtractor):
 247 (JSC::LLIntOffsetsExtractor::dummy):
 248 (main):
 249 * llint/LLIntThunks.cpp: Added.
 250 (LLInt):
 251 (JSC::LLInt::generateThunkWithJumpTo):
 252 (JSC::LLInt::functionForCallEntryThunkGenerator):
 253 (JSC::LLInt::functionForConstructEntryThunkGenerator):
 254 (JSC::LLInt::functionForCallArityCheckThunkGenerator):
 255 (JSC::LLInt::functionForConstructArityCheckThunkGenerator):
 256 (JSC::LLInt::evalEntryThunkGenerator):
 257 (JSC::LLInt::programEntryThunkGenerator):
 258 * llint/LLIntThunks.h: Added.
 259 (JSC):
 260 (LLInt):
 261 * llint/LowLevelInterpreter.asm: Added.
 262 * llint/LowLevelInterpreter.cpp: Added.
 263 * llint/LowLevelInterpreter.h: Added.
 264 * offlineasm: Added.
 265 * offlineasm/armv7.rb: Added.
 266 * offlineasm/asm.rb: Added.
 267 * offlineasm/ast.rb: Added.
 268 * offlineasm/backends.rb: Added.
 269 * offlineasm/generate_offset_extractor.rb: Added.
 270 * offlineasm/instructions.rb: Added.
 271 * offlineasm/offset_extractor_constants.rb: Added.
 272 * offlineasm/offsets.rb: Added.
 273 * offlineasm/opt.rb: Added.
 274 * offlineasm/parser.rb: Added.
 275 * offlineasm/registers.rb: Added.
 276 * offlineasm/self_hash.rb: Added.
 277 * offlineasm/settings.rb: Added.
 278 * offlineasm/transform.rb: Added.
 279 * offlineasm/x86.rb: Added.
 280 * runtime/CodeSpecializationKind.h: Added.
 281 (JSC):
 282 * runtime/CommonSlowPaths.h:
 283 (JSC::CommonSlowPaths::arityCheckFor):
 284 (CommonSlowPaths):
 285 * runtime/Executable.cpp:
 286 (JSC::jettisonCodeBlock):
 287 (JSC::EvalExecutable::jitCompile):
 288 (JSC):
 289 (JSC::samplingDescription):
 290 (JSC::EvalExecutable::compileInternal):
 291 (JSC::ProgramExecutable::jitCompile):
 292 (JSC::ProgramExecutable::compileInternal):
 293 (JSC::FunctionExecutable::baselineCodeBlockFor):
 294 (JSC::FunctionExecutable::jitCompileForCall):
 295 (JSC::FunctionExecutable::jitCompileForConstruct):
 296 (JSC::FunctionExecutable::compileForCallInternal):
 297 (JSC::FunctionExecutable::compileForConstructInternal):
 298 * runtime/Executable.h:
 299 (JSC):
 300 (EvalExecutable):
 301 (ProgramExecutable):
 302 (FunctionExecutable):
 303 (JSC::FunctionExecutable::jitCompileFor):
 304 * runtime/ExecutionHarness.h: Added.
 305 (JSC):
 306 (JSC::prepareForExecution):
 307 (JSC::prepareFunctionForExecution):
 308 * runtime/JSActivation.h:
 309 (JSC::JSActivation::tearOff):
 310 * runtime/JSArray.h:
 311 (JSC):
 312 (JSArray):
 313 * runtime/JSCell.h:
 314 (JSC):
 315 (JSCell):
 316 * runtime/JSFunction.h:
 317 (JSC):
 318 (JSFunction):
 319 * runtime/JSGlobalData.cpp:
 320 (JSC::JSGlobalData::JSGlobalData):
 321 * runtime/JSGlobalData.h:
 322 (JSC):
 323 (JSGlobalData):
 324 * runtime/JSGlobalObject.h:
 325 (JSC):
 326 (JSGlobalObject):
 327 * runtime/JSObject.h:
 328 (JSC):
 329 (JSObject):
 330 (JSFinalObject):
 331 * runtime/JSPropertyNameIterator.h:
 332 (JSC):
 333 (JSPropertyNameIterator):
 334 * runtime/JSString.h:
 335 (JSC):
 336 (JSString):
 337 * runtime/JSTypeInfo.h:
 338 (JSC):
 339 (TypeInfo):
 340 * runtime/JSValue.cpp:
 341 (JSC::JSValue::description):
 342 * runtime/JSVariableObject.h:
 343 (JSC):
 344 (JSVariableObject):
 345 * runtime/Options.cpp:
 346 (Options):
 347 (JSC::Options::initializeOptions):
 348 * runtime/Options.h:
 349 (Options):
 350 * runtime/ScopeChain.h:
 351 (JSC):
 352 (ScopeChainNode):
 353 * runtime/Structure.cpp:
 354 (JSC::Structure::addPropertyTransition):
 355 * runtime/Structure.h:
 356 (JSC):
 357 (Structure):
 358 * runtime/StructureChain.h:
 359 (JSC):
 360 (StructureChain):
 361 * wtf/InlineASM.h:
 362 * wtf/Platform.h:
 363 * wtf/SentinelLinkedList.h:
 364 (SentinelLinkedList):
 365 (WTF::SentinelLinkedList::isEmpty):
 366 * wtf/text/StringImpl.h:
 367 (JSC):
 368 (StringImpl):
 369
13702012-02-14 Eric Seidel <eric@webkit.org>
2371
3372 Upstream Android's additions to Platform.h
107713

Source/JavaScriptCore/CMakeLists.txt

@@SET(JavaScriptCore_INCLUDE_DIRECTORIES
1111 "${JAVASCRIPTCORE_DIR}/debugger"
1212 "${JAVASCRIPTCORE_DIR}/interpreter"
1313 "${JAVASCRIPTCORE_DIR}/jit"
 14 "${JAVASCRIPTCORE_DIR}/llint"
1415 "${JAVASCRIPTCORE_DIR}/parser"
1516 "${JAVASCRIPTCORE_DIR}/profiler"
1617 "${JAVASCRIPTCORE_DIR}/runtime"

@@SET(JavaScriptCore_SOURCES
9798 interpreter/RegisterFile.cpp
9899
99100 jit/ExecutableAllocator.cpp
 101 jit/HostCallReturnValue.cpp
100102 jit/JITArithmetic32_64.cpp
101103 jit/JITArithmetic.cpp
102104 jit/JITCall32_64.cpp
107713

Source/JavaScriptCore/GNUmakefile.am

@@javascriptcore_cppflags += \
5757 -I$(srcdir)/Source/JavaScriptCore/interpreter \
5858 -I$(srcdir)/Source/JavaScriptCore/jit \
5959 -I$(srcdir)/Source/JavaScriptCore/jit \
 60 -I$(srcdir)/Source/JavaScriptCore/llint \
6061 -I$(srcdir)/Source/JavaScriptCore/parser \
6162 -I$(srcdir)/Source/JavaScriptCore/profiler \
6263 -I$(srcdir)/Source/JavaScriptCore/runtime \
107713

Source/JavaScriptCore/GNUmakefile.list.am

@@javascriptcore_sources += \
8181 Source/JavaScriptCore/assembler/RepatchBuffer.h \
8282 Source/JavaScriptCore/assembler/SH4Assembler.h \
8383 Source/JavaScriptCore/assembler/X86Assembler.h \
 84 Source/JavaScriptCore/bytecode/BytecodeConventions.h \
8485 Source/JavaScriptCore/bytecode/CallLinkInfo.cpp \
8586 Source/JavaScriptCore/bytecode/CallLinkInfo.h \
8687 Source/JavaScriptCore/bytecode/CallLinkStatus.cpp \

@@javascriptcore_sources += \
102103 Source/JavaScriptCore/bytecode/Instruction.h \
103104 Source/JavaScriptCore/bytecode/JumpTable.cpp \
104105 Source/JavaScriptCore/bytecode/JumpTable.h \
 106 Source/JavaScriptCore/bytecode/LLIntCallLinkInfo.h \
105107 Source/JavaScriptCore/bytecode/LineInfo.h \
106108 Source/JavaScriptCore/bytecode/MethodCallLinkInfo.cpp \
107109 Source/JavaScriptCore/bytecode/MethodCallLinkInfo.h \

@@javascriptcore_sources += \
285287 Source/JavaScriptCore/jit/CompactJITCodeMap.h \
286288 Source/JavaScriptCore/jit/ExecutableAllocator.cpp \
287289 Source/JavaScriptCore/jit/ExecutableAllocator.h \
 290 Source/JavaScriptCore/jit/HostCallReturnValue.cpp \
 291 Source/JavaScriptCore/jit/HostCallReturnValue.h \
288292 Source/JavaScriptCore/jit/JITArithmetic32_64.cpp \
289293 Source/JavaScriptCore/jit/JITArithmetic.cpp \
290294 Source/JavaScriptCore/jit/JITCall32_64.cpp \

@@javascriptcore_sources += \
308312 Source/JavaScriptCore/jit/SpecializedThunkJIT.h \
309313 Source/JavaScriptCore/jit/ThunkGenerators.cpp \
310314 Source/JavaScriptCore/jit/ThunkGenerators.h \
 315 Source/JavaScriptCore/llint/LLIntData.h \
311316 Source/JavaScriptCore/os-win32/stdbool.h \
312317 Source/JavaScriptCore/os-win32/stdint.h \
313318 Source/JavaScriptCore/parser/ASTBuilder.h \

@@javascriptcore_sources += \
358363 Source/JavaScriptCore/runtime/CallData.cpp \
359364 Source/JavaScriptCore/runtime/CallData.h \
360365 Source/JavaScriptCore/runtime/ClassInfo.h \
 366 Source/JavaScriptCore/runtime/CodeSpecializationKind.h \
361367 Source/JavaScriptCore/runtime/CommonIdentifiers.cpp \
362368 Source/JavaScriptCore/runtime/CommonIdentifiers.h \
363369 Source/JavaScriptCore/runtime/CommonSlowPaths.h \

@@javascriptcore_sources += \
386392 Source/JavaScriptCore/runtime/ExceptionHelpers.h \
387393 Source/JavaScriptCore/runtime/Executable.cpp \
388394 Source/JavaScriptCore/runtime/Executable.h \
 395 Source/JavaScriptCore/runtime/ExecutionHarness.h \
389396 Source/JavaScriptCore/runtime/FunctionConstructor.cpp \
390397 Source/JavaScriptCore/runtime/FunctionConstructor.h \
391398 Source/JavaScriptCore/runtime/FunctionPrototype.cpp \
107713

Source/JavaScriptCore/JavaScriptCore.pri

@@INCLUDEPATH += \
2020 $$SOURCE_DIR/debugger \
2121 $$SOURCE_DIR/interpreter \
2222 $$SOURCE_DIR/jit \
 23 $$SOURCE_DIR/llint \
2324 $$SOURCE_DIR/parser \
2425 $$SOURCE_DIR/profiler \
2526 $$SOURCE_DIR/runtime \
107713

Source/JavaScriptCore/Target.pri

@@SOURCES += \
108108 interpreter/RegisterFile.cpp \
109109 jit/ExecutableAllocatorFixedVMPool.cpp \
110110 jit/ExecutableAllocator.cpp \
 111 jit/HostCallReturnValue.cpp \
111112 jit/JITArithmetic.cpp \
112113 jit/JITArithmetic32_64.cpp \
113114 jit/JITCall.cpp \
107713

Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj

17621762 >
17631763 </File>
17641764 <File
 1765 RelativePath="..\..\jit\HostCallReturnValue.cpp"
 1766 >
 1767 </File>
 1768 <File
17651769 RelativePath="..\..\jit\JIT.cpp"
17661770 >
17671771 </File>

18471851 </File>
18481852 </Filter>
18491853 <Filter
 1854 Name="llint"
 1855 >
 1856 <File
 1857 RelativePath="..\..\llint\LLIntData.h"
 1858 >
 1859 </File>
 1860 </Filter>
 1861 <Filter
18501862 Name="interpreter"
18511863 >
18521864 <File
107713

Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops

66 >
77 <Tool
88 Name="VCCLCompilerTool"
9  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;"
 9 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;"
1010 PreprocessorDefinitions="__STD_C"
1111 ForcedIncludeFiles="ICUVersion.h"
1212 />
107713

Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd

@@for %%d in (
4343 debugger
4444 interpreter
4545 jit
 46 llint
4647 parser
4748 profiler
4849 runtime
107713

Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

77 objects = {
88
99/* Begin PBXAggregateTarget section */
 10 0F4680A914BA7FD900BFE272 /* LLInt Offsets */ = {
 11 isa = PBXAggregateTarget;
 12 buildConfigurationList = 0F4680AC14BA7FD900BFE272 /* Build configuration list for PBXAggregateTarget "LLInt Offsets" */;
 13 buildPhases = (
 14 0F4680AA14BA7FD900BFE272 /* Generate Derived Sources */,
 15 );
 16 name = "LLInt Offsets";
 17 productName = "Derived Sources";
 18 };
1019 65FB3F6609D11E9100F49DEB /* Derived Sources */ = {
1120 isa = PBXAggregateTarget;
1221 buildConfigurationList = 65FB3F7709D11EBD00F49DEB /* Build configuration list for PBXAggregateTarget "Derived Sources" */;

1423 65FB3F6509D11E9100F49DEB /* Generate Derived Sources */,
1524 5D35DEE10C7C140B008648B2 /* Generate DTrace header */,
1625 );
 26 dependencies = (
 27 0F4680B414BA821400BFE272 /* PBXTargetDependency */,
 28 );
1729 name = "Derived Sources";
1830 productName = "Derived Sources";
1931 };

4860 0BAC94A01338728400CF135B /* ThreadRestrictionVerifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BAC949E1338728400CF135B /* ThreadRestrictionVerifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
4961 0BCD83571485845200EA2003 /* TemporaryChange.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BCD83541485841200EA2003 /* TemporaryChange.h */; settings = {ATTRIBUTES = (Private, ); }; };
5062 0BF28A2911A33DC300638F84 /* SizeLimits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0BF28A2811A33DC300638F84 /* SizeLimits.cpp */; };
 63 0F0B839A14BCF45D00885B4F /* LLIntEntrypoints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839514BCF45A00885B4F /* LLIntEntrypoints.cpp */; };
 64 0F0B839B14BCF46000885B4F /* LLIntEntrypoints.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B839614BCF45A00885B4F /* LLIntEntrypoints.h */; settings = {ATTRIBUTES = (Private, ); }; };
 65 0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */; };
 66 0F0B839D14BCF46600885B4F /* LLIntThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B839814BCF45A00885B4F /* LLIntThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
5167 0F0B83A714BCF50700885B4F /* CodeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83A514BCF50400885B4F /* CodeType.h */; settings = {ATTRIBUTES = (Private, ); }; };
5268 0F0B83A914BCF56200885B4F /* HandlerInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83A814BCF55E00885B4F /* HandlerInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
5369 0F0B83AB14BCF5BB00885B4F /* ExpressionRangeInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83AA14BCF5B900885B4F /* ExpressionRangeInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };

5874 0F0B83B514BCF86200885B4F /* MethodCallLinkInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83B314BCF85E00885B4F /* MethodCallLinkInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
5975 0F0B83B714BCF8E100885B4F /* GlobalResolveInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83B614BCF8DF00885B4F /* GlobalResolveInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
6076 0F0B83B914BCF95F00885B4F /* CallReturnOffsetToBytecodeOffset.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */; settings = {ATTRIBUTES = (Private, ); }; };
 77 0F0FC45A14BD15F500B81154 /* LLIntCallLinkInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
6178 0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */; settings = {ATTRIBUTES = (Private, ); }; };
6279 0F16D726142C39C000CF784A /* BitVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F16D724142C39A200CF784A /* BitVector.cpp */; };
6380 0F21C26814BE5F6800ADC64B /* JITDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C26614BE5F5E00ADC64B /* JITDriver.h */; settings = {ATTRIBUTES = (Private, ); }; };
 81 0F21C27C14BE727600ADC64B /* ExecutionHarness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27A14BE727300ADC64B /* ExecutionHarness.h */; settings = {ATTRIBUTES = (Private, ); }; };
 82 0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */; settings = {ATTRIBUTES = (Private, ); }; };
 83 0F21C27F14BEAA8200ADC64B /* BytecodeConventions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */; settings = {ATTRIBUTES = (Private, ); }; };
6484 0F242DA713F3B1E8007ADD4C /* WeakReferenceHarvester.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */; settings = {ATTRIBUTES = (Private, ); }; };
6585 0F2C556F14738F3100121E4F /* DFGCodeBlocks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */; settings = {ATTRIBUTES = (Private, ); }; };
6686 0F2C557014738F3500121E4F /* DFGCodeBlocks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */; };

7191 0F431738146BAC69007E3890 /* ListableHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F431736146BAC65007E3890 /* ListableHandler.h */; settings = {ATTRIBUTES = (Private, ); }; };
7292 0F46808214BA572D00BFE272 /* JITExceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F46808014BA572700BFE272 /* JITExceptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
7393 0F46808314BA573100BFE272 /* JITExceptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F46807F14BA572700BFE272 /* JITExceptions.cpp */; };
 94 0F4680A314BA7F8D00BFE272 /* LLIntExceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F46809E14BA7F8200BFE272 /* LLIntExceptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
 95 0F4680A414BA7F8D00BFE272 /* LLIntHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F46809F14BA7F8200BFE272 /* LLIntHelpers.cpp */; settings = {COMPILER_FLAGS = "-Wno-unused-parameter"; }; };
 96 0F4680A514BA7F8D00BFE272 /* LLIntHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680A014BA7F8200BFE272 /* LLIntHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; };
 97 0F4680A714BA7FA100BFE272 /* LLIntOffsetsExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */; };
 98 0F4680A814BA7FAB00BFE272 /* LLIntExceptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F46809D14BA7F8200BFE272 /* LLIntExceptions.cpp */; };
 99 0F4680CA14BBB16C00BFE272 /* LLIntCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680C514BBB16900BFE272 /* LLIntCommon.h */; settings = {ATTRIBUTES = (Private, ); }; };
 100 0F4680CB14BBB17200BFE272 /* LLIntOfflineAsmConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680C614BBB16900BFE272 /* LLIntOfflineAsmConfig.h */; settings = {ATTRIBUTES = (Private, ); }; };
 101 0F4680CC14BBB17A00BFE272 /* LowLevelInterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680C714BBB16900BFE272 /* LowLevelInterpreter.cpp */; };
 102 0F4680CD14BBB17D00BFE272 /* LowLevelInterpreter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680C814BBB16900BFE272 /* LowLevelInterpreter.h */; settings = {ATTRIBUTES = (Private, ); }; };
 103 0F4680D214BBD16500BFE272 /* LLIntData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680CE14BBB3D100BFE272 /* LLIntData.cpp */; };
 104 0F4680D314BBD16700BFE272 /* LLIntData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680CF14BBB3D100BFE272 /* LLIntData.h */; settings = {ATTRIBUTES = (Private, ); }; };
 105 0F4680D414BBD24900BFE272 /* HostCallReturnValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */; };
 106 0F4680D514BBD24B00BFE272 /* HostCallReturnValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
74107 0F55F0F414D1063900AC7649 /* AbstractPC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F55F0F114D1063600AC7649 /* AbstractPC.cpp */; };
75108 0F55F0F514D1063C00AC7649 /* AbstractPC.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F55F0F214D1063600AC7649 /* AbstractPC.h */; settings = {ATTRIBUTES = (Private, ); }; };
76109 0F5F08CF146C7633000472A9 /* UnconditionalFinalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */; settings = {ATTRIBUTES = (Private, ); }; };

408441 86B99AE3117E578100DF5A90 /* StringBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86B99AE1117E578100DF5A90 /* StringBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
409442 86BB09C0138E381B0056702F /* DFGRepatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86BB09BE138E381B0056702F /* DFGRepatch.cpp */; };
410443 86BB09C1138E381B0056702F /* DFGRepatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 86BB09BF138E381B0056702F /* DFGRepatch.h */; };
411  86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */; };
 444 86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
412445 86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86C568DD11A213EE0007F7F0 /* MacroAssemblerARM.cpp */; };
413446 86C568E111A213EE0007F7F0 /* MacroAssemblerMIPS.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C568DE11A213EE0007F7F0 /* MacroAssemblerMIPS.h */; };
414447 86C568E211A213EE0007F7F0 /* MIPSAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C568DF11A213EE0007F7F0 /* MIPSAssembler.h */; };

778811/* End PBXBuildFile section */
779812
780813/* Begin PBXContainerItemProxy section */
 814 0F4680B114BA811500BFE272 /* PBXContainerItemProxy */ = {
 815 isa = PBXContainerItemProxy;
 816 containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
 817 proxyType = 1;
 818 remoteGlobalIDString = 0F4680A914BA7FD900BFE272;
 819 remoteInfo = "LLInt Offsets";
 820 };
 821 0F4680B314BA821400BFE272 /* PBXContainerItemProxy */ = {
 822 isa = PBXContainerItemProxy;
 823 containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
 824 proxyType = 1;
 825 remoteGlobalIDString = 0F46808E14BA7E5E00BFE272;
 826 remoteInfo = JSCLLIntOffsetsExtractor;
 827 };
781828 141214BE0A49190E00480255 /* PBXContainerItemProxy */ = {
782829 isa = PBXContainerItemProxy;
783830 containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;

823870/* End PBXContainerItemProxy section */
824871
825872/* Begin PBXCopyFilesBuildPhase section */
 873 0F46808D14BA7E5E00BFE272 /* CopyFiles */ = {
 874 isa = PBXCopyFilesBuildPhase;
 875 buildActionMask = 2147483647;
 876 dstPath = /usr/share/man/man1/;
 877 dstSubfolderSpec = 0;
 878 files = (
 879 );
 880 runOnlyForDeploymentPostprocessing = 1;
 881 };
826882 5DBB1511131D0B130056AD36 /* Copy Support Script */ = {
827883 isa = PBXCopyFilesBuildPhase;
828884 buildActionMask = 12;

863919 0BAC949E1338728400CF135B /* ThreadRestrictionVerifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadRestrictionVerifier.h; sourceTree = "<group>"; };
864920 0BCD83541485841200EA2003 /* TemporaryChange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemporaryChange.h; sourceTree = "<group>"; };
865921 0BF28A2811A33DC300638F84 /* SizeLimits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SizeLimits.cpp; sourceTree = "<group>"; };
 922 0F0B839514BCF45A00885B4F /* LLIntEntrypoints.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntEntrypoints.cpp; path = llint/LLIntEntrypoints.cpp; sourceTree = "<group>"; };
 923 0F0B839614BCF45A00885B4F /* LLIntEntrypoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntEntrypoints.h; path = llint/LLIntEntrypoints.h; sourceTree = "<group>"; };
 924 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; };
 925 0F0B839814BCF45A00885B4F /* LLIntThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntThunks.h; path = llint/LLIntThunks.h; sourceTree = "<group>"; };
866926 0F0B83A514BCF50400885B4F /* CodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeType.h; sourceTree = "<group>"; };
867927 0F0B83A814BCF55E00885B4F /* HandlerInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HandlerInfo.h; sourceTree = "<group>"; };
868928 0F0B83AA14BCF5B900885B4F /* ExpressionRangeInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExpressionRangeInfo.h; sourceTree = "<group>"; };

873933 0F0B83B314BCF85E00885B4F /* MethodCallLinkInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MethodCallLinkInfo.h; sourceTree = "<group>"; };
874934 0F0B83B614BCF8DF00885B4F /* GlobalResolveInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GlobalResolveInfo.h; sourceTree = "<group>"; };
875935 0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallReturnOffsetToBytecodeOffset.h; sourceTree = "<group>"; };
 936 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLIntCallLinkInfo.h; sourceTree = "<group>"; };
876937 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonSlowPaths.h; sourceTree = "<group>"; };
877938 0F16D724142C39A200CF784A /* BitVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BitVector.cpp; sourceTree = "<group>"; };
878939 0F21C26614BE5F5E00ADC64B /* JITDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITDriver.h; sourceTree = "<group>"; };
 940 0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeSpecializationKind.h; sourceTree = "<group>"; };
 941 0F21C27A14BE727300ADC64B /* ExecutionHarness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutionHarness.h; sourceTree = "<group>"; };
 942 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeConventions.h; sourceTree = "<group>"; };
879943 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakReferenceHarvester.h; sourceTree = "<group>"; };
880944 0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DFGCodeBlocks.cpp; sourceTree = "<group>"; };
881945 0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFGCodeBlocks.h; sourceTree = "<group>"; };

886950 0F431736146BAC65007E3890 /* ListableHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ListableHandler.h; sourceTree = "<group>"; };
887951 0F46807F14BA572700BFE272 /* JITExceptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITExceptions.cpp; sourceTree = "<group>"; };
888952 0F46808014BA572700BFE272 /* JITExceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITExceptions.h; sourceTree = "<group>"; };
 953 0F46808F14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; };
 954 0F46809D14BA7F8200BFE272 /* LLIntExceptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntExceptions.cpp; path = llint/LLIntExceptions.cpp; sourceTree = "<group>"; };
 955 0F46809E14BA7F8200BFE272 /* LLIntExceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntExceptions.h; path = llint/LLIntExceptions.h; sourceTree = "<group>"; };
 956 0F46809F14BA7F8200BFE272 /* LLIntHelpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntHelpers.cpp; path = llint/LLIntHelpers.cpp; sourceTree = "<group>"; };
 957 0F4680A014BA7F8200BFE272 /* LLIntHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntHelpers.h; path = llint/LLIntHelpers.h; sourceTree = "<group>"; };
 958 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntOffsetsExtractor.cpp; path = llint/LLIntOffsetsExtractor.cpp; sourceTree = "<group>"; };
 959 0F4680C514BBB16900BFE272 /* LLIntCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntCommon.h; path = llint/LLIntCommon.h; sourceTree = "<group>"; };
 960 0F4680C614BBB16900BFE272 /* LLIntOfflineAsmConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntOfflineAsmConfig.h; path = llint/LLIntOfflineAsmConfig.h; sourceTree = "<group>"; };
 961 0F4680C714BBB16900BFE272 /* LowLevelInterpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LowLevelInterpreter.cpp; path = llint/LowLevelInterpreter.cpp; sourceTree = "<group>"; };
 962 0F4680C814BBB16900BFE272 /* LowLevelInterpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LowLevelInterpreter.h; path = llint/LowLevelInterpreter.h; sourceTree = "<group>"; };
 963 0F4680CE14BBB3D100BFE272 /* LLIntData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntData.cpp; path = llint/LLIntData.cpp; sourceTree = "<group>"; };
 964 0F4680CF14BBB3D100BFE272 /* LLIntData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntData.h; path = llint/LLIntData.h; sourceTree = "<group>"; };
 965 0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HostCallReturnValue.cpp; sourceTree = "<group>"; };
 966 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HostCallReturnValue.h; sourceTree = "<group>"; };
889967 0F55F0F114D1063600AC7649 /* AbstractPC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AbstractPC.cpp; sourceTree = "<group>"; };
890968 0F55F0F214D1063600AC7649 /* AbstractPC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbstractPC.h; sourceTree = "<group>"; };
891969 0F5F08CC146BE602000472A9 /* DFGByteCodeCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGByteCodeCache.h; path = dfg/DFGByteCodeCache.h; sourceTree = "<group>"; };

16321710/* End PBXFileReference section */
16331711
16341712/* Begin PBXFrameworksBuildPhase section */
 1713 0F46808C14BA7E5E00BFE272 /* Frameworks */ = {
 1714 isa = PBXFrameworksBuildPhase;
 1715 buildActionMask = 2147483647;
 1716 files = (
 1717 );
 1718 runOnlyForDeploymentPostprocessing = 0;
 1719 };
16351720 1412111E0A48793C00480255 /* Frameworks */ = {
16361721 isa = PBXFrameworksBuildPhase;
16371722 buildActionMask = 2147483647;

16901775 141211200A48793C00480255 /* minidom */,
16911776 14BD59BF0A3E8F9000BAF59C /* testapi */,
16921777 6511230514046A4C002B101D /* testRegExp */,
 1778 0F46808F14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */,
16931779 );
16941780 name = Products;
16951781 sourceTree = "<group>";

17151801 F5C290E60284F98E018635CA /* JavaScriptCorePrefix.h */,
17161802 45E12D8806A49B0F00E9DF84 /* jsc.cpp */,
17171803 F68EBB8C0255D4C601FF60F7 /* config.h */,
 1804 0F46809C14BA7F4D00BFE272 /* llint */,
17181805 1432EBD70A34CAD400717B9F /* API */,
17191806 9688CB120ED12B4E001D649F /* assembler */,
17201807 969A078F0ED1D3AE00F1F681 /* bytecode */,

17541841 tabWidth = 4;
17551842 usesTabs = 0;
17561843 };
 1844 0F46809C14BA7F4D00BFE272 /* llint */ = {
 1845 isa = PBXGroup;
 1846 children = (
 1847 0F0B839514BCF45A00885B4F /* LLIntEntrypoints.cpp */,
 1848 0F0B839614BCF45A00885B4F /* LLIntEntrypoints.h */,
 1849 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */,
 1850 0F0B839814BCF45A00885B4F /* LLIntThunks.h */,
 1851 0F4680CE14BBB3D100BFE272 /* LLIntData.cpp */,
 1852 0F4680CF14BBB3D100BFE272 /* LLIntData.h */,
 1853 0F4680C514BBB16900BFE272 /* LLIntCommon.h */,
 1854 0F4680C614BBB16900BFE272 /* LLIntOfflineAsmConfig.h */,
 1855 0F4680C714BBB16900BFE272 /* LowLevelInterpreter.cpp */,
 1856 0F4680C814BBB16900BFE272 /* LowLevelInterpreter.h */,
 1857 0F46809D14BA7F8200BFE272 /* LLIntExceptions.cpp */,
 1858 0F46809E14BA7F8200BFE272 /* LLIntExceptions.h */,
 1859 0F46809F14BA7F8200BFE272 /* LLIntHelpers.cpp */,
 1860 0F4680A014BA7F8200BFE272 /* LLIntHelpers.h */,
 1861 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */,
 1862 );
 1863 name = llint;
 1864 sourceTree = "<group>";
 1865 };
17571866 141211000A48772600480255 /* tests */ = {
17581867 isa = PBXGroup;
17591868 children = (

17881897 1429D92C0ED22D7000B89619 /* jit */ = {
17891898 isa = PBXGroup;
17901899 children = (
 1900 0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */,
 1901 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */,
17911902 0F46807F14BA572700BFE272 /* JITExceptions.cpp */,
17921903 0F46808014BA572700BFE272 /* JITExceptions.h */,
17931904 0FD82E37141AB14200179C94 /* CompactJITCodeMap.h */,

22602371 7EF6E0BB0EB7A1EC0079AFAF /* runtime */ = {
22612372 isa = PBXGroup;
22622373 children = (
 2374 0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */,
 2375 0F21C27A14BE727300ADC64B /* ExecutionHarness.h */,
22632376 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */,
22642377 BCF605110E203EF800B9A64D /* ArgList.cpp */,
22652378 BCF605120E203EF800B9A64D /* ArgList.h */,

26342747 969A078F0ED1D3AE00F1F681 /* bytecode */ = {
26352748 isa = PBXGroup;
26362749 children = (
 2750 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */,
 2751 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */,
26372752 0F9FC8BF14E1B5FB00D52AE0 /* PolymorphicPutByIdList.cpp */,
26382753 0F9FC8C014E1B5FB00D52AE0 /* PolymorphicPutByIdList.h */,
26392754 0F9FC8C114E1B5FB00D52AE0 /* PutKind.h */,

31983313 86704B8A12DBA33700A9FE7B /* YarrPattern.h in Headers */,
31993314 86704B4312DB8A8100A9FE7B /* YarrSyntaxChecker.h in Headers */,
32003315 0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */,
 3316 0F4680A314BA7F8D00BFE272 /* LLIntExceptions.h in Headers */,
 3317 0F4680A514BA7F8D00BFE272 /* LLIntHelpers.h in Headers */,
32013318 0F46808214BA572D00BFE272 /* JITExceptions.h in Headers */,
 3319 0F4680CA14BBB16C00BFE272 /* LLIntCommon.h in Headers */,
 3320 0F4680CB14BBB17200BFE272 /* LLIntOfflineAsmConfig.h in Headers */,
 3321 0F4680CD14BBB17D00BFE272 /* LowLevelInterpreter.h in Headers */,
 3322 0F4680D314BBD16700BFE272 /* LLIntData.h in Headers */,
 3323 0F4680D514BBD24B00BFE272 /* HostCallReturnValue.h in Headers */,
 3324 0F0B839B14BCF46000885B4F /* LLIntEntrypoints.h in Headers */,
 3325 0F0B839D14BCF46600885B4F /* LLIntThunks.h in Headers */,
32023326 0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
32033327 0F0B83A914BCF56200885B4F /* HandlerInfo.h in Headers */,
32043328 0F0B83AB14BCF5BB00885B4F /* ExpressionRangeInfo.h in Headers */,

32073331 0F0B83B514BCF86200885B4F /* MethodCallLinkInfo.h in Headers */,
32083332 0F0B83B714BCF8E100885B4F /* GlobalResolveInfo.h in Headers */,
32093333 0F0B83B914BCF95F00885B4F /* CallReturnOffsetToBytecodeOffset.h in Headers */,
 3334 0F0FC45A14BD15F500B81154 /* LLIntCallLinkInfo.h in Headers */,
32103335 0F21C26814BE5F6800ADC64B /* JITDriver.h in Headers */,
 3336 0F21C27C14BE727600ADC64B /* ExecutionHarness.h in Headers */,
 3337 0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
 3338 0F21C27F14BEAA8200ADC64B /* BytecodeConventions.h in Headers */,
32113339 0F7B294A14C3CD29007C3DB1 /* DFGCCallHelpers.h in Headers */,
32123340 0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */,
32133341 0F7B294C14C3CD43007C3DB1 /* DFGByteCodeCache.h in Headers */,

32323360/* End PBXHeadersBuildPhase section */
32333361
32343362/* Begin PBXNativeTarget section */
 3363 0F46808E14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */ = {
 3364 isa = PBXNativeTarget;
 3365 buildConfigurationList = 0F46809A14BA7E5F00BFE272 /* Build configuration list for PBXNativeTarget "JSCLLIntOffsetsExtractor" */;
 3366 buildPhases = (
 3367 0F46808B14BA7E5E00BFE272 /* Sources */,
 3368 0F46808C14BA7E5E00BFE272 /* Frameworks */,
 3369 0F46808D14BA7E5E00BFE272 /* CopyFiles */,
 3370 );
 3371 buildRules = (
 3372 );
 3373 dependencies = (
 3374 0F4680B214BA811500BFE272 /* PBXTargetDependency */,
 3375 );
 3376 name = JSCLLIntOffsetsExtractor;
 3377 productName = JSCLLIntOffsetsExtractor;
 3378 productReference = 0F46808F14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */;
 3379 productType = "com.apple.product-type.tool";
 3380 };
32353381 1412111F0A48793C00480255 /* minidom */ = {
32363382 isa = PBXNativeTarget;
32373383 buildConfigurationList = 141211390A48798400480255 /* Build configuration list for PBXNativeTarget "minidom" */;

33583504 14BD59BE0A3E8F9000BAF59C /* testapi */,
33593505 932F5BDA0822A1C700736975 /* jsc */,
33603506 651122F714046A4C002B101D /* testRegExp */,
 3507 0F46808E14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */,
 3508 0F4680A914BA7FD900BFE272 /* LLInt Offsets */,
33613509 );
33623510 };
33633511/* End PBXProject section */
33643512
33653513/* Begin PBXShellScriptBuildPhase section */
 3514 0F4680AA14BA7FD900BFE272 /* Generate Derived Sources */ = {
 3515 isa = PBXShellScriptBuildPhase;
 3516 buildActionMask = 2147483647;
 3517 files = (
 3518 );
 3519 inputPaths = (
 3520 "$(SRCROOT)/llint/LowLevelAssembler.asm",
 3521 );
 3522 name = "Generate Derived Sources";
 3523 outputPaths = (
 3524 "$(BUILT_PRODUCTS_DIR)/LLIntOffsets/LLIntDesiredOffsets.h",
 3525 );
 3526 runOnlyForDeploymentPostprocessing = 0;
 3527 shellPath = /bin/sh;
 3528 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";
 3529 };
33663530 3713F014142905240036387F /* Check For Inappropriate Objective-C Class Names */ = {
33673531 isa = PBXShellScriptBuildPhase;
33683532 buildActionMask = 2147483647;

34683632 );
34693633 runOnlyForDeploymentPostprocessing = 0;
34703634 shellPath = /bin/sh;
3471  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";
 3635 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";
34723636 };
34733637 9319586B09D9F91A00A56FD4 /* Check For Global Initializers */ = {
34743638 isa = PBXShellScriptBuildPhase;

35033667/* End PBXShellScriptBuildPhase section */
35043668
35053669/* Begin PBXSourcesBuildPhase section */
 3670 0F46808B14BA7E5E00BFE272 /* Sources */ = {
 3671 isa = PBXSourcesBuildPhase;
 3672 buildActionMask = 2147483647;
 3673 files = (
 3674 0F4680A714BA7FA100BFE272 /* LLIntOffsetsExtractor.cpp in Sources */,
 3675 );
 3676 runOnlyForDeploymentPostprocessing = 0;
 3677 };
35063678 1412111D0A48793C00480255 /* Sources */ = {
35073679 isa = PBXSourcesBuildPhase;
35083680 buildActionMask = 2147483647;

37643936 86704B8612DBA33700A9FE7B /* YarrJIT.cpp in Sources */,
37653937 86704B8912DBA33700A9FE7B /* YarrPattern.cpp in Sources */,
37663938 86704B4212DB8A8100A9FE7B /* YarrSyntaxChecker.cpp in Sources */,
 3939 0F4680A414BA7F8D00BFE272 /* LLIntHelpers.cpp in Sources */,
 3940 0F4680A814BA7FAB00BFE272 /* LLIntExceptions.cpp in Sources */,
37673941 0F46808314BA573100BFE272 /* JITExceptions.cpp in Sources */,
 3942 0F4680CC14BBB17A00BFE272 /* LowLevelInterpreter.cpp in Sources */,
 3943 0F4680D214BBD16500BFE272 /* LLIntData.cpp in Sources */,
 3944 0F4680D414BBD24900BFE272 /* HostCallReturnValue.cpp in Sources */,
 3945 0F0B839A14BCF45D00885B4F /* LLIntEntrypoints.cpp in Sources */,
 3946 0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */,
37683947 0F0B83B014BCF71600885B4F /* CallLinkInfo.cpp in Sources */,
37693948 0F0B83B414BCF86000885B4F /* MethodCallLinkInfo.cpp in Sources */,
37703949 F69E86C314C6E551002C2C62 /* NumberOfCores.cpp in Sources */,

37923971/* End PBXSourcesBuildPhase section */
37933972
37943973/* Begin PBXTargetDependency section */
 3974 0F4680B214BA811500BFE272 /* PBXTargetDependency */ = {
 3975 isa = PBXTargetDependency;
 3976 target = 0F4680A914BA7FD900BFE272 /* LLInt Offsets */;
 3977 targetProxy = 0F4680B114BA811500BFE272 /* PBXContainerItemProxy */;
 3978 };
 3979 0F4680B414BA821400BFE272 /* PBXTargetDependency */ = {
 3980 isa = PBXTargetDependency;
 3981 target = 0F46808E14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */;
 3982 targetProxy = 0F4680B314BA821400BFE272 /* PBXContainerItemProxy */;
 3983 };
37953984 141214BF0A49190E00480255 /* PBXTargetDependency */ = {
37963985 isa = PBXTargetDependency;
37973986 target = 1412111F0A48793C00480255 /* minidom */;

38254014/* End PBXTargetDependency section */
38264015
38274016/* Begin XCBuildConfiguration section */
 4017 0F46809614BA7E5E00BFE272 /* Debug */ = {
 4018 isa = XCBuildConfiguration;
 4019 buildSettings = {
 4020 ALWAYS_SEARCH_USER_PATHS = NO;
 4021 ARCHS = "$(ARCHS_STANDARD_64_BIT)";
 4022 COPY_PHASE_STRIP = NO;
 4023 GCC_C_LANGUAGE_STANDARD = gnu99;
 4024 GCC_DYNAMIC_NO_PIC = NO;
 4025 GCC_ENABLE_OBJC_EXCEPTIONS = YES;
 4026 GCC_OPTIMIZATION_LEVEL = 0;
 4027 GCC_PREPROCESSOR_DEFINITIONS = (
 4028 "DEBUG=1",
 4029 "$(inherited)",
 4030 );
 4031 GCC_SYMBOLS_PRIVATE_EXTERN = NO;
 4032 GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
 4033 GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
 4034 GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
 4035 GCC_WARN_ABOUT_RETURN_TYPE = YES;
 4036 GCC_WARN_UNUSED_VARIABLE = YES;
 4037 "HEADER_SEARCH_PATHS[arch=*]" = (
 4038 .,
 4039 icu,
 4040 "$(BUILT_PRODUCTS_DIR)/LLIntOffsets",
 4041 "$(HEADER_SEARCH_PATHS)",
 4042 );
 4043 MACOSX_DEPLOYMENT_TARGET = 10.7;
 4044 ONLY_ACTIVE_ARCH = NO;
 4045 PRODUCT_NAME = "$(TARGET_NAME)";
 4046 SDKROOT = macosx;
 4047 USER_HEADER_SEARCH_PATHS = ". icu $(BUILT_PRODUCTS_DIR)/LLIntOffsets $(HEADER_SEARCH_PATHS)";
 4048 };
 4049 name = Debug;
 4050 };
 4051 0F46809714BA7E5E00BFE272 /* Release */ = {
 4052 isa = XCBuildConfiguration;
 4053 buildSettings = {
 4054 ALWAYS_SEARCH_USER_PATHS = NO;
 4055 ARCHS = "$(ARCHS_STANDARD_64_BIT)";
 4056 COPY_PHASE_STRIP = YES;
 4057 DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 4058 GCC_C_LANGUAGE_STANDARD = gnu99;
 4059 GCC_ENABLE_OBJC_EXCEPTIONS = YES;
 4060 GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
 4061 GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
 4062 GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
 4063 GCC_WARN_ABOUT_RETURN_TYPE = YES;
 4064 GCC_WARN_UNUSED_VARIABLE = YES;
 4065 "HEADER_SEARCH_PATHS[arch=*]" = (
 4066 .,
 4067 icu,
 4068 "$(BUILT_PRODUCTS_DIR)/LLIntOffsets$(HEADER_SEARCH_PATHS)",
 4069 );
 4070 MACOSX_DEPLOYMENT_TARGET = 10.7;
 4071 ONLY_ACTIVE_ARCH = NO;
 4072 PRODUCT_NAME = "$(TARGET_NAME)";
 4073 SDKROOT = macosx;
 4074 USER_HEADER_SEARCH_PATHS = ". icu $(BUILT_PRODUCTS_DIR)/LLIntOffsets $(HEADER_SEARCH_PATHS)";
 4075 };
 4076 name = Release;
 4077 };
 4078 0F46809814BA7E5E00BFE272 /* Profiling */ = {
 4079 isa = XCBuildConfiguration;
 4080 buildSettings = {
 4081 ALWAYS_SEARCH_USER_PATHS = NO;
 4082 ARCHS = "$(ARCHS_STANDARD_64_BIT)";
 4083 COPY_PHASE_STRIP = YES;
 4084 DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 4085 GCC_C_LANGUAGE_STANDARD = gnu99;
 4086 GCC_ENABLE_OBJC_EXCEPTIONS = YES;
 4087 GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
 4088 GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
 4089 GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
 4090 GCC_WARN_ABOUT_RETURN_TYPE = YES;
 4091 GCC_WARN_UNUSED_VARIABLE = YES;
 4092 "HEADER_SEARCH_PATHS[arch=*]" = (
 4093 .,
 4094 icu,
 4095 "$(BUILT_PRODUCTS_DIR)/LLIntOffsets",
 4096 "$(HEADER_SEARCH_PATHS)",
 4097 );
 4098 MACOSX_DEPLOYMENT_TARGET = 10.7;
 4099 ONLY_ACTIVE_ARCH = NO;
 4100 PRODUCT_NAME = "$(TARGET_NAME)";
 4101 SDKROOT = macosx;
 4102 USER_HEADER_SEARCH_PATHS = ". icu $(BUILT_PRODUCTS_DIR)/LLIntOffsets $(HEADER_SEARCH_PATHS)";
 4103 };
 4104 name = Profiling;
 4105 };
 4106 0F46809914BA7E5E00BFE272 /* Production */ = {
 4107 isa = XCBuildConfiguration;
 4108 buildSettings = {
 4109 ALWAYS_SEARCH_USER_PATHS = NO;
 4110 ARCHS = "$(ARCHS_STANDARD_64_BIT)";
 4111 COPY_PHASE_STRIP = YES;
 4112 DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 4113 GCC_C_LANGUAGE_STANDARD = gnu99;
 4114 GCC_ENABLE_OBJC_EXCEPTIONS = YES;
 4115 GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
 4116 GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
 4117 GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
 4118 GCC_WARN_ABOUT_RETURN_TYPE = YES;
 4119 GCC_WARN_UNUSED_VARIABLE = YES;
 4120 "HEADER_SEARCH_PATHS[arch=*]" = (
 4121 .,
 4122 icu,
 4123 "$(BUILT_PRODUCTS_DIR)/LLIntOffsets",
 4124 "$(HEADER_SEARCH_PATHS)",
 4125 );
 4126 MACOSX_DEPLOYMENT_TARGET = 10.7;
 4127 PRODUCT_NAME = "$(TARGET_NAME)";
 4128 SDKROOT = macosx;
 4129 USER_HEADER_SEARCH_PATHS = ". icu $(BUILT_PRODUCTS_DIR)/LLIntOffsets $(HEADER_SEARCH_PATHS)";
 4130 };
 4131 name = Production;
 4132 };
 4133 0F4680AD14BA7FD900BFE272 /* Debug */ = {
 4134 isa = XCBuildConfiguration;
 4135 buildSettings = {
 4136 PRODUCT_NAME = "Derived Sources copy";
 4137 };
 4138 name = Debug;
 4139 };
 4140 0F4680AE14BA7FD900BFE272 /* Release */ = {
 4141 isa = XCBuildConfiguration;
 4142 buildSettings = {
 4143 PRODUCT_NAME = "Derived Sources copy";
 4144 };
 4145 name = Release;
 4146 };
 4147 0F4680AF14BA7FD900BFE272 /* Profiling */ = {
 4148 isa = XCBuildConfiguration;
 4149 buildSettings = {
 4150 PRODUCT_NAME = "Derived Sources copy";
 4151 };
 4152 name = Profiling;
 4153 };
 4154 0F4680B014BA7FD900BFE272 /* Production */ = {
 4155 isa = XCBuildConfiguration;
 4156 buildSettings = {
 4157 PRODUCT_NAME = "Derived Sources copy";
 4158 };
 4159 name = Production;
 4160 };
38284161 1412113A0A48798400480255 /* Debug */ = {
38294162 isa = XCBuildConfiguration;
38304163 buildSettings = {

40664399/* End XCBuildConfiguration section */
40674400
40684401/* Begin XCConfigurationList section */
 4402 0F46809A14BA7E5F00BFE272 /* Build configuration list for PBXNativeTarget "JSCLLIntOffsetsExtractor" */ = {
 4403 isa = XCConfigurationList;
 4404 buildConfigurations = (
 4405 0F46809614BA7E5E00BFE272 /* Debug */,
 4406 0F46809714BA7E5E00BFE272 /* Release */,
 4407 0F46809814BA7E5E00BFE272 /* Profiling */,
 4408 0F46809914BA7E5E00BFE272 /* Production */,
 4409 );
 4410 defaultConfigurationIsVisible = 0;
 4411 defaultConfigurationName = Production;
 4412 };
 4413 0F4680AC14BA7FD900BFE272 /* Build configuration list for PBXAggregateTarget "LLInt Offsets" */ = {
 4414 isa = XCConfigurationList;
 4415 buildConfigurations = (
 4416 0F4680AD14BA7FD900BFE272 /* Debug */,
 4417 0F4680AE14BA7FD900BFE272 /* Release */,
 4418 0F4680AF14BA7FD900BFE272 /* Profiling */,
 4419 0F4680B014BA7FD900BFE272 /* Production */,
 4420 );
 4421 defaultConfigurationIsVisible = 0;
 4422 defaultConfigurationName = Production;
 4423 };
40694424 141211390A48798400480255 /* Build configuration list for PBXNativeTarget "minidom" */ = {
40704425 isa = XCConfigurationList;
40714426 buildConfigurations = (
107713

Source/JavaScriptCore/assembler/LinkBuffer.h

3434#define GLOBAL_THUNK_ID reinterpret_cast<void*>(static_cast<intptr_t>(-1))
3535#define REGEXP_CODE_ID reinterpret_cast<void*>(static_cast<intptr_t>(-2))
3636
37 #include <MacroAssembler.h>
 37#include "MacroAssembler.h"
3838#include <wtf/DataLog.h>
3939#include <wtf/Noncopyable.h>
4040
107713

Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h

@@public:
273273 {
274274 ASSERT_VALID_CODE_POINTER(m_value);
275275 }
 276
 277 static MacroAssemblerCodePtr createFromExecutableAddress(void* value)
 278 {
 279 ASSERT_VALID_CODE_POINTER(value);
 280 MacroAssemblerCodePtr result;
 281 result.m_value = value;
 282 return result;
 283 }
276284
277285 explicit MacroAssemblerCodePtr(ReturnAddressPtr ra)
278286 : m_value(ra.value())
107713

Source/JavaScriptCore/bytecode/BytecodeConventions.h

 1/*
 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef BytecodeConventions_h
 27#define BytecodeConventions_h
 28
 29// Register numbers used in bytecode operations have different meaning according to their ranges:
 30// 0x80000000-0xFFFFFFFF Negative indices from the CallFrame pointer are entries in the call frame, see RegisterFile.h.
 31// 0x00000000-0x3FFFFFFF Forwards indices from the CallFrame pointer are local vars and temporaries with the function's callframe.
 32// 0x40000000-0x7FFFFFFF Positive indices from 0x40000000 specify entries in the constant pool on the CodeBlock.
 33static const int FirstConstantRegisterIndex = 0x40000000;
 34
 35#endif // BytecodeConventions_h
 36
0

Source/JavaScriptCore/bytecode/CallLinkStatus.cpp

2727#include "CallLinkStatus.h"
2828
2929#include "CodeBlock.h"
 30#include "LLIntCallLinkInfo.h"
3031
3132namespace JSC {
3233
 34CallLinkStatus CallLinkStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex)
 35{
 36 UNUSED_PARAM(profiledBlock);
 37 UNUSED_PARAM(bytecodeIndex);
 38#if ENABLE(LLINT)
 39 Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
 40 LLIntCallLinkInfo* callLinkInfo = instruction[4].u.callLinkInfo;
 41
 42 return CallLinkStatus(callLinkInfo->lastSeenCallee.get(), false);
 43#else
 44 return CallLinkStatus(0, false);
 45#endif
 46}
 47
3348CallLinkStatus CallLinkStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex)
3449{
3550 UNUSED_PARAM(profiledBlock);
3651 UNUSED_PARAM(bytecodeIndex);
3752#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
38  return CallLinkStatus(
39  profiledBlock->getCallLinkInfo(bytecodeIndex).lastSeenCallee.get(),
40  profiledBlock->couldTakeSlowCase(bytecodeIndex));
 53 if (!profiledBlock->numberOfCallLinkInfos())
 54 return computeFromLLInt(profiledBlock, bytecodeIndex);
 55
 56 if (profiledBlock->couldTakeSlowCase(bytecodeIndex))
 57 return CallLinkStatus(0, true);
 58
 59 JSFunction* target = profiledBlock->getCallLinkInfo(bytecodeIndex).lastSeenCallee.get();
 60 if (!target)
 61 return computeFromLLInt(profiledBlock, bytecodeIndex);
 62
 63 return CallLinkStatus(target, false);
4164#else
4265 return CallLinkStatus(0, false);
4366#endif
107713

Source/JavaScriptCore/bytecode/CallLinkStatus.h

@@public:
4747
4848 static CallLinkStatus computeFor(CodeBlock*, unsigned bytecodeIndex);
4949
50  bool isSet() const { return !!m_callTarget; }
 50 bool isSet() const { return !!m_callTarget || m_couldTakeSlowPath; }
5151
52  bool operator!() const { return !m_callTarget; }
 52 bool operator!() const { return !isSet(); }
5353
5454 bool couldTakeSlowPath() const { return m_couldTakeSlowPath; }
5555
5656 JSFunction* callTarget() const { return m_callTarget; }
5757
5858private:
 59 static CallLinkStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex);
 60
5961 JSFunction* m_callTarget;
6062 bool m_couldTakeSlowPath;
6163};
107713

Source/JavaScriptCore/bytecode/CodeBlock.cpp

4242#include "JSFunction.h"
4343#include "JSStaticScopeObject.h"
4444#include "JSValue.h"
 45#include "LowLevelInterpreter.h"
4546#include "RepatchBuffer.h"
4647#include "UStringConcatenate.h"
4748#include <stdio.h>

@@void CodeBlock::dump(ExecState* exec) co
356357 for (size_t i = 0; i < instructions().size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(instructions()[i].u.opcode)])
357358 ++instructionCount;
358359
359  dataLog("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n",
 360 dataLog("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s); %d variable(s)\n\n",
360361 static_cast<unsigned long>(instructionCount),
361362 static_cast<unsigned long>(instructions().size() * sizeof(Instruction)),
362  this, m_numParameters, m_numCalleeRegisters);
 363 this, m_numParameters, m_numCalleeRegisters, m_numVars);
363364
364365 Vector<Instruction>::const_iterator begin = instructions().begin();
365366 Vector<Instruction>::const_iterator end = instructions().end();

@@void CodeBlock::dump(ExecState* exec, co
896897 printPutByIdOp(exec, location, it, "put_by_id_transition");
897898 break;
898899 }
 900 case op_put_by_id_transition_direct: {
 901 printPutByIdOp(exec, location, it, "put_by_id_transition_direct");
 902 break;
 903 }
 904 case op_put_by_id_transition_normal: {
 905 printPutByIdOp(exec, location, it, "put_by_id_transition_normal");
 906 break;
 907 }
899908 case op_put_by_id_generic: {
900909 printPutByIdOp(exec, location, it, "put_by_id_generic");
901910 break;

@@CodeBlock::CodeBlock(CopyParsedBlockTag,
14531462{
14541463 setNumParameters(other.numParameters());
14551464 optimizeAfterWarmUp();
 1465 jitAfterWarmUp();
14561466
14571467 if (other.m_rareData) {
14581468 createRareDataIfNecessary();

@@CodeBlock::CodeBlock(ScriptExecutable* o
15011511 ASSERT(m_source);
15021512
15031513 optimizeAfterWarmUp();
 1514 jitAfterWarmUp();
15041515
15051516#if DUMP_CODE_BLOCK_STATISTICS
15061517 liveCodeBlockSet.add(this);

@@CodeBlock::~CodeBlock()
15181529#if ENABLE(VERBOSE_VALUE_PROFILE)
15191530 dumpValueProfiles();
15201531#endif
1521 
 1532
 1533#if ENABLE(LLINT)
 1534 while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end())
 1535 m_incomingLLIntCalls.begin()->remove();
 1536#endif // ENABLE(LLINT)
15221537#if ENABLE(JIT)
15231538 // We may be destroyed before any CodeBlocks that refer to us are destroyed.
15241539 // Consider that two CodeBlocks become unreachable at the same time. There

@@void CodeBlock::finalizeUnconditionally(
17301745#else
17311746 static const bool verboseUnlinking = false;
17321747#endif
1733 #endif
 1748#endif // ENABLE(JIT)
17341749
 1750#if ENABLE(LLINT)
 1751 Interpreter* interpreter = m_globalData->interpreter;
 1752 // interpreter->enabled() returns true if the old C++ interpreter is enabled. If that's enabled
 1753 // then we're not using LLInt.
 1754 if (!interpreter->enabled()) {
 1755 for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) {
 1756 Instruction* curInstruction = &instructions()[m_propertyAccessInstructions[i]];
 1757 switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) {
 1758 case op_get_by_id:
 1759 case op_put_by_id:
 1760 if (!curInstruction[4].u.structure || Heap::isMarked(curInstruction[4].u.structure.get()))
 1761 break;
 1762 if (verboseUnlinking)
 1763 dataLog("Clearing LLInt property access with structure %p.\n", curInstruction[4].u.structure.get());
 1764 curInstruction[4].u.structure.clear();
 1765 curInstruction[5].u.operand = 0;
 1766 break;
 1767 case op_put_by_id_transition_direct:
 1768 case op_put_by_id_transition_normal:
 1769 if (Heap::isMarked(curInstruction[4].u.structure.get())
 1770 && Heap::isMarked(curInstruction[6].u.structure.get())
 1771 && Heap::isMarked(curInstruction[7].u.structureChain.get()))
 1772 break;
 1773 if (verboseUnlinking) {
 1774 dataLog("Clearing LLInt put transition with structures %p -> %p, chain %p.\n",
 1775 curInstruction[4].u.structure.get(),
 1776 curInstruction[6].u.structure.get(),
 1777 curInstruction[7].u.structureChain.get());
 1778 }
 1779 curInstruction[4].u.structure.clear();
 1780 curInstruction[6].u.structure.clear();
 1781 curInstruction[7].u.structureChain.clear();
 1782 curInstruction[0].u.opcode = interpreter->getOpcode(op_put_by_id);
 1783 break;
 1784 default:
 1785 ASSERT_NOT_REACHED();
 1786 }
 1787 }
 1788 for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i) {
 1789 Instruction* curInstruction = &instructions()[m_globalResolveInstructions[i]];
 1790 ASSERT(interpreter->getOpcodeID(curInstruction[0].u.opcode) == op_resolve_global
 1791 || interpreter->getOpcodeID(curInstruction[0].u.opcode) == op_resolve_global_dynamic);
 1792 if (!curInstruction[3].u.structure || Heap::isMarked(curInstruction[3].u.structure.get()))
 1793 continue;
 1794 if (verboseUnlinking)
 1795 dataLog("Clearing LLInt global resolve cache with structure %p.\n", curInstruction[3].u.structure.get());
 1796 curInstruction[3].u.structure.clear();
 1797 curInstruction[4].u.operand = 0;
 1798 }
 1799 for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) {
 1800 if (m_llintCallLinkInfos[i].isLinked() && !Heap::isMarked(m_llintCallLinkInfos[i].callee.get())) {
 1801 if (verboseUnlinking)
 1802 dataLog("Clearing LLInt call from %p.\n", this);
 1803 m_llintCallLinkInfos[i].unlink();
 1804 }
 1805 if (!!m_llintCallLinkInfos[i].lastSeenCallee && !Heap::isMarked(m_llintCallLinkInfos[i].lastSeenCallee.get()))
 1806 m_llintCallLinkInfos[i].lastSeenCallee.clear();
 1807 }
 1808 }
 1809#endif // ENABLE(LLINT)
 1810
17351811#if ENABLE(DFG_JIT)
17361812 // Check if we're not live. If we are, then jettison.
17371813 if (!(shouldImmediatelyAssumeLivenessDuringScan() || m_dfgData->livenessHasBeenProved)) {

@@void CodeBlock::finalizeUnconditionally(
17541830 for (unsigned i = 0; i < numberOfCallLinkInfos(); ++i) {
17551831 if (callLinkInfo(i).isLinked() && !Heap::isMarked(callLinkInfo(i).callee.get())) {
17561832 if (verboseUnlinking)
1757  dataLog("Clearing call from %p.\n", this);
 1833 dataLog("Clearing call from %p to %p.\n", this, callLinkInfo(i).callee.get());
17581834 callLinkInfo(i).unlink(*m_globalData, repatchBuffer);
17591835 }
17601836 if (!!callLinkInfo(i).lastSeenCallee

@@void CodeBlock::stronglyVisitStrongRefer
18521928 for (size_t i = 0; i < m_functionDecls.size(); ++i)
18531929 visitor.append(&m_functionDecls[i]);
18541930#if ENABLE(INTERPRETER)
1855  for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i)
1856  visitStructures(visitor, &instructions()[m_propertyAccessInstructions[i]]);
1857  for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)
1858  visitStructures(visitor, &instructions()[m_globalResolveInstructions[i]]);
 1931 if (m_globalData->interpreter->enabled()) {
 1932 for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i)
 1933 visitStructures(visitor, &instructions()[m_propertyAccessInstructions[i]]);
 1934 for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)
 1935 visitStructures(visitor, &instructions()[m_globalResolveInstructions[i]]);
 1936 }
18591937#endif
18601938
18611939#if ENABLE(DFG_JIT)

@@void CodeBlock::stronglyVisitStrongRefer
18631941 // Make sure that executables that we have inlined don't die.
18641942 // FIXME: If they would have otherwise died, we should probably trigger recompilation.
18651943 for (size_t i = 0; i < inlineCallFrames().size(); ++i) {
1866  visitor.append(&inlineCallFrames()[i].executable);
1867  visitor.append(&inlineCallFrames()[i].callee);
 1944 InlineCallFrame& inlineCallFrame = inlineCallFrames()[i];
 1945 visitor.append(&inlineCallFrame.executable);
 1946 visitor.append(&inlineCallFrame.callee);
18681947 }
18691948 }
18701949#endif

@@void CodeBlock::unlinkCalls()
20742153{
20752154 if (!!m_alternative)
20762155 m_alternative->unlinkCalls();
 2156#if ENABLE(LLINT)
 2157 for (size_t i = 0; i < m_llintCallLinkInfos.size(); ++i) {
 2158 if (m_llintCallLinkInfos[i].isLinked())
 2159 m_llintCallLinkInfos[i].unlink();
 2160 }
 2161#endif
20772162 if (!(m_callLinkInfos.size() || m_methodCallLinkInfos.size()))
20782163 return;
20792164 if (!m_globalData->canUseJIT())

@@void CodeBlock::unlinkCalls()
20882173
20892174void CodeBlock::unlinkIncomingCalls()
20902175{
 2176#if ENABLE(LLINT)
 2177 while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end())
 2178 m_incomingLLIntCalls.begin()->unlink();
 2179#endif
 2180 if (m_incomingCalls.isEmpty())
 2181 return;
20912182 RepatchBuffer repatchBuffer(this);
20922183 while (m_incomingCalls.begin() != m_incomingCalls.end())
20932184 m_incomingCalls.begin()->unlink(*m_globalData, repatchBuffer);
20942185}
 2186
 2187unsigned CodeBlock::bytecodeOffset(ExecState* exec, ReturnAddressPtr returnAddress)
 2188{
 2189#if ENABLE(LLINT)
 2190 if (returnAddress.value() >= bitwise_cast<void*>(&llint_begin)
 2191 && returnAddress.value() <= bitwise_cast<void*>(&llint_end)) {
 2192 ASSERT(exec->codeBlock());
 2193 ASSERT(exec->codeBlock() == this);
 2194 ASSERT(JITCode::isBaselineCode(getJITType()));
 2195 Instruction* instruction = exec->currentVPC();
 2196 ASSERT(instruction);
 2197 return bytecodeOffset(instruction);
 2198 }
 2199#else
 2200 UNUSED_PARAM(exec);
 2201#endif
 2202 if (!m_rareData)
 2203 return 1;
 2204 Vector<CallReturnOffsetToBytecodeOffset>& callIndices = m_rareData->m_callReturnIndexVector;
 2205 if (!callIndices.size())
 2206 return 1;
 2207 return binarySearch<CallReturnOffsetToBytecodeOffset, unsigned, getCallReturnOffset>(callIndices.begin(), callIndices.size(), getJITCode().offsetOf(returnAddress.value()))->bytecodeOffset;
 2208}
20952209#endif
20962210
20972211void CodeBlock::clearEvalCache()

@@bool FunctionCodeBlock::canCompileWithDF
21872301
21882302void ProgramCodeBlock::jettison()
21892303{
2190  ASSERT(getJITType() != JITCode::BaselineJIT);
 2304 ASSERT(JITCode::isOptimizingJIT(getJITType()));
21912305 ASSERT(this == replacement());
21922306 static_cast<ProgramExecutable*>(ownerExecutable())->jettisonOptimizedCode(*globalData());
21932307}
21942308
21952309void EvalCodeBlock::jettison()
21962310{
2197  ASSERT(getJITType() != JITCode::BaselineJIT);
 2311 ASSERT(JITCode::isOptimizingJIT(getJITType()));
21982312 ASSERT(this == replacement());
21992313 static_cast<EvalExecutable*>(ownerExecutable())->jettisonOptimizedCode(*globalData());
22002314}
22012315
22022316void FunctionCodeBlock::jettison()
22032317{
2204  ASSERT(getJITType() != JITCode::BaselineJIT);
 2318 ASSERT(JITCode::isOptimizingJIT(getJITType()));
22052319 ASSERT(this == replacement());
22062320 static_cast<FunctionExecutable*>(ownerExecutable())->jettisonOptimizedCodeFor(*globalData(), m_isConstructor ? CodeForConstruct : CodeForCall);
22072321}
 2322
 2323void ProgramCodeBlock::jitCompileImpl(JSGlobalData& globalData)
 2324{
 2325 ASSERT(getJITType() == JITCode::InterpreterThunk);
 2326 ASSERT(this == replacement());
 2327 return static_cast<ProgramExecutable*>(ownerExecutable())->jitCompile(globalData);
 2328}
 2329
 2330void EvalCodeBlock::jitCompileImpl(JSGlobalData& globalData)
 2331{
 2332 ASSERT(getJITType() == JITCode::InterpreterThunk);
 2333 ASSERT(this == replacement());
 2334 return static_cast<EvalExecutable*>(ownerExecutable())->jitCompile(globalData);
 2335}
 2336
 2337void FunctionCodeBlock::jitCompileImpl(JSGlobalData& globalData)
 2338{
 2339 ASSERT(getJITType() == JITCode::InterpreterThunk);
 2340 ASSERT(this == replacement());
 2341 return static_cast<FunctionExecutable*>(ownerExecutable())->jitCompileFor(globalData, m_isConstructor ? CodeForConstruct : CodeForCall);
 2342}
22082343#endif
22092344
22102345#if ENABLE(VALUE_PROFILER)
107713

Source/JavaScriptCore/bytecode/CodeBlock.h

3030#ifndef CodeBlock_h
3131#define CodeBlock_h
3232
 33#include "BytecodeConventions.h"
3334#include "CallLinkInfo.h"
3435#include "CallReturnOffsetToBytecodeOffset.h"
3536#include "CodeOrigin.h"

5051#include "JITWriteBarrier.h"
5152#include "JSGlobalObject.h"
5253#include "JumpTable.h"
 54#include "LLIntCallLinkInfo.h"
5355#include "LineInfo.h"
5456#include "Nodes.h"
5557#include "PredictionTracker.h"

6567#include <wtf/Vector.h>
6668#include "StructureStubInfo.h"
6769
68 // Register numbers used in bytecode operations have different meaning according to their ranges:
69 // 0x80000000-0xFFFFFFFF Negative indices from the CallFrame pointer are entries in the call frame, see RegisterFile.h.
70 // 0x00000000-0x3FFFFFFF Forwards indices from the CallFrame pointer are local vars and temporaries with the function's callframe.
71 // 0x40000000-0x7FFFFFFF Positive indices from 0x40000000 specify entries in the constant pool on the CodeBlock.
72 static const int FirstConstantRegisterIndex = 0x40000000;
73 
7470namespace JSC {
7571
76  class ExecState;
7772 class DFGCodeBlocks;
 73 class ExecState;
 74 class LLIntOffsetsExtractor;
7875
7976 inline int unmodifiedArgumentsRegister(int argumentsRegister) { return argumentsRegister - 1; }
8077

@@namespace JSC {
8380 class CodeBlock : public UnconditionalFinalizer, public WeakReferenceHarvester {
8481 WTF_MAKE_FAST_ALLOCATED;
8582 friend class JIT;
 83 friend class LLIntOffsetsExtractor;
8684 public:
8785 enum CopyParsedBlockTag { CopyParsedBlock };
8886 protected:

@@namespace JSC {
123121 while (result->alternative())
124122 result = result->alternative();
125123 ASSERT(result);
126  ASSERT(result->getJITType() == JITCode::BaselineJIT);
 124 ASSERT(JITCode::isBaselineCode(result->getJITType()));
127125 return result;
128126 }
129127#endif

@@namespace JSC {
192190 return *(binarySearch<MethodCallLinkInfo, unsigned, getMethodCallLinkInfoBytecodeIndex>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), bytecodeIndex));
193191 }
194192
195  unsigned bytecodeOffset(ReturnAddressPtr returnAddress)
196  {
197  if (!m_rareData)
198  return 1;
199  Vector<CallReturnOffsetToBytecodeOffset>& callIndices = m_rareData->m_callReturnIndexVector;
200  if (!callIndices.size())
201  return 1;
202  return binarySearch<CallReturnOffsetToBytecodeOffset, unsigned, getCallReturnOffset>(callIndices.begin(), callIndices.size(), getJITCode().offsetOf(returnAddress.value()))->bytecodeOffset;
203  }
 193 unsigned bytecodeOffset(ExecState*, ReturnAddressPtr);
204194
205195 unsigned bytecodeOffsetForCallAtIndex(unsigned index)
206196 {

@@namespace JSC {
221211 {
222212 m_incomingCalls.push(incoming);
223213 }
 214#if ENABLE(LLINT)
 215 void linkIncomingCall(LLIntCallLinkInfo* incoming)
 216 {
 217 m_incomingLLIntCalls.push(incoming);
 218 }
 219#endif // ENABLE(LLINT)
224220
225221 void unlinkIncomingCalls();
226 #endif
 222#endif // ENABLE(JIT)
227223
228 #if ENABLE(DFG_JIT)
 224#if ENABLE(DFG_JIT) || ENABLE(LLINT)
229225 void setJITCodeMap(PassOwnPtr<CompactJITCodeMap> jitCodeMap)
230226 {
231227 m_jitCodeMap = jitCodeMap;

@@namespace JSC {
234230 {
235231 return m_jitCodeMap.get();
236232 }
 233#endif
237234
 235#if ENABLE(DFG_JIT)
238236 void createDFGDataIfNecessary()
239237 {
240238 if (!!m_dfgData)

@@namespace JSC {
333331 }
334332#endif
335333
336 #if ENABLE(INTERPRETER)
337334 unsigned bytecodeOffset(Instruction* returnAddress)
338335 {
 336 ASSERT(returnAddress >= instructions().begin() && returnAddress < instructions().end());
339337 return static_cast<Instruction*>(returnAddress) - instructions().begin();
340338 }
341 #endif
342339
343340 void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; }
344341 bool isNumericCompareFunction() { return m_isNumericCompareFunction; }

@@namespace JSC {
376373 ExecutableMemoryHandle* executableMemory() { return getJITCode().getExecutableMemory(); }
377374 virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*) = 0;
378375 virtual void jettison() = 0;
 376 bool jitCompile(JSGlobalData& globalData)
 377 {
 378 if (getJITType() != JITCode::InterpreterThunk) {
 379 ASSERT(getJITType() == JITCode::BaselineJIT);
 380 return false;
 381 }
 382 jitCompileImpl(globalData);
 383 return true;
 384 }
379385 virtual CodeBlock* replacement() = 0;
380386
381387 enum CompileWithDFGState {

@@namespace JSC {
395401
396402 bool hasOptimizedReplacement()
397403 {
398  ASSERT(getJITType() == JITCode::BaselineJIT);
 404 ASSERT(JITCode::isBaselineCode(getJITType()));
399405 bool result = replacement()->getJITType() > getJITType();
400406#if !ASSERT_DISABLED
401407 if (result)
402408 ASSERT(replacement()->getJITType() == JITCode::DFGJIT);
403409 else {
404  ASSERT(replacement()->getJITType() == JITCode::BaselineJIT);
 410 ASSERT(JITCode::isBaselineCode(replacement()->getJITType()));
405411 ASSERT(replacement() == this);
406412 }
407413#endif

@@namespace JSC {
460466
461467 void clearEvalCache();
462468
463 #if ENABLE(INTERPRETER)
464469 void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
465470 {
466  if (!m_globalData->canUseJIT())
467  m_propertyAccessInstructions.append(propertyAccessInstruction);
 471 m_propertyAccessInstructions.append(propertyAccessInstruction);
468472 }
469473 void addGlobalResolveInstruction(unsigned globalResolveInstruction)
470474 {
471  if (!m_globalData->canUseJIT())
472  m_globalResolveInstructions.append(globalResolveInstruction);
 475 m_globalResolveInstructions.append(globalResolveInstruction);
473476 }
474477 bool hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset);
 478#if ENABLE(LLINT)
 479 LLIntCallLinkInfo* addLLIntCallLinkInfo()
 480 {
 481 m_llintCallLinkInfos.append(LLIntCallLinkInfo());
 482 return &m_llintCallLinkInfos.last();
 483 }
475484#endif
476485#if ENABLE(JIT)
477486 void setNumberOfStructureStubInfos(size_t size) { m_structureStubInfos.grow(size); }

@@namespace JSC {
480489
481490 void addGlobalResolveInfo(unsigned globalResolveInstruction)
482491 {
483  if (m_globalData->canUseJIT())
484  m_globalResolveInfos.append(GlobalResolveInfo(globalResolveInstruction));
 492 m_globalResolveInfos.append(GlobalResolveInfo(globalResolveInstruction));
485493 }
486494 GlobalResolveInfo& globalResolveInfo(int index) { return m_globalResolveInfos[index]; }
487495 bool hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset);

@@namespace JSC {
492500
493501 void addMethodCallLinkInfos(unsigned n) { ASSERT(m_globalData->canUseJIT()); m_methodCallLinkInfos.grow(n); }
494502 MethodCallLinkInfo& methodCallLinkInfo(int index) { return m_methodCallLinkInfos[index]; }
 503 size_t numberOfMethodCallLinkInfos() { return m_methodCallLinkInfos.size(); }
495504#endif
496505
497506#if ENABLE(VALUE_PROFILER)

@@namespace JSC {
533542 bytecodeOffset].u.opcode)) - 1].u.profile == result);
534543 return result;
535544 }
 545 PredictedType valueProfilePredictionForBytecodeOffset(int bytecodeOffset)
 546 {
 547 return valueProfileForBytecodeOffset(bytecodeOffset)->computeUpdatedPrediction();
 548 }
536549
537550 unsigned totalNumberOfValueProfiles()
538551 {

@@namespace JSC {
559572
560573 bool likelyToTakeSlowCase(int bytecodeOffset)
561574 {
 575 if (!numberOfRareCaseProfiles())
 576 return false;
562577 unsigned value = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
563578 return value >= Options::likelyToTakeSlowCaseMinimumCount && static_cast<double>(value) / m_executionEntryCount >= Options::likelyToTakeSlowCaseThreshold;
564579 }
565580
566581 bool couldTakeSlowCase(int bytecodeOffset)
567582 {
 583 if (!numberOfRareCaseProfiles())
 584 return false;
568585 unsigned value = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
569586 return value >= Options::couldTakeSlowCaseMinimumCount && static_cast<double>(value) / m_executionEntryCount >= Options::couldTakeSlowCaseThreshold;
570587 }

@@namespace JSC {
583600
584601 bool likelyToTakeSpecialFastCase(int bytecodeOffset)
585602 {
 603 if (!numberOfRareCaseProfiles())
 604 return false;
586605 unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
587606 return specialFastCaseCount >= Options::likelyToTakeSlowCaseMinimumCount && static_cast<double>(specialFastCaseCount) / m_executionEntryCount >= Options::likelyToTakeSlowCaseThreshold;
588607 }
589608
590609 bool likelyToTakeDeepestSlowCase(int bytecodeOffset)
591610 {
 611 if (!numberOfRareCaseProfiles())
 612 return false;
592613 unsigned slowCaseCount = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
593614 unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
594615 unsigned value = slowCaseCount - specialFastCaseCount;

@@namespace JSC {
597618
598619 bool likelyToTakeAnySlowCase(int bytecodeOffset)
599620 {
 621 if (!numberOfRareCaseProfiles())
 622 return false;
600623 unsigned slowCaseCount = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
601624 unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
602625 unsigned value = slowCaseCount + specialFastCaseCount;

@@namespace JSC {
694717
695718 bool addFrequentExitSite(const DFG::FrequentExitSite& site)
696719 {
697  ASSERT(getJITType() == JITCode::BaselineJIT);
 720 ASSERT(JITCode::isBaselineCode(getJITType()));
698721 return m_exitProfile.add(site);
699722 }
700723

@@namespace JSC {
802825 void copyPostParseDataFrom(CodeBlock* alternative);
803826 void copyPostParseDataFromAlternative();
804827
 828 // Functions for controlling when JITting kicks in, in a mixed mode
 829 // execution world.
 830
 831 void dontJITAnytimeSoon()
 832 {
 833 m_llintExecuteCounter = Options::executionCounterValueForDontJITAnytimeSoon;
 834 }
 835
 836 void jitAfterWarmUp()
 837 {
 838 m_llintExecuteCounter = Options::executionCounterValueForJITAfterWarmUp;
 839 }
 840
 841 void jitSoon()
 842 {
 843 m_llintExecuteCounter = Options::executionCounterValueForJITSoon;
 844 }
 845
 846 int32_t llintExecuteCounter() const
 847 {
 848 return m_llintExecuteCounter;
 849 }
 850
805851 // Functions for controlling when tiered compilation kicks in. This
806852 // controls both when the optimizing compiler is invoked and when OSR
807853 // entry happens. Two triggers exist: the loop trigger and the return

@@namespace JSC {
9941040 bool m_shouldDiscardBytecode;
9951041
9961042 protected:
 1043 virtual void jitCompileImpl(JSGlobalData&) = 0;
9971044 virtual void visitWeakReferences(SlotVisitor&);
9981045 virtual void finalizeUnconditionally();
9991046

@@namespace JSC {
10751122 RefPtr<SourceProvider> m_source;
10761123 unsigned m_sourceOffset;
10771124
1078 #if ENABLE(INTERPRETER)
10791125 Vector<unsigned> m_propertyAccessInstructions;
10801126 Vector<unsigned> m_globalResolveInstructions;
 1127#if ENABLE(LLINT)
 1128 SegmentedVector<LLIntCallLinkInfo, 8> m_llintCallLinkInfos;
 1129 SentinelLinkedList<LLIntCallLinkInfo, BasicRawSentinelNode<LLIntCallLinkInfo> > m_incomingLLIntCalls;
10811130#endif
10821131#if ENABLE(JIT)
10831132 Vector<StructureStubInfo> m_structureStubInfos;

@@namespace JSC {
10881137 MacroAssemblerCodePtr m_jitCodeWithArityCheck;
10891138 SentinelLinkedList<CallLinkInfo, BasicRawSentinelNode<CallLinkInfo> > m_incomingCalls;
10901139#endif
1091 #if ENABLE(DFG_JIT)
 1140#if ENABLE(DFG_JIT) || ENABLE(LLINT)
10921141 OwnPtr<CompactJITCodeMap> m_jitCodeMap;
1093 
 1142#endif
 1143#if ENABLE(DFG_JIT)
10941144 struct WeakReferenceTransition {
10951145 WeakReferenceTransition() { }
10961146

@@namespace JSC {
11531203
11541204 OwnPtr<CodeBlock> m_alternative;
11551205
 1206 int32_t m_llintExecuteCounter;
 1207
11561208 int32_t m_jitExecuteCounter;
11571209 uint32_t m_speculativeSuccessCounter;
11581210 uint32_t m_speculativeFailCounter;
11591211 uint8_t m_optimizationDelayCounter;
11601212 uint8_t m_reoptimizationRetryCounter;
1161 
 1213
11621214 struct RareData {
11631215 WTF_MAKE_FAST_ALLOCATED;
11641216 public:

@@namespace JSC {
12341286 protected:
12351287 virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
12361288 virtual void jettison();
 1289 virtual void jitCompileImpl(JSGlobalData&);
12371290 virtual CodeBlock* replacement();
12381291 virtual bool canCompileWithDFGInternal();
12391292#endif

@@namespace JSC {
12681321 protected:
12691322 virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
12701323 virtual void jettison();
 1324 virtual void jitCompileImpl(JSGlobalData&);
12711325 virtual CodeBlock* replacement();
12721326 virtual bool canCompileWithDFGInternal();
12731327#endif

@@namespace JSC {
13051359 protected:
13061360 virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
13071361 virtual void jettison();
 1362 virtual void jitCompileImpl(JSGlobalData&);
13081363 virtual CodeBlock* replacement();
13091364 virtual bool canCompileWithDFGInternal();
13101365#endif
107713

Source/JavaScriptCore/bytecode/GetByIdStatus.cpp

2727#include "GetByIdStatus.h"
2828
2929#include "CodeBlock.h"
 30#include "LowLevelInterpreter.h"
3031
3132namespace JSC {
3233
 34GetByIdStatus GetByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
 35{
 36 UNUSED_PARAM(profiledBlock);
 37 UNUSED_PARAM(bytecodeIndex);
 38 UNUSED_PARAM(ident);
 39#if ENABLE(LLINT)
 40 Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
 41
 42 if (instruction[0].u.opcode == llint_op_method_check)
 43 instruction++;
 44
 45 Structure* structure = instruction[4].u.structure.get();
 46 if (!structure)
 47 return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
 48
 49 size_t offset = structure->get(*profiledBlock->globalData(), ident);
 50 if (offset == notFound)
 51 return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
 52
 53 return GetByIdStatus(SimpleDirect, StructureSet(structure), offset, false);
 54#else
 55 return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
 56#endif
 57}
 58
3359GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
3460{
3561 UNUSED_PARAM(profiledBlock);
3662 UNUSED_PARAM(bytecodeIndex);
3763 UNUSED_PARAM(ident);
3864#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
 65 if (!profiledBlock->numberOfStructureStubInfos())
 66 return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
 67
3968 // First check if it makes either calls, in which case we want to be super careful, or
4069 // if it's not set at all, in which case we punt.
4170 StructureStubInfo& stubInfo = profiledBlock->getStubInfo(bytecodeIndex);
4271 if (!stubInfo.seen)
43  return GetByIdStatus(NoInformation, StructureSet(), notFound);
 72 return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
4473
4574 PolymorphicAccessStructureList* list;
4675 int listSize;

@@GetByIdStatus GetByIdStatus::computeFor(
6089 }
6190 for (int i = 0; i < listSize; ++i) {
6291 if (!list->list[i].isDirect)
63  return GetByIdStatus(MakesCalls, StructureSet(), notFound);
 92 return GetByIdStatus(MakesCalls, StructureSet(), notFound, true);
6493 }
6594
6695 // Next check if it takes slow case, in which case we want to be kind of careful.
6796 if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex))
68  return GetByIdStatus(TakesSlowPath, StructureSet(), notFound);
 97 return GetByIdStatus(TakesSlowPath, StructureSet(), notFound, true);
6998
7099 // Finally figure out if we can derive an access strategy.
71100 GetByIdStatus result;
 101 result.m_wasSeenInJIT = true;
72102 switch (stubInfo.accessType) {
73103 case access_unset:
74  return GetByIdStatus(NoInformation, StructureSet(), notFound);
 104 return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
75105
76106 case access_get_by_id_self: {
77107 Structure* structure = stubInfo.u.getByIdSelf.baseObjectStructure.get();

@@GetByIdStatus GetByIdStatus::computeFor(
130160
131161 return result;
132162#else // ENABLE(JIT)
133  return GetByIdStatus(NoInformation, StructureSet(), notFound);
 163 return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
134164#endif // ENABLE(JIT)
135165}
136166
107713

Source/JavaScriptCore/bytecode/GetByIdStatus.h

@@public:
4949 {
5050 }
5151
52  GetByIdStatus(State state, const StructureSet& structureSet, size_t offset)
 52 GetByIdStatus(State state, const StructureSet& structureSet, size_t offset, bool wasSeenInJIT)
5353 : m_state(state)
5454 , m_structureSet(structureSet)
5555 , m_offset(offset)
 56 , m_wasSeenInJIT(wasSeenInJIT)
5657 {
5758 ASSERT((state == SimpleDirect) == (offset != notFound));
5859 }

@@public:
7071 const StructureSet& structureSet() const { return m_structureSet; }
7172 size_t offset() const { return m_offset; }
7273
 74 bool wasSeenInJIT() const { return m_wasSeenInJIT; }
 75
7376private:
 77 static GetByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, Identifier&);
 78
7479 State m_state;
7580 StructureSet m_structureSet;
7681 size_t m_offset;
 82 bool m_wasSeenInJIT;
7783};
7884
7985} // namespace JSC
107713

Source/JavaScriptCore/bytecode/Instruction.h

@@namespace JSC {
4848 class JSCell;
4949 class Structure;
5050 class StructureChain;
 51 struct LLIntCallLinkInfo;
5152 struct ValueProfile;
5253
5354#if ENABLE(JIT)

@@namespace JSC {
146147#endif
147148
148149 struct Instruction {
 150 Instruction()
 151 {
 152 u.jsCell.clear();
 153 }
 154
149155 Instruction(Opcode opcode)
150156 {
151157#if !ENABLE(COMPUTED_GOTO_INTERPRETER)

@@namespace JSC {
182188
183189 Instruction(PropertySlot::GetValueFunc getterFunc) { u.getterFunc = getterFunc; }
184190
 191 Instruction(LLIntCallLinkInfo* callLinkInfo) { u.callLinkInfo = callLinkInfo; }
 192
185193 Instruction(ValueProfile* profile) { u.profile = profile; }
186194
187195 union {

@@namespace JSC {
191199 WriteBarrierBase<StructureChain> structureChain;
192200 WriteBarrierBase<JSCell> jsCell;
193201 PropertySlot::GetValueFunc getterFunc;
 202 LLIntCallLinkInfo* callLinkInfo;
194203 ValueProfile* profile;
 204 void* pointer;
195205 } u;
196206
197207 private:
107713

Source/JavaScriptCore/bytecode/LLIntCallLinkInfo.h

 1/*
 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef LLIntCallLinkInfo_h
 27#define LLIntCallLinkInfo_h
 28
 29#include "JSFunction.h"
 30#include "MacroAssemblerCodeRef.h"
 31#include <wtf/SentinelLinkedList.h>
 32
 33namespace JSC {
 34
 35struct Instruction;
 36
 37struct LLIntCallLinkInfo : public BasicRawSentinelNode<LLIntCallLinkInfo> {
 38 LLIntCallLinkInfo()
 39 {
 40 }
 41
 42 ~LLIntCallLinkInfo()
 43 {
 44 if (isOnList())
 45 remove();
 46 }
 47
 48 bool isLinked() { return callee; }
 49
 50 void unlink()
 51 {
 52 callee.clear();
 53 machineCodeTarget = MacroAssemblerCodePtr();
 54 if (isOnList())
 55 remove();
 56 }
 57
 58 WriteBarrier<JSFunction> callee;
 59 WriteBarrier<JSFunction> lastSeenCallee;
 60 MacroAssemblerCodePtr machineCodeTarget;
 61};
 62
 63} // namespace JSC
 64
 65#endif // LLIntCallLinkInfo_h
 66
0

Source/JavaScriptCore/bytecode/MethodCallLinkStatus.cpp

@@MethodCallLinkStatus MethodCallLinkStatu
3535 UNUSED_PARAM(profiledBlock);
3636 UNUSED_PARAM(bytecodeIndex);
3737#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
 38 // NOTE: This does not have an LLInt fall-back because LLInt does not do any method
 39 // call link caching.
 40 if (!profiledBlock->numberOfMethodCallLinkInfos())
 41 return MethodCallLinkStatus();
 42
3843 MethodCallLinkInfo& methodCall = profiledBlock->getMethodCallLinkInfo(bytecodeIndex);
3944
4045 if (!methodCall.seen || !methodCall.cachedStructure)
107713

Source/JavaScriptCore/bytecode/Opcode.h

@@namespace JSC {
123123 macro(op_get_arguments_length, 4) \
124124 macro(op_put_by_id, 9) \
125125 macro(op_put_by_id_transition, 9) \
 126 macro(op_put_by_id_transition_direct, 9) \
 127 macro(op_put_by_id_transition_normal, 9) \
126128 macro(op_put_by_id_replace, 9) \
127129 macro(op_put_by_id_generic, 9) \
128130 macro(op_del_by_id, 4) \

@@namespace JSC {
201203 typedef enum { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) } OpcodeID;
202204 #undef OPCODE_ID_ENUM
203205
 206 const int maxOpcodeLength = 9;
204207 const int numOpcodeIDs = op_end + 1;
205208
206209 #define OPCODE_ID_LENGTHS(id, length) const int id##_length = length;

@@namespace JSC {
217220 FOR_EACH_OPCODE_ID(VERIFY_OPCODE_ID);
218221 #undef VERIFY_OPCODE_ID
219222
220 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
 223#if ENABLE(COMPUTED_GOTO_INTERPRETER) || ENABLE(LLINT)
221224#if COMPILER(RVCT) || COMPILER(INTEL)
222225 typedef void* Opcode;
223226#else
107713

Source/JavaScriptCore/bytecode/PutByIdStatus.cpp

2727#include "PutByIdStatus.h"
2828
2929#include "CodeBlock.h"
 30#include "LowLevelInterpreter.h"
3031#include "Structure.h"
3132#include "StructureChain.h"
3233
3334namespace JSC {
3435
 36PutByIdStatus PutByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
 37{
 38 UNUSED_PARAM(profiledBlock);
 39 UNUSED_PARAM(bytecodeIndex);
 40 UNUSED_PARAM(ident);
 41#if ENABLE(LLINT)
 42 Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
 43
 44 Structure* structure = instruction[4].u.structure.get();
 45 if (!structure)
 46 return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
 47
 48 if (instruction[0].u.opcode == llint_op_put_by_id) {
 49 size_t offset = structure->get(*profiledBlock->globalData(), ident);
 50 if (offset == notFound)
 51 return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
 52
 53 return PutByIdStatus(SimpleReplace, structure, 0, 0, offset);
 54 }
 55
 56 ASSERT(instruction[0].u.opcode == llint_op_put_by_id_transition_direct
 57 || instruction[0].u.opcode == llint_op_put_by_id_transition_normal);
 58
 59 Structure* newStructure = instruction[6].u.structure.get();
 60 StructureChain* chain = instruction[7].u.structureChain.get();
 61 ASSERT(newStructure);
 62 ASSERT(chain);
 63
 64 size_t offset = newStructure->get(*profiledBlock->globalData(), ident);
 65 if (offset == notFound)
 66 return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
 67
 68 return PutByIdStatus(SimpleTransition, structure, newStructure, chain, offset);
 69#else
 70 return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
 71#endif
 72}
 73
3574PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
3675{
3776 UNUSED_PARAM(profiledBlock);
3877 UNUSED_PARAM(bytecodeIndex);
3978 UNUSED_PARAM(ident);
4079#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
 80 if (!profiledBlock->numberOfStructureStubInfos())
 81 return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
 82
4183 if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex))
4284 return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound);
4385
4486 StructureStubInfo& stubInfo = profiledBlock->getStubInfo(bytecodeIndex);
4587 if (!stubInfo.seen)
46  return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
 88 return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
4789
4890 switch (stubInfo.accessType) {
4991 case access_unset:
50  return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
 92 return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
5193
5294 case access_put_by_id_replace: {
5395 size_t offset = stubInfo.u.putByIdReplace.baseObjectStructure->get(
107713

Source/JavaScriptCore/bytecode/PutByIdStatus.h

@@public:
9393 size_t offset() const { return m_offset; }
9494
9595private:
 96 static PutByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, Identifier&);
 97
9698 State m_state;
9799 Structure* m_oldStructure;
98100 Structure* m_newStructure;
107713

Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

3535#include "JSActivation.h"
3636#include "JSFunction.h"
3737#include "Interpreter.h"
 38#include "LowLevelInterpreter.h"
3839#include "ScopeChain.h"
3940#include "StrongInlines.h"
4041#include "UString.h"

@@RegisterID* BytecodeGenerator::emitResol
12781279#if ENABLE(JIT)
12791280 m_codeBlock->addGlobalResolveInfo(instructions().size());
12801281#endif
1281 #if ENABLE(INTERPRETER)
12821282 m_codeBlock->addGlobalResolveInstruction(instructions().size());
1283 #endif
12841283 bool dynamic = resolveResult.isDynamic() && resolveResult.depth();
12851284 ValueProfile* profile = emitProfiledOpcode(dynamic ? op_resolve_global_dynamic : op_resolve_global);
12861285 instructions().append(dst->index());

@@RegisterID* BytecodeGenerator::emitResol
13841383 return baseDst;
13851384 }
13861385
1387 
1388 
1389 
13901386 ValueProfile* profile = emitProfiledOpcode(op_resolve_with_base);
13911387 instructions().append(baseDst->index());
13921388 instructions().append(propDst->index());

@@void BytecodeGenerator::emitMethodCheck(
14941490
14951491RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
14961492{
1497 #if ENABLE(INTERPRETER)
14981493 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1499 #endif
15001494
15011495 ValueProfile* profile = emitProfiledOpcode(op_get_by_id);
15021496 instructions().append(dst->index());

@@RegisterID* BytecodeGenerator::emitGetAr
15221516
15231517RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
15241518{
1525 #if ENABLE(INTERPRETER)
15261519 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1527 #endif
15281520
15291521 emitOpcode(op_put_by_id);
15301522 instructions().append(base->index());

@@RegisterID* BytecodeGenerator::emitPutBy
15401532
15411533RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value)
15421534{
1543 #if ENABLE(INTERPRETER)
15441535 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1545 #endif
15461536
15471537 emitOpcode(op_put_by_id);
15481538 instructions().append(base->index());

@@RegisterID* BytecodeGenerator::emitCall(
18231813 instructions().append(func->index()); // func
18241814 instructions().append(callArguments.argumentCountIncludingThis()); // argCount
18251815 instructions().append(callArguments.registerOffset()); // registerOffset
 1816#if ENABLE(LLINT)
 1817 instructions().append(m_codeBlock->addLLIntCallLinkInfo());
 1818#else
18261819 instructions().append(0);
 1820#endif
18271821 instructions().append(0);
18281822 if (dst != ignoredResult()) {
18291823 ValueProfile* profile = emitProfiledOpcode(op_call_put_result);

@@RegisterID* BytecodeGenerator::emitConst
19271921 instructions().append(func->index()); // func
19281922 instructions().append(callArguments.argumentCountIncludingThis()); // argCount
19291923 instructions().append(callArguments.registerOffset()); // registerOffset
 1924#if ENABLE(LLINT)
 1925 instructions().append(m_codeBlock->addLLIntCallLinkInfo());
 1926#else
19301927 instructions().append(0);
 1928#endif
19311929 instructions().append(0);
19321930 if (dst != ignoredResult()) {
19331931 ValueProfile* profile = emitProfiledOpcode(op_call_put_result);

@@RegisterID* BytecodeGenerator::emitCatch
21882186{
21892187 m_usesExceptions = true;
21902188#if ENABLE(JIT)
 2189#if ENABLE(LLINT)
 2190 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))) };
 2191#else
21912192 HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel() };
 2193#endif
21922194#else
21932195 HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth };
21942196#endif
107713

Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

@@private:
585585 {
586586 UNUSED_PARAM(nodeIndex);
587587
588  ValueProfile* profile = m_inlineStackTop->m_profiledBlock->valueProfileForBytecodeOffset(bytecodeIndex);
589  ASSERT(profile);
590  PredictedType prediction = profile->computeUpdatedPrediction();
 588 PredictedType prediction = m_inlineStackTop->m_profiledBlock->valueProfilePredictionForBytecodeOffset(bytecodeIndex);
591589#if DFG_ENABLE(DEBUG_VERBOSE)
592590 dataLog("Dynamic [@%u, bc#%u] prediction: %s\n", nodeIndex, bytecodeIndex, predictionToString(prediction));
593591#endif

@@bool ByteCodeParser::handleInlining(bool
10221020
10231021 // If we get here then it looks like we should definitely inline this code. Proceed
10241022 // with parsing the code to get bytecode, so that we can then parse the bytecode.
 1023 // Note that if LLInt is enabled, the bytecode will always be available. Also note
 1024 // that if LLInt is enabled, we may inline a code block that has never been JITted
 1025 // before!
10251026 CodeBlock* codeBlock = m_codeBlockCache.get(CodeBlockKey(executable, kind), expectedFunction->scope());
10261027 if (!codeBlock)
10271028 return false;

@@bool ByteCodeParser::parseBlock(unsigned
17221723 m_inlineStackTop->m_profiledBlock, m_currentIndex);
17231724
17241725 if (methodCallStatus.isSet()
1725  && !getByIdStatus.isSet()
 1726 && !getByIdStatus.wasSeenInJIT()
17261727 && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
17271728 // It's monomorphic as far as we can tell, since the method_check was linked
17281729 // but the slow path (i.e. the normal get_by_id) never fired.

@@bool ByteCodeParser::parseBlock(unsigned
17911792
17921793 NEXT_OPCODE(op_get_by_id);
17931794 }
1794  case op_put_by_id: {
 1795 case op_put_by_id:
 1796 case op_put_by_id_transition_direct:
 1797 case op_put_by_id_transition_normal: {
17951798 NodeIndex value = get(currentInstruction[3].u.operand);
17961799 NodeIndex base = get(currentInstruction[1].u.operand);
17971800 unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
107713

Source/JavaScriptCore/dfg/DFGCapabilities.h

@@inline bool canCompileOpcode(OpcodeID op
111111 case op_put_scoped_var:
112112 case op_get_by_id:
113113 case op_put_by_id:
 114 case op_put_by_id_transition_direct:
 115 case op_put_by_id_transition_normal:
114116 case op_get_global_var:
115117 case op_put_global_var:
116118 case op_jmp:
107713

Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp

@@void compileOSRExit(ExecState* exec)
4848 uint32_t exitIndex = globalData->osrExitIndex;
4949 OSRExit& exit = codeBlock->osrExit(exitIndex);
5050
 51 // Make sure all code on our inline stack is JIT compiled. This is necessary since
 52 // we may opt to inline a code block even before it had ever been compiled by the
 53 // JIT, but our OSR exit infrastructure currently only works if the target of the
 54 // OSR exit is JIT code. This could be changed since there is nothing particularly
 55 // hard about doing an OSR exit into the interpreter, but for now this seems to make
 56 // sense in that if we're OSR exiting from inlined code of a DFG code block, then
 57 // probably it's a good sign that the thing we're exiting into is hot. Even more
 58 // interestingly, since the code was inlined, it may never otherwise get JIT
 59 // compiled since the act of inlining it may ensure that it otherwise never runs.
 60 for (CodeOrigin codeOrigin = exit.m_codeOrigin; codeOrigin.inlineCallFrame; codeOrigin = codeOrigin.inlineCallFrame->caller) {
 61 static_cast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())
 62 ->baselineCodeBlockFor(codeOrigin.inlineCallFrame->isCall ? CodeForCall : CodeForConstruct)
 63 ->jitCompile(*globalData);
 64 }
 65
5166 SpeculationRecovery* recovery = 0;
5267 if (exit.m_recoveryIndex)
5368 recovery = &codeBlock->speculationRecovery(exit.m_recoveryIndex - 1);
107713

Source/JavaScriptCore/dfg/DFGOperations.cpp

3131#include "CodeBlock.h"
3232#include "DFGOSRExit.h"
3333#include "DFGRepatch.h"
 34#include "HostCallReturnValue.h"
3435#include "GetterSetter.h"
3536#include "InlineASM.h"
3637#include "Interpreter.h"

@@size_t DFG_OPERATION operationCompareStr
737738 return JSValue::strictEqual(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
738739}
739740
740 EncodedJSValue DFG_OPERATION getHostCallReturnValue();
741 EncodedJSValue DFG_OPERATION getHostCallReturnValueWithExecState(ExecState*);
742 
743 #if CPU(X86_64)
744 asm (
745 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
746 HIDE_SYMBOL(getHostCallReturnValue) "\n"
747 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
748  "mov -40(%r13), %r13\n"
749  "mov %r13, %rdi\n"
750  "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
751 );
752 #elif CPU(X86)
753 asm (
754 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
755 HIDE_SYMBOL(getHostCallReturnValue) "\n"
756 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
757  "mov -40(%edi), %edi\n"
758  "mov %edi, 4(%esp)\n"
759  "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
760 );
761 #elif CPU(ARM_THUMB2)
762 asm (
763 ".text" "\n"
764 ".align 2" "\n"
765 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
766 HIDE_SYMBOL(getHostCallReturnValue) "\n"
767 ".thumb" "\n"
768 ".thumb_func " THUMB_FUNC_PARAM(getHostCallReturnValue) "\n"
769 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
770  "ldr r5, [r5, #-40]" "\n"
771  "cpy r0, r5" "\n"
772  "b " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
773 );
774 #endif
775 
776 EncodedJSValue DFG_OPERATION getHostCallReturnValueWithExecState(ExecState* exec)
777 {
778  JSGlobalData* globalData = &exec->globalData();
779  NativeCallFrameTracer tracer(globalData, exec);
780 
781  return JSValue::encode(exec->globalData().hostCallReturnValue);
782 }
783 
784741static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializationKind kind)
785742{
786743 ExecState* exec = execCallee->callerFrame();
107713

Source/JavaScriptCore/heap/Heap.cpp

@@void Heap::collect(SweepToggle sweepTogg
837837 setHighWaterMark(max(proportionalBytes, m_minBytesPerCycle));
838838 }
839839 JAVASCRIPTCORE_GC_END();
840 
 840
841841 (*m_activityCallback)();
842842}
843843
107713

Source/JavaScriptCore/heap/Heap.h

@@namespace JSC {
5050 class JSGlobalData;
5151 class JSValue;
5252 class LiveObjectIterator;
 53 class LLIntOffsetsExtractor;
5354 class MarkedArgumentBuffer;
5455 class RegisterFile;
5556 class UString;

@@namespace JSC {
136137 void getConservativeRegisterRoots(HashSet<JSCell*>& roots);
137138
138139 private:
 140 friend class CodeBlock;
 141 friend class LLIntOffsetsExtractor;
139142 friend class MarkedSpace;
140143 friend class MarkedAllocator;
141144 friend class MarkedBlock;
142145 friend class BumpSpace;
143146 friend class SlotVisitor;
144  friend class CodeBlock;
145147 template<typename T> friend void* allocateCell(Heap&);
146148
147149 void* allocateWithDestructor(size_t);
107713

Source/JavaScriptCore/heap/MarkStack.cpp

@@ALWAYS_INLINE static void visitChildren(
304304#endif
305305
306306 ASSERT(Heap::isMarked(cell));
307 
 307
308308 if (isJSString(cell)) {
309309 JSString::visitChildren(const_cast<JSCell*>(cell), visitor);
310310 return;
107713

Source/JavaScriptCore/heap/MarkedAllocator.h

@@namespace JSC {
88
99class Heap;
1010class MarkedSpace;
 11class LLIntOffsetsExtractor;
1112
1213namespace DFG {
1314class SpeculativeJIT;

@@public:
3334 void init(Heap*, MarkedSpace*, size_t cellSize, bool cellsNeedDestruction);
3435
3536private:
 37 friend class LLIntOffsetsExtractor;
 38
3639 JS_EXPORT_PRIVATE void* allocateSlowCase();
3740 void* tryAllocate();
3841 void* tryAllocateHelper();
107713

Source/JavaScriptCore/heap/MarkedSpace.h

@@namespace JSC {
4141class Heap;
4242class JSCell;
4343class LiveObjectIterator;
 44class LLIntOffsetsExtractor;
4445class WeakGCHandle;
4546class SlotVisitor;
4647

@@public:
7980 void didConsumeFreeList(MarkedBlock*);
8081
8182private:
 83 friend class LLIntOffsetsExtractor;
 84
8285 // [ 32... 256 ]
8386 static const size_t preciseStep = MarkedBlock::atomSize;
8487 static const size_t preciseCutoff = 256;
107713

Source/JavaScriptCore/interpreter/CallFrame.h

@@namespace JSC {
124124#if ENABLE(INTERPRETER)
125125 Instruction* returnVPC() const { return this[RegisterFile::ReturnPC].vPC(); }
126126#endif
 127#if ENABLE(LLINT)
 128 Instruction* currentVPC() const { return bitwise_cast<Instruction*>(this[RegisterFile::ArgumentCount].tag()); }
 129#endif
127130
128131 void setCallerFrame(CallFrame* callerFrame) { static_cast<Register*>(this)[RegisterFile::CallerFrame] = callerFrame; }
129132 void setScopeChain(ScopeChainNode* scopeChain) { static_cast<Register*>(this)[RegisterFile::ScopeChain] = scopeChain; }
107713

Source/JavaScriptCore/interpreter/Interpreter.cpp

6969#include "JIT.h"
7070#endif
7171
72 #define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND (ENABLE(COMPUTED_GOTO_INTERPRETER) && !defined(__llvm__))
 72#define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND ((ENABLE(COMPUTED_GOTO_INTERPRETER) || ENABLE(LLINT)) && !defined(__llvm__))
7373
7474using namespace std;
7575

@@Interpreter::Interpreter()
547547{
548548}
549549
550 void Interpreter::initialize(bool canUseJIT)
 550Interpreter::~Interpreter()
551551{
552 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
 552#if ENABLE(LLINT)
 553 if (m_enabled)
 554 delete[] m_opcodeTable;
 555#endif
 556}
 557
 558void Interpreter::initialize(LLInt::Data* llintData, bool canUseJIT)
 559{
 560 UNUSED_PARAM(llintData);
 561 UNUSED_PARAM(canUseJIT);
 562#if ENABLE(COMPUTED_GOTO_INTERPRETER) || ENABLE(LLINT)
 563#if !ENABLE(COMPUTED_GOTO_INTERPRETER)
 564 // Having LLInt enabled, but not being able to use the JIT, and not having
 565 // a computed goto interpreter, is not supported. Not because we cannot
 566 // support it, but because I decided to draw the line at the number of
 567 // permutations of execution engines that I wanted this code to grok.
 568 ASSERT(canUseJIT);
 569#endif
553570 if (canUseJIT) {
 571#if ENABLE(LLINT)
 572 m_opcodeTable = llintData->opcodeMap();
 573 for (int i = 0; i < numOpcodeIDs; ++i)
 574 m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
 575#else
554576 // If the JIT is present, don't use jump destinations for opcodes.
555577
556578 for (int i = 0; i < numOpcodeIDs; ++i) {
557579 Opcode opcode = bitwise_cast<void*>(static_cast<uintptr_t>(i));
558580 m_opcodeTable[i] = opcode;
559581 }
 582#endif
560583 } else {
 584#if ENABLE(LLINT)
 585 m_opcodeTable = new Opcode[numOpcodeIDs];
 586#endif
561587 privateExecute(InitializeAndReturn, 0, 0);
562588
563589 for (int i = 0; i < numOpcodeIDs; ++i)

@@void Interpreter::initialize(bool canUse
566592 m_enabled = true;
567593 }
568594#else
569  UNUSED_PARAM(canUseJIT);
570595#if ENABLE(INTERPRETER)
571596 m_enabled = true;
572597#else

@@void Interpreter::dumpRegisters(CallFram
667692
668693bool Interpreter::isOpcode(Opcode opcode)
669694{
670 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
 695#if ENABLE(COMPUTED_GOTO_INTERPRETER) || ENABLE(LLINT)
 696#if !ENABLE(LLINT)
671697 if (!m_enabled)
672698 return opcode >= 0 && static_cast<OpcodeID>(bitwise_cast<uintptr_t>(opcode)) <= op_end;
 699#endif
673700 return opcode != HashTraits<Opcode>::emptyValue()
674701 && !HashTraits<Opcode>::isDeletedValue(opcode)
675702 && m_opcodeIDTable.contains(opcode);

@@NEVER_INLINE bool Interpreter::unwindCal
726753 // have to subtract 1.
727754#if ENABLE(JIT) && ENABLE(INTERPRETER)
728755 if (callerFrame->globalData().canUseJIT())
729  bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnPC());
 756 bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
730757 else
731758 bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1;
732759#elif ENABLE(JIT)
733  bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnPC());
 760 bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
734761#else
735762 bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1;
736763#endif

@@skip_id_custom_self:
33273354#if USE(GCC_COMPUTED_GOTO_WORKAROUND)
33283355 skip_put_by_id:
33293356#endif
 3357 DEFINE_OPCODE(op_put_by_id_transition_direct)
 3358 DEFINE_OPCODE(op_put_by_id_transition_normal)
33303359 DEFINE_OPCODE(op_put_by_id_transition) {
33313360 /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n) direct(b)
33323361

@@void Interpreter::retrieveLastCaller(Cal
51605189 bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnVPC());
51615190#if ENABLE(JIT)
51625191 else
5163  bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
 5192 bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
51645193#endif
51655194#else
5166  bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
 5195 bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
51675196#endif
51685197 lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
51695198 sourceID = callerCodeBlock->ownerExecutable()->sourceID();
107713

Source/JavaScriptCore/interpreter/Interpreter.h

3333#include "JSCell.h"
3434#include "JSValue.h"
3535#include "JSObject.h"
 36#include "LLIntData.h"
3637#include "Opcode.h"
3738#include "RegisterFile.h"
3839

@@namespace JSC {
4546 class FunctionExecutable;
4647 class JSFunction;
4748 class JSGlobalObject;
 49 class LLIntOffsetsExtractor;
4850 class ProgramExecutable;
4951 class Register;
5052 class ScopeChainNode;

@@namespace JSC {
100102
101103 class Interpreter {
102104 WTF_MAKE_FAST_ALLOCATED;
103  friend class JIT;
104105 friend class CachedCall;
 106 friend class LLIntOffsetsExtractor;
 107 friend class JIT;
105108 public:
106109 Interpreter();
 110 ~Interpreter();
107111
108  void initialize(bool canUseJIT);
 112 void initialize(LLInt::Data*, bool canUseJIT);
109113
110114 RegisterFile& registerFile() { return m_registerFile; }
111115
112116 Opcode getOpcode(OpcodeID id)
113117 {
114118 ASSERT(m_initialized);
115 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
 119#if ENABLE(COMPUTED_GOTO_INTERPRETER) || ENABLE(LLINT)
116120 return m_opcodeTable[id];
117121#else
118122 return id;

@@namespace JSC {
122126 OpcodeID getOpcodeID(Opcode opcode)
123127 {
124128 ASSERT(m_initialized);
125 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
 129#if ENABLE(LLINT)
 130 ASSERT(isOpcode(opcode));
 131 return m_opcodeIDTable.get(opcode);
 132#elif ENABLE(COMPUTED_GOTO_INTERPRETER)
126133 ASSERT(isOpcode(opcode));
127134 if (!m_enabled)
128135 return static_cast<OpcodeID>(bitwise_cast<uintptr_t>(opcode));

@@namespace JSC {
132139 return opcode;
133140#endif
134141 }
 142
 143 bool enabled()
 144 {
 145 return m_enabled;
 146 }
135147
136148 bool isOpcode(Opcode);
137149

@@namespace JSC {
199211
200212 RegisterFile m_registerFile;
201213
202 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
 214#if ENABLE(LLINT)
 215 Opcode* m_opcodeTable; // Maps OpcodeID => Opcode for compiling
 216 HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
 217#elif ENABLE(COMPUTED_GOTO_INTERPRETER)
203218 Opcode m_opcodeTable[numOpcodeIDs]; // Maps OpcodeID => Opcode for compiling
204219 HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
205220#endif
107713

Source/JavaScriptCore/interpreter/RegisterFile.h

@@namespace JSC {
3939
4040 class ConservativeRoots;
4141 class DFGCodeBlocks;
 42 class LLIntOffsetsExtractor;
4243
4344 class RegisterFile {
4445 WTF_MAKE_NONCOPYABLE(RegisterFile);

@@namespace JSC {
8182 }
8283
8384 private:
 85 friend class LLIntOffsetsExtractor;
 86
8487 bool growSlowCase(Register*);
8588 void releaseExcessCapacity();
8689 void addToCommittedByteCount(long);
107713

Source/JavaScriptCore/jit/HostCallReturnValue.cpp

 1/*
 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27#include "HostCallReturnValue.h"
 28
 29#include "CallFrame.h"
 30#include "InlineASM.h"
 31#include "JSObject.h"
 32#include "JSValueInlineMethods.h"
 33#include "ScopeChain.h"
 34
 35namespace JSC {
 36
 37#if COMPILER(GCC)
 38
 39#if CPU(X86_64)
 40asm (
 41".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
 42HIDE_SYMBOL(getHostCallReturnValue) "\n"
 43SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
 44 "mov -40(%r13), %r13\n"
 45 "mov %r13, %rdi\n"
 46 "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
 47);
 48#elif CPU(X86)
 49asm (
 50".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
 51HIDE_SYMBOL(getHostCallReturnValue) "\n"
 52SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
 53 "mov -40(%edi), %edi\n"
 54 "mov %edi, 4(%esp)\n"
 55 "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
 56);
 57#elif CPU(ARM_THUMB2)
 58asm (
 59".text" "\n"
 60".align 2" "\n"
 61".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
 62HIDE_SYMBOL(getHostCallReturnValue) "\n"
 63".thumb" "\n"
 64".thumb_func " THUMB_FUNC_PARAM(getHostCallReturnValue) "\n"
 65SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
 66 "ldr r5, [r5, #-40]" "\n"
 67 "cpy r0, r5" "\n"
 68 "b " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
 69);
 70#endif
 71
 72extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWithExecState(ExecState* exec)
 73{
 74 if (!exec)
 75 return JSValue::encode(JSValue());
 76 return JSValue::encode(exec->globalData().hostCallReturnValue);
 77}
 78
 79#endif // COMPILER(GCC)
 80
 81} // namespace JSC
 82
0

Source/JavaScriptCore/jit/HostCallReturnValue.h

 1/*
 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef HostCallReturnValue_h
 27#define HostCallReturnValue_h
 28
 29#include "JSValue.h"
 30#include "MacroAssemblerCodeRef.h"
 31#include <wtf/Platform.h>
 32
 33// Unfortunately this only works on GCC-like compilers. And it's currently only used
 34// by LLInt and DFG, which also are restricted to GCC-like compilers. We should
 35// probably fix that at some point.
 36#if COMPILER(GCC)
 37
 38#if CALLING_CONVENTION_IS_STDCALL
 39#define HOST_CALL_RETURN_VALUE_OPTION CDECL
 40#else
 41#define HOST_CALL_RETURN_VALUE_OPTION
 42#endif
 43
 44namespace JSC {
 45
 46extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValue();
 47
 48// This is a public declaration only to convince CLANG not to elide it.
 49extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWithExecState(ExecState*);
 50
 51inline void initializeHostCallReturnValue()
 52{
 53 getHostCallReturnValueWithExecState(0);
 54}
 55
 56}
 57
 58#else // COMPILER(GCC)
 59
 60namespace JSC {
 61inline void initializeHostCallReturnValue() { }
 62}
 63
 64#endif // COMPILER(GCC)
 65
 66#endif // HostCallReturnValue_h
 67
0

Source/JavaScriptCore/jit/JIT.cpp

@@void JIT::privateCompileMainPass()
325325 DEFINE_OP(op_profile_will_call)
326326 DEFINE_OP(op_push_new_scope)
327327 DEFINE_OP(op_push_scope)
 328 case op_put_by_id_transition_direct:
 329 case op_put_by_id_transition_normal:
328330 DEFINE_OP(op_put_by_id)
329331 DEFINE_OP(op_put_by_index)
330332 DEFINE_OP(op_put_by_val)

@@void JIT::privateCompileSlowCases()
486488 DEFINE_SLOWCASE_OP(op_post_inc)
487489 DEFINE_SLOWCASE_OP(op_pre_dec)
488490 DEFINE_SLOWCASE_OP(op_pre_inc)
 491 case op_put_by_id_transition_direct:
 492 case op_put_by_id_transition_normal:
489493 DEFINE_SLOWCASE_OP(op_put_by_id)
490494 DEFINE_SLOWCASE_OP(op_put_by_val)
491495 DEFINE_SLOWCASE_OP(op_resolve_global)

@@void JIT::privateCompileSlowCases()
525529
526530JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck)
527531{
 532#if ENABLE(JIT_VERBOSE_OSR)
 533 printf("Compiling JIT code!\n");
 534#endif
 535
528536#if ENABLE(VALUE_PROFILER)
529537 m_canBeOptimized = m_codeBlock->canCompileWithDFG();
530538#endif

@@JITCode JIT::privateCompile(CodePtr* fun
693701 info.callReturnLocation = m_codeBlock->structureStubInfo(m_methodCallCompilationInfo[i].propertyAccessIndex).callReturnLocation;
694702 }
695703
696 #if ENABLE(DFG_JIT)
697  if (m_canBeOptimized) {
 704#if ENABLE(DFG_JIT) || ENABLE(LLINT)
 705 if (m_canBeOptimized
 706#if ENABLE(LLINT)
 707 || true
 708#endif
 709 ) {
698710 CompactJITCodeMap::Encoder jitCodeMapEncoder;
699711 for (unsigned bytecodeOffset = 0; bytecodeOffset < m_labels.size(); ++bytecodeOffset) {
700712 if (m_labels[bytecodeOffset].isSet())
107713

Source/JavaScriptCore/jit/JITCode.h

@@namespace JSC {
4848 JITCode() { }
4949#endif
5050 public:
51  enum JITType { HostCallThunk, BaselineJIT, DFGJIT };
 51 enum JITType { None, HostCallThunk, InterpreterThunk, BaselineJIT, DFGJIT };
5252
5353 static JITType bottomTierJIT()
5454 {

@@namespace JSC {
6666 return DFGJIT;
6767 }
6868
 69 static bool isOptimizingJIT(JITType jitType)
 70 {
 71 return jitType == DFGJIT;
 72 }
 73
 74 static bool isBaselineCode(JITType jitType)
 75 {
 76 return jitType == InterpreterThunk || jitType == BaselineJIT;
 77 }
 78
6979#if ENABLE(JIT)
7080 JITCode()
 81 : m_jitType(None)
7182 {
7283 }
7384

@@namespace JSC {
7586 : m_ref(ref)
7687 , m_jitType(jitType)
7788 {
 89 ASSERT(jitType != None);
7890 }
7991
8092 bool operator !() const
107713

Source/JavaScriptCore/jit/JITDriver.h

3333#include "BytecodeGenerator.h"
3434#include "DFGDriver.h"
3535#include "JIT.h"
 36#include "LLIntEntrypoints.h"
3637
3738namespace JSC {
3839
3940template<typename CodeBlockType>
4041inline bool jitCompileIfAppropriate(JSGlobalData& globalData, OwnPtr<CodeBlockType>& codeBlock, JITCode& jitCode, JITCode::JITType jitType)
4142{
 43 if (jitType == codeBlock->getJITType())
 44 return true;
 45
4246 if (!globalData.canUseJIT())
4347 return true;
4448
 49 codeBlock->unlinkIncomingCalls();
 50
4551 bool dfgCompiled = false;
4652 if (jitType == JITCode::DFGJIT)
4753 dfgCompiled = DFG::tryCompile(globalData, codeBlock.get(), jitCode);

@@inline bool jitCompileIfAppropriate(JSGl
6268
6369inline bool jitCompileFunctionIfAppropriate(JSGlobalData& globalData, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType)
6470{
 71 if (jitType == codeBlock->getJITType())
 72 return true;
 73
6574 if (!globalData.canUseJIT())
6675 return true;
6776
 77 codeBlock->unlinkIncomingCalls();
 78
6879 bool dfgCompiled = false;
6980 if (jitType == JITCode::DFGJIT)
7081 dfgCompiled = DFG::tryCompileFunction(globalData, codeBlock.get(), jitCode, jitCodeWithArityCheck);

@@inline bool jitCompileFunctionIfAppropri
7990 }
8091 jitCode = JIT::compile(&globalData, codeBlock.get(), &jitCodeWithArityCheck);
8192 }
82 
8393 codeBlock->setJITCode(jitCode, jitCodeWithArityCheck);
8494
8595 return true;
107713

Source/JavaScriptCore/jit/JITExceptions.cpp

@@ExceptionHandler genericThrow(JSGlobalDa
6464
6565ExceptionHandler jitThrow(JSGlobalData* globalData, ExecState* callFrame, JSValue exceptionValue, ReturnAddressPtr faultLocation)
6666{
67  return genericThrow(globalData, callFrame, exceptionValue, callFrame->codeBlock()->bytecodeOffset(faultLocation));
 67 return genericThrow(globalData, callFrame, exceptionValue, callFrame->codeBlock()->bytecodeOffset(callFrame, faultLocation));
6868}
6969
7070}
107713

Source/JavaScriptCore/jit/JITStubs.cpp

@@DEFINE_STUB_FUNCTION(void, op_put_by_id_
14461446 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
14471447 JSValue baseValue = stackFrame.args[0].jsValue();
14481448 ASSERT(baseValue.isObject());
 1449
14491450 asObject(baseValue)->putDirect(callFrame->globalData(), ident, stackFrame.args[2].jsValue(), slot);
14501451
14511452 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();

@@DEFINE_STUB_FUNCTION(void, optimize_from
19311932 unsigned bytecodeIndex = stackFrame.args[0].int32();
19321933
19331934#if ENABLE(JIT_VERBOSE_OSR)
1934  dataLog("Entered optimize_from_loop with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
 1935 dataLog("%p: Entered optimize_from_loop with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock, codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
19351936#endif
19361937
19371938 if (codeBlock->hasOptimizedReplacement()) {

@@DEFINE_STUB_FUNCTION(void*, op_construct
21862187 return result;
21872188}
21882189
2189 inline CallFrame* arityCheckFor(CallFrame* callFrame, RegisterFile* registerFile, CodeSpecializationKind kind)
2190 {
2191  JSFunction* callee = asFunction(callFrame->callee());
2192  ASSERT(!callee->isHostFunction());
2193  CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecodeFor(kind);
2194  int argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
2195 
2196  // This ensures enough space for the worst case scenario of zero arguments passed by the caller.
2197  if (!registerFile->grow(callFrame->registers() + newCodeBlock->numParameters() + newCodeBlock->m_numCalleeRegisters))
2198  return 0;
2199 
2200  ASSERT(argumentCountIncludingThis < newCodeBlock->numParameters());
2201 
2202  // Too few arguments -- copy call frame and arguments, then fill in missing arguments with undefined.
2203  size_t delta = newCodeBlock->numParameters() - argumentCountIncludingThis;
2204  Register* src = callFrame->registers();
2205  Register* dst = callFrame->registers() + delta;
2206 
2207  int i;
2208  int end = -CallFrame::offsetFor(argumentCountIncludingThis);
2209  for (i = -1; i >= end; --i)
2210  dst[i] = src[i];
2211 
2212  end -= delta;
2213  for ( ; i >= end; --i)
2214  dst[i] = jsUndefined();
2215 
2216  CallFrame* newCallFrame = CallFrame::create(dst);
2217  ASSERT((void*)newCallFrame <= registerFile->end());
2218  return newCallFrame;
2219 }
2220 
22212190DEFINE_STUB_FUNCTION(void*, op_call_arityCheck)
22222191{
22232192 STUB_INIT_STACK_FRAME(stackFrame);
22242193
22252194 CallFrame* callFrame = stackFrame.callFrame;
22262195
2227  CallFrame* newCallFrame = arityCheckFor(callFrame, stackFrame.registerFile, CodeForCall);
 2196 CallFrame* newCallFrame = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.registerFile, CodeForCall);
22282197 if (!newCallFrame)
22292198 return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createStackOverflowError(callFrame->callerFrame()));
22302199

@@DEFINE_STUB_FUNCTION(void*, op_construct
22372206
22382207 CallFrame* callFrame = stackFrame.callFrame;
22392208
2240  CallFrame* newCallFrame = arityCheckFor(callFrame, stackFrame.registerFile, CodeForConstruct);
 2209 CallFrame* newCallFrame = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.registerFile, CodeForConstruct);
22412210 if (!newCallFrame)
22422211 return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createStackOverflowError(callFrame->callerFrame()));
22432212
107713

Source/JavaScriptCore/jit/JSInterfaceJIT.h

2626#ifndef JSInterfaceJIT_h
2727#define JSInterfaceJIT_h
2828
 29#include "BytecodeConventions.h"
2930#include "JITCode.h"
3031#include "JITStubs.h"
 32#include "JSString.h"
3133#include "JSValue.h"
3234#include "MacroAssembler.h"
3335#include "RegisterFile.h"
107713

Source/JavaScriptCore/llint/LLIntCommon.h

 1/*
 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef LLIntCommon_h
 27#define LLIntCommon_h
 28
 29#define LLINT_EXECUTION_TRACING 0
 30#define LLINT_HELPER_TRACING 0
 31#define LLINT_ALWAYS_ALLOCATE_SLOW 0
 32
 33#endif // LLIntCommon_h
 34
0

Source/JavaScriptCore/llint/LLIntData.cpp

 1/*
 2 * Copyright (C) 2011 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27#include "LLIntData.h"
 28
 29#if ENABLE(LLINT)
 30
 31#include "Instruction.h"
 32#include "LowLevelInterpreter.h"
 33#include "Opcode.h"
 34
 35namespace JSC { namespace LLInt {
 36
 37Data::Data()
 38 : m_exceptionInstructions(new Instruction[maxOpcodeLength + 1])
 39 , m_opcodeMap(new Opcode[numOpcodeIDs])
 40{
 41 for (int i = 0; i < maxOpcodeLength + 1; ++i)
 42 m_exceptionInstructions[i].u.pointer = bitwise_cast<void*>(&llint_throw_from_helper_trampoline);
 43#define OPCODE_ENTRY(opcode, length) m_opcodeMap[opcode] = bitwise_cast<void*>(&llint_##opcode);
 44 FOR_EACH_OPCODE_ID(OPCODE_ENTRY);
 45#undef OPCODE_ENTRY
 46}
 47
 48Data::~Data()
 49{
 50 delete[] m_exceptionInstructions;
 51 delete[] m_opcodeMap;
 52}
 53
 54} } // namespace JSC::LLInt
 55
 56#endif // ENABLE(LLINT)
0

Source/JavaScriptCore/llint/LLIntData.h

 1/*
 2 * Copyright (C) 2011 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef LLIntData_h
 27#define LLIntData_h
 28
 29#include "Opcode.h"
 30#include <wtf/Platform.h>
 31
 32namespace JSC {
 33
 34struct Instruction;
 35
 36namespace LLInt {
 37
 38#if ENABLE(LLINT)
 39class Data {
 40public:
 41 Data();
 42 ~Data();
 43
 44 Instruction* exceptionInstructions()
 45 {
 46 return m_exceptionInstructions;
 47 }
 48
 49 Opcode* opcodeMap()
 50 {
 51 return m_opcodeMap;
 52 }
 53private:
 54 Instruction* m_exceptionInstructions;
 55 Opcode* m_opcodeMap;
 56};
 57#else // ENABLE(LLINT)
 58
 59#if COMPILER(CLANG)
 60#pragma clang diagnostic push
 61#pragma clang diagnostic ignored "-Wmissing-noreturn"
 62#endif
 63
 64class Data {
 65public:
 66 Instruction* exceptionInstructions()
 67 {
 68 ASSERT_NOT_REACHED();
 69 return 0;
 70 }
 71
 72 Opcode* opcodeMap()
 73 {
 74 ASSERT_NOT_REACHED();
 75 return 0;
 76 }
 77};
 78
 79#if COMPILER(CLANG)
 80#pragma clang diagnostic pop
 81#endif
 82
 83#endif // ENABLE(LLINT)
 84
 85} } // namespace JSC::LLInt
 86
 87#endif // LLIntData_h
 88
0

Source/JavaScriptCore/llint/LLIntEntrypoints.cpp

 1/*
 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27#include "LLIntEntrypoints.h"
 28
 29#if ENABLE(LLINT)
 30
 31#include "JITCode.h"
 32#include "JSGlobalData.h"
 33#include "LLIntThunks.h"
 34#include "LowLevelInterpreter.h"
 35
 36namespace JSC { namespace LLInt {
 37
 38void getFunctionEntrypoint(JSGlobalData& globalData, CodeSpecializationKind kind, JITCode& jitCode, MacroAssemblerCodePtr& arityCheck)
 39{
 40 if (!globalData.canUseJIT()) {
 41 if (kind == CodeForCall) {
 42 jitCode = JITCode::HostFunction(MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_function_for_call_prologue))));
 43 arityCheck = MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_function_for_call_arity_check));
 44 return;
 45 }
 46
 47 ASSERT(kind == CodeForConstruct);
 48 jitCode = JITCode::HostFunction(MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_function_for_construct_prologue))));
 49 arityCheck = MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_function_for_construct_arity_check));
 50 return;
 51 }
 52
 53 if (kind == CodeForCall) {
 54 jitCode = JITCode(globalData.getCTIStub(functionForCallEntryThunkGenerator), JITCode::InterpreterThunk);
 55 arityCheck = globalData.getCTIStub(functionForCallArityCheckThunkGenerator).code();
 56 return;
 57 }
 58
 59 ASSERT(kind == CodeForConstruct);
 60 jitCode = JITCode(globalData.getCTIStub(functionForConstructEntryThunkGenerator), JITCode::InterpreterThunk);
 61 arityCheck = globalData.getCTIStub(functionForConstructArityCheckThunkGenerator).code();
 62}
 63
 64void getEvalEntrypoint(JSGlobalData& globalData, JITCode& jitCode)
 65{
 66 if (!globalData.canUseJIT()) {
 67 jitCode = JITCode::HostFunction(MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_eval_prologue))));
 68 return;
 69 }
 70
 71 jitCode = JITCode(globalData.getCTIStub(evalEntryThunkGenerator), JITCode::InterpreterThunk);
 72}
 73
 74void getProgramEntrypoint(JSGlobalData& globalData, JITCode& jitCode)
 75{
 76 if (!globalData.canUseJIT()) {
 77 jitCode = JITCode::HostFunction(MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_program_prologue))));
 78 return;
 79 }
 80
 81 jitCode = JITCode(globalData.getCTIStub(programEntryThunkGenerator), JITCode::InterpreterThunk);
 82}
 83
 84} } // namespace JSC::LLInt
 85
 86#endif // ENABLE(LLINT)
0

Source/JavaScriptCore/llint/LLIntEntrypoints.h

 1/*
 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef LLIntEntrypoints_h
 27#define LLIntEntrypoints_h
 28
 29#include <wtf/Platform.h>
 30
 31#if ENABLE(LLINT)
 32
 33#include "CodeSpecializationKind.h"
 34
 35namespace JSC {
 36
 37class EvalCodeBlock;
 38class JITCode;
 39class JSGlobalData;
 40class MacroAssemblerCodePtr;
 41class MacroAssemblerCodeRef;
 42class ProgramCodeBlock;
 43
 44namespace LLInt {
 45
 46void getFunctionEntrypoint(JSGlobalData&, CodeSpecializationKind, JITCode&, MacroAssemblerCodePtr& arityCheck);
 47void getEvalEntrypoint(JSGlobalData&, JITCode&);
 48void getProgramEntrypoint(JSGlobalData&, JITCode&);
 49
 50inline void getEntrypoint(JSGlobalData& globalData, EvalCodeBlock*, JITCode& jitCode)
 51{
 52 getEvalEntrypoint(globalData, jitCode);
 53}
 54
 55inline void getEntrypoint(JSGlobalData& globalData, ProgramCodeBlock*, JITCode& jitCode)
 56{
 57 getProgramEntrypoint(globalData, jitCode);
 58}
 59
 60} } // namespace JSC::LLInt
 61
 62#endif // ENABLE(LLINT)
 63
 64#endif // LLIntEntrypoints_h
0

Source/JavaScriptCore/llint/LLIntExceptions.cpp

 1/*
 2 * Copyright (C) 2011 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27#include "LLIntExceptions.h"
 28
 29#if ENABLE(LLINT)
 30
 31#include "CallFrame.h"
 32#include "CodeBlock.h"
 33#include "Instruction.h"
 34#include "JITExceptions.h"
 35#include "LLIntCommon.h"
 36#include "LowLevelInterpreter.h"
 37
 38namespace JSC { namespace LLInt {
 39
 40void interpreterThrowInCaller(ExecState* exec)
 41{
 42 JSGlobalData* globalData = &exec->globalData();
 43#if LLINT_HELPER_TRACING
 44 dataLog("Throwing exception %s.\n", globalData->exception.description());
 45#endif
 46 genericThrow(
 47 globalData, exec->callerFrame(), globalData->exception,
 48 exec->callerFrame()->codeBlock()->bytecodeOffset(exec->callerFrame(), exec->returnPC()));
 49}
 50
 51Instruction* returnToThrowForThrownException(ExecState* exec)
 52{
 53 return exec->globalData().llintData.exceptionInstructions();
 54}
 55
 56Instruction* returnToThrow(ExecState* exec, Instruction* pc)
 57{
 58 JSGlobalData* globalData = &exec->globalData();
 59#if LLINT_HELPER_TRACING
 60 dataLog("Throwing exception %s (returnToThrow).\n", globalData->exception.description());
 61#endif
 62 genericThrow(globalData, exec, globalData->exception, pc - exec->codeBlock()->instructions().begin());
 63
 64 return globalData->llintData.exceptionInstructions();
 65}
 66
 67void* callToThrow(ExecState* exec, Instruction* pc)
 68{
 69 JSGlobalData* globalData = &exec->globalData();
 70#if LLINT_HELPER_TRACING
 71 dataLog("Throwing exception %s (callToThrow).\n", globalData->exception.description());
 72#endif
 73 genericThrow(globalData, exec, globalData->exception, pc - exec->codeBlock()->instructions().begin());
 74
 75 return bitwise_cast<void*>(&llint_throw_during_call_trampoline);
 76}
 77
 78} } // namespace JSC::LLInt
 79
 80#endif // ENABLE(LLINT)
0

Source/JavaScriptCore/llint/LLIntExceptions.h

 1/*
 2 * Copyright (C) 2011 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef LLIntExceptions_h
 27#define LLIntExceptions_h
 28
 29#include <wtf/Platform.h>
 30#include <wtf/StdLibExtras.h>
 31
 32#if ENABLE(LLINT)
 33
 34namespace JSC {
 35
 36class ExecState;
 37struct Instruction;
 38
 39namespace LLInt {
 40
 41// Throw the currently active exception in the context of the caller's call frame.
 42void interpreterThrowInCaller(ExecState*);
 43
 44// Tells you where to jump to if you want to return-to-throw, after you've already
 45// set up all information needed to throw the exception.
 46Instruction* returnToThrowForThrownException(ExecState*);
 47
 48// Saves the current PC in the global data for safe-keeping, and gives you a PC
 49// that you can tell the interpreter to go to, which when advanced between 1
 50// and 9 slots will give you an "instruction" that threads to the interpreter's
 51// exception handler. Note that if you give it the PC for exception handling,
 52// it's smart enough to just return that PC without doing anything else; this
 53// lets you thread exception handling through common helper functions used by
 54// other helpers.
 55Instruction* returnToThrow(ExecState*, Instruction*);
 56
 57// Use this when you're throwing to a call thunk.
 58void* callToThrow(ExecState*, Instruction*);
 59
 60} } // namespace JSC::LLInt
 61
 62#endif // ENABLE(LLINT)
 63
 64#endif // LLIntExceptions_h
0

Source/JavaScriptCore/llint/LLIntHelpers.cpp

 1/*
 2 * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27#include "LLIntHelpers.h"
 28
 29#if ENABLE(LLINT)
 30
 31#include "Arguments.h"
 32#include "CallFrame.h"
 33#include "CommonSlowPaths.h"
 34#include "GetterSetter.h"
 35#include "HostCallReturnValue.h"
 36#include "Interpreter.h"
 37#include "JIT.h"
 38#include "JITDriver.h"
 39#include "JSActivation.h"
 40#include "JSByteArray.h"
 41#include "JSGlobalObjectFunctions.h"
 42#include "JSPropertyNameIterator.h"
 43#include "JSStaticScopeObject.h"
 44#include "JSString.h"
 45#include "JSValue.h"
 46#include "LLIntCommon.h"
 47#include "LLIntExceptions.h"
 48#include "LowLevelInterpreter.h"
 49#include "Operations.h"
 50
 51namespace JSC { namespace LLInt {
 52
 53#define LLINT_BEGIN() NativeCallFrameTracer tracer(&exec->globalData(), exec)
 54
 55#define LLINT_OP(index) (exec->uncheckedR(pc[index].u.operand))
 56#define LLINT_OP_C(index) (exec->r(pc[index].u.operand))
 57
 58#define LLINT_RETURN_TWO(first, second) do { \
 59 union { \
 60 struct { \
 61 void* a; \
 62 void* b; \
 63 } pair; \
 64 int64_t i; \
 65 } __rt_u; \
 66 __rt_u.pair.a = first; \
 67 __rt_u.pair.b = second; \
 68 return __rt_u.i; \
 69 } while (false)
 70
 71#define LLINT_END_IMPL() LLINT_RETURN_TWO(pc, exec)
 72
 73#define LLINT_THROW(exceptionToThrow) do { \
 74 JSGlobalData& __t_globalData = exec->globalData(); \
 75 __t_globalData.exception = (exceptionToThrow); \
 76 pc = returnToThrow(exec, pc); \
 77 LLINT_END_IMPL(); \
 78 } while (false)
 79
 80#define LLINT_CHECK_EXCEPTION() do { \
 81 if (UNLIKELY(exec->globalData().exception)) { \
 82 pc = returnToThrow(exec, pc); \
 83 LLINT_END_IMPL(); \
 84 } \
 85 } while (false)
 86
 87#define LLINT_END() do { \
 88 LLINT_CHECK_EXCEPTION(); \
 89 LLINT_END_IMPL(); \
 90 } while (false)
 91
 92#define LLINT_BRANCH(opcode, condition) do { \
 93 bool __b_condition = (condition); \
 94 LLINT_CHECK_EXCEPTION(); \
 95 if (__b_condition) \
 96 pc += pc[OPCODE_LENGTH(opcode) - 1].u.operand; \
 97 else \
 98 pc += OPCODE_LENGTH(opcode); \
 99 LLINT_END_IMPL(); \
 100 } while (false)
 101
 102#define LLINT_RETURN(value) do { \
 103 JSValue __r_returnValue = (value); \
 104 LLINT_CHECK_EXCEPTION(); \
 105 LLINT_OP(1) = __r_returnValue; \
 106 LLINT_END_IMPL(); \
 107 } while (false)
 108
 109#define LLINT_RETURN_PROFILED(opcode, value) do { \
 110 JSValue __rp_returnValue = (value); \
 111 LLINT_CHECK_EXCEPTION(); \
 112 LLINT_OP(1) = __rp_returnValue; \
 113 pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \
 114 JSValue::encode(__rp_returnValue); \
 115 LLINT_END_IMPL(); \
 116 } while (false)
 117
 118#define LLINT_CALL_END_IMPL(exec, callTarget) LLINT_RETURN_TWO((callTarget), (exec))
 119
 120#define LLINT_CALL_THROW(exec, pc, exceptionToThrow) do { \
 121 ExecState* __ct_exec = (exec); \
 122 Instruction* __ct_pc = (pc); \
 123 JSGlobalData& __ct_globalData = (__ct_exec)->globalData(); \
 124 __ct_globalData.exception = (exceptionToThrow); \
 125 LLINT_CALL_END_IMPL(__ct_exec, callToThrow(__ct_exec, __ct_pc)); \
 126 } while (false)
 127
 128#define LLINT_CALL_CHECK_EXCEPTION(exec, pc) do { \
 129 ExecState* __cce_exec = (exec); \
 130 Instruction* __cce_pc = (pc); \
 131 if (UNLIKELY(__cce_exec->globalData().exception)) \
 132 LLINT_CALL_END_IMPL(__cce_exec, callToThrow(__cce_exec, __cce_pc)); \
 133 } while (false)
 134
 135#define LLINT_CALL_RETURN(exec, pc, callTarget) do { \
 136 ExecState* __cr_exec = (exec); \
 137 Instruction* __cr_pc = (pc); \
 138 void* __cr_callTarget = (callTarget); \
 139 LLINT_CALL_CHECK_EXCEPTION(__cr_exec->callerFrame(), __cr_pc); \
 140 LLINT_CALL_END_IMPL(__cr_exec, __cr_callTarget); \
 141 } while (false)
 142
 143extern "C" HelperReturnType llint_trace_operand(ExecState* exec, Instruction* pc, int fromWhere, int operand)
 144{
 145 dataLog("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d\n",
 146 exec->codeBlock(),
 147 exec,
 148 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
 149 exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode),
 150 fromWhere,
 151 operand,
 152 pc[operand].u.operand);
 153 LLINT_END();
 154}
 155
 156extern "C" HelperReturnType llint_trace_value(ExecState* exec, Instruction* pc, int fromWhere, int operand)
 157{
 158 JSValue value = LLINT_OP_C(operand).jsValue();
 159 union {
 160 struct {
 161 uint32_t tag;
 162 uint32_t payload;
 163 } bits;
 164 EncodedJSValue asValue;
 165 } u;
 166 u.asValue = JSValue::encode(value);
 167 dataLog("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d: %08x:%08x: %s\n",
 168 exec->codeBlock(),
 169 exec,
 170 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
 171 exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode),
 172 fromWhere,
 173 operand,
 174 pc[operand].u.operand,
 175 u.bits.tag,
 176 u.bits.payload,
 177 value.description());
 178 LLINT_END();
 179}
 180
 181LLINT_HELPER_DECL(trace_prologue)
 182{
 183 dataLog("%p / %p: in prologue.\n", exec->codeBlock(), exec);
 184 LLINT_END();
 185}
 186
 187static void traceFunctionPrologue(ExecState* exec, const char* comment, CodeSpecializationKind kind)
 188{
 189 JSFunction* callee = asFunction(exec->callee());
 190 FunctionExecutable* executable = callee->jsExecutable();
 191 CodeBlock* codeBlock = &executable->generatedBytecodeFor(kind);
 192 dataLog("%p / %p: in %s of function %p, executable %p; numVars = %u, numParameters = %u, numCalleeRegisters = %u.\n",
 193 codeBlock, exec, comment, callee, executable,
 194 codeBlock->m_numVars, codeBlock->numParameters(), codeBlock->m_numCalleeRegisters);
 195}
 196
 197LLINT_HELPER_DECL(trace_prologue_function_for_call)
 198{
 199 traceFunctionPrologue(exec, "call prologue", CodeForCall);
 200 LLINT_END();
 201}
 202
 203LLINT_HELPER_DECL(trace_prologue_function_for_construct)
 204{
 205 traceFunctionPrologue(exec, "construct prologue", CodeForConstruct);
 206 LLINT_END();
 207}
 208
 209LLINT_HELPER_DECL(trace_arityCheck_for_call)
 210{
 211 traceFunctionPrologue(exec, "call arity check", CodeForCall);
 212 LLINT_END();
 213}
 214
 215LLINT_HELPER_DECL(trace_arityCheck_for_construct)
 216{
 217 traceFunctionPrologue(exec, "construct arity check", CodeForConstruct);
 218 LLINT_END();
 219}
 220
 221LLINT_HELPER_DECL(trace)
 222{
 223 dataLog("%p / %p: executing bc#%zu, %s, scope %p\n",
 224 exec->codeBlock(),
 225 exec,
 226 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
 227 opcodeNames[exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode)],
 228 exec->scopeChain());
 229 LLINT_END();
 230}
 231
 232LLINT_HELPER_DECL(special_trace)
 233{
 234 dataLog("%p / %p: executing special case bc#%zu, op#%u, return PC is %p\n",
 235 exec->codeBlock(),
 236 exec,
 237 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
 238 exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode),
 239 exec->returnPC().value());
 240 LLINT_END();
 241}
 242
 243inline bool shouldJIT(ExecState* exec)
 244{
 245 // You can modify this to turn off JITting without rebuilding the world.
 246 return exec->globalData().canUseJIT();
 247}
 248
 249enum EntryKind { Prologue, ArityCheck };
 250static HelperReturnType entryOSR(ExecState* exec, Instruction* pc, CodeBlock* codeBlock, const char *name, EntryKind kind)
 251{
 252#if ENABLE(JIT_VERBOSE_OSR)
 253 dataLog("%p: Entered %s with executeCounter = %d\n", codeBlock, name, codeBlock->llintExecuteCounter());
 254#endif
 255
 256 if (!shouldJIT(exec)) {
 257 codeBlock->dontJITAnytimeSoon();
 258 LLINT_RETURN_TWO(0, exec);
 259 }
 260 if (!codeBlock->jitCompile(exec->globalData())) {
 261#if ENABLE(JIT_VERBOSE_OSR)
 262 dataLog(" Code was already compiled.\n");
 263#endif
 264 }
 265 codeBlock->jitSoon();
 266 if (kind == Prologue)
 267 LLINT_RETURN_TWO(codeBlock->getJITCode().executableAddressAtOffset(0), exec);
 268 ASSERT(kind == ArityCheck);
 269 LLINT_RETURN_TWO(codeBlock->getJITCodeWithArityCheck().executableAddress(), exec);
 270}
 271
 272LLINT_HELPER_DECL(entry_osr)
 273{
 274 return entryOSR(exec, pc, exec->codeBlock(), "entry_osr", Prologue);
 275}
 276
 277LLINT_HELPER_DECL(entry_osr_function_for_call)
 278{
 279 return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall), "entry_osr_function_for_call", Prologue);
 280}
 281
 282LLINT_HELPER_DECL(entry_osr_function_for_construct)
 283{
 284 return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct), "entry_osr_function_for_construct", Prologue);
 285}
 286
 287LLINT_HELPER_DECL(entry_osr_function_for_call_arityCheck)
 288{
 289 return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall), "entry_osr_function_for_call_arityCheck", ArityCheck);
 290}
 291
 292LLINT_HELPER_DECL(entry_osr_function_for_construct_arityCheck)
 293{
 294 return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct), "entry_osr_function_for_construct_arityCheck", ArityCheck);
 295}
 296
 297LLINT_HELPER_DECL(loop_osr)
 298{
 299 CodeBlock* codeBlock = exec->codeBlock();
 300
 301#if ENABLE(JIT_VERBOSE_OSR)
 302 dataLog("%p: Entered loop_osr with executeCounter = %d\n", codeBlock, codeBlock->llintExecuteCounter());
 303#endif
 304
 305 if (!shouldJIT(exec)) {
 306 codeBlock->dontJITAnytimeSoon();
 307 LLINT_RETURN_TWO(0, exec);
 308 }
 309
 310 if (!codeBlock->jitCompile(exec->globalData())) {
 311#if ENABLE(JIT_VERBOSE_OSR)
 312 dataLog(" Code was already compiled.\n");
 313#endif
 314 }
 315 codeBlock->jitSoon();
 316
 317 ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT);
 318
 319 Vector<BytecodeAndMachineOffset> map;
 320 codeBlock->jitCodeMap()->decode(map);
 321 BytecodeAndMachineOffset* mapping = binarySearch<BytecodeAndMachineOffset, unsigned, BytecodeAndMachineOffset::getBytecodeIndex>(map.begin(), map.size(), pc - codeBlock->instructions().begin());
 322 ASSERT(mapping);
 323 ASSERT(mapping->m_bytecodeIndex == static_cast<unsigned>(pc - codeBlock->instructions().begin()));
 324
 325 void* jumpTarget = codeBlock->getJITCode().executableAddressAtOffset(mapping->m_machineCodeOffset);
 326 ASSERT(jumpTarget);
 327
 328 LLINT_RETURN_TWO(jumpTarget, exec);
 329}
 330
 331LLINT_HELPER_DECL(replace)
 332{
 333 CodeBlock* codeBlock = exec->codeBlock();
 334
 335#if ENABLE(JIT_VERBOSE_OSR)
 336 dataLog("%p: Entered replace with executeCounter = %d\n", codeBlock, codeBlock->llintExecuteCounter());
 337#endif
 338
 339 if (shouldJIT(exec)) {
 340 if (!codeBlock->jitCompile(exec->globalData())) {
 341#if ENABLE(JIT_VERBOSE_OSR)
 342 dataLog(" Code was already compiled.\n");
 343#endif
 344 }
 345 codeBlock->jitSoon();
 346 } else
 347 codeBlock->dontJITAnytimeSoon();
 348 LLINT_END();
 349}
 350
 351LLINT_HELPER_DECL(register_file_check)
 352{
 353 LLINT_BEGIN();
 354#if LLINT_HELPER_TRACING
 355 dataLog("Checking stack height with exec = %p.\n", exec);
 356 dataLog("CodeBlock = %p.\n", exec->codeBlock());
 357 dataLog("Num callee registers = %u.\n", exec->codeBlock()->m_numCalleeRegisters);
 358 dataLog("Num vars = %u.\n", exec->codeBlock()->m_numVars);
 359 dataLog("Current end is at %p.\n", exec->globalData().interpreter->registerFile().end());
 360#endif
 361 ASSERT(&exec->registers()[exec->codeBlock()->m_numCalleeRegisters] > exec->globalData().interpreter->registerFile().end());
 362 if (UNLIKELY(!exec->globalData().interpreter->registerFile().grow(&exec->registers()[exec->codeBlock()->m_numCalleeRegisters]))) {
 363 exec = exec->callerFrame();
 364 exec->globalData().exception = createStackOverflowError(exec);
 365 interpreterThrowInCaller(exec);
 366 pc = returnToThrowForThrownException(exec);
 367 }
 368 LLINT_END_IMPL();
 369}
 370
 371LLINT_HELPER_DECL(helper_call_arityCheck)
 372{
 373 LLINT_BEGIN();
 374 ExecState* newExec = CommonSlowPaths::arityCheckFor(exec, &exec->globalData().interpreter->registerFile(), CodeForCall);
 375 if (!newExec) {
 376 exec = exec->callerFrame();
 377 exec->globalData().exception = createStackOverflowError(exec);
 378 interpreterThrowInCaller(exec);
 379 LLINT_RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
 380 }
 381 LLINT_RETURN_TWO(0, newExec);
 382}
 383
 384LLINT_HELPER_DECL(helper_construct_arityCheck)
 385{
 386 LLINT_BEGIN();
 387 ExecState* newExec = CommonSlowPaths::arityCheckFor(exec, &exec->globalData().interpreter->registerFile(), CodeForConstruct);
 388 if (!newExec) {
 389 exec = exec->callerFrame();
 390 exec->globalData().exception = createStackOverflowError(exec);
 391 interpreterThrowInCaller(exec);
 392 LLINT_RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
 393 }
 394 LLINT_RETURN_TWO(0, newExec);
 395}
 396
 397LLINT_HELPER_DECL(helper_create_activation)
 398{
 399 LLINT_BEGIN();
 400#if LLINT_HELPER_TRACING
 401 dataLog("Creating an activation, exec = %p!\n", exec);
 402#endif
 403 JSActivation* activation = JSActivation::create(exec->globalData(), exec, static_cast<FunctionExecutable*>(exec->codeBlock()->ownerExecutable()));
 404 exec->setScopeChain(exec->scopeChain()->push(activation));
 405 LLINT_RETURN(JSValue(activation));
 406}
 407
 408LLINT_HELPER_DECL(helper_create_arguments)
 409{
 410 LLINT_BEGIN();
 411 JSValue arguments = JSValue(Arguments::create(exec->globalData(), exec));
 412 LLINT_CHECK_EXCEPTION();
 413 exec->uncheckedR(pc[1].u.operand) = arguments;
 414 exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)) = arguments;
 415 LLINT_END();
 416}
 417
 418LLINT_HELPER_DECL(helper_create_this)
 419{
 420 LLINT_BEGIN();
 421 JSFunction* constructor = asFunction(exec->callee());
 422
 423#if !ASSERT_DISABLED
 424 ConstructData constructData;
 425 ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
 426#endif
 427
 428 Structure* structure;
 429 JSValue proto = LLINT_OP(2).jsValue();
 430 if (proto.isObject())
 431 structure = asObject(proto)->inheritorID(exec->globalData());
 432 else
 433 structure = constructor->scope()->globalObject->emptyObjectStructure();
 434
 435 LLINT_RETURN(constructEmptyObject(exec, structure));
 436}
 437
 438LLINT_HELPER_DECL(helper_convert_this)
 439{
 440 LLINT_BEGIN();
 441 JSValue v1 = LLINT_OP(1).jsValue();
 442 ASSERT(v1.isPrimitive());
 443 LLINT_RETURN(v1.toThisObject(exec));
 444}
 445
 446LLINT_HELPER_DECL(helper_new_object)
 447{
 448 LLINT_BEGIN();
 449 LLINT_RETURN(constructEmptyObject(exec));
 450}
 451
 452LLINT_HELPER_DECL(helper_new_array)
 453{
 454 LLINT_BEGIN();
 455 LLINT_RETURN(constructArray(exec, bitwise_cast<JSValue*>(&LLINT_OP(2)), pc[3].u.operand));
 456}
 457
 458LLINT_HELPER_DECL(helper_new_array_buffer)
 459{
 460 LLINT_BEGIN();
 461 LLINT_RETURN(constructArray(exec, exec->codeBlock()->constantBuffer(pc[2].u.operand), pc[3].u.operand));
 462}
 463
 464LLINT_HELPER_DECL(helper_new_regexp)
 465{
 466 LLINT_BEGIN();
 467 RegExp* regExp = exec->codeBlock()->regexp(pc[2].u.operand);
 468 if (!regExp->isValid())
 469 LLINT_THROW(createSyntaxError(exec, "Invalid flag supplied to RegExp constructor."));
 470 LLINT_RETURN(RegExpObject::create(exec->globalData(), exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regExp));
 471}
 472
 473LLINT_HELPER_DECL(helper_not)
 474{
 475 LLINT_BEGIN();
 476 LLINT_RETURN(jsBoolean(!LLINT_OP_C(2).jsValue().toBoolean(exec)));
 477}
 478
 479LLINT_HELPER_DECL(helper_eq)
 480{
 481 LLINT_BEGIN();
 482 LLINT_RETURN(jsBoolean(JSValue::equal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
 483}
 484
 485LLINT_HELPER_DECL(helper_neq)
 486{
 487 LLINT_BEGIN();
 488 LLINT_RETURN(jsBoolean(!JSValue::equal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
 489}
 490
 491LLINT_HELPER_DECL(helper_stricteq)
 492{
 493 LLINT_BEGIN();
 494 LLINT_RETURN(jsBoolean(JSValue::strictEqual(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
 495}
 496
 497LLINT_HELPER_DECL(helper_nstricteq)
 498{
 499 LLINT_BEGIN();
 500 LLINT_RETURN(jsBoolean(!JSValue::strictEqual(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
 501}
 502
 503LLINT_HELPER_DECL(helper_less)
 504{
 505 LLINT_BEGIN();
 506 LLINT_RETURN(jsBoolean(jsLess<true>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
 507}
 508
 509LLINT_HELPER_DECL(helper_lesseq)
 510{
 511 LLINT_BEGIN();
 512 LLINT_RETURN(jsBoolean(jsLessEq<true>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
 513}
 514
 515LLINT_HELPER_DECL(helper_greater)
 516{
 517 LLINT_BEGIN();
 518 LLINT_RETURN(jsBoolean(jsLess<false>(exec, LLINT_OP_C(3).jsValue(), LLINT_OP_C(2).jsValue())));
 519}
 520
 521LLINT_HELPER_DECL(helper_greatereq)
 522{
 523 LLINT_BEGIN();
 524 LLINT_RETURN(jsBoolean(jsLessEq<false>(exec, LLINT_OP_C(3).jsValue(), LLINT_OP_C(2).jsValue())));
 525}
 526
 527LLINT_HELPER_DECL(helper_pre_inc)
 528{
 529 LLINT_BEGIN();
 530 LLINT_RETURN(jsNumber(LLINT_OP(1).jsValue().toNumber(exec) + 1));
 531}
 532
 533LLINT_HELPER_DECL(helper_pre_dec)
 534{
 535 LLINT_BEGIN();
 536 LLINT_RETURN(jsNumber(LLINT_OP(1).jsValue().toNumber(exec) - 1));
 537}
 538
 539LLINT_HELPER_DECL(helper_post_inc)
 540{
 541 LLINT_BEGIN();
 542 double result = LLINT_OP(2).jsValue().toNumber(exec);
 543 LLINT_OP(2) = jsNumber(result + 1);
 544 LLINT_RETURN(jsNumber(result));
 545}
 546
 547LLINT_HELPER_DECL(helper_post_dec)
 548{
 549 LLINT_BEGIN();
 550 double result = LLINT_OP(2).jsValue().toNumber(exec);
 551 LLINT_OP(2) = jsNumber(result - 1);
 552 LLINT_RETURN(jsNumber(result));
 553}
 554
 555LLINT_HELPER_DECL(helper_to_jsnumber)
 556{
 557 LLINT_BEGIN();
 558 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec)));
 559}
 560
 561LLINT_HELPER_DECL(helper_negate)
 562{
 563 LLINT_BEGIN();
 564 LLINT_RETURN(jsNumber(-LLINT_OP_C(2).jsValue().toNumber(exec)));
 565}
 566
 567LLINT_HELPER_DECL(helper_add)
 568{
 569 LLINT_BEGIN();
 570 JSValue v1 = LLINT_OP_C(2).jsValue();
 571 JSValue v2 = LLINT_OP_C(3).jsValue();
 572
 573#if LLINT_HELPER_TRACING
 574 dataLog("Trying to add %s", v1.description());
 575 dataLog(" to %s.\n", v2.description());
 576#endif
 577
 578 if (v1.isString() && !v2.isObject())
 579 LLINT_RETURN(jsString(exec, asString(v1), v2.toString(exec)));
 580
 581 if (v1.isNumber() && v2.isNumber())
 582 LLINT_RETURN(jsNumber(v1.asNumber() + v2.asNumber()));
 583
 584 LLINT_RETURN(jsAddSlowCase(exec, v1, v2));
 585}
 586
 587LLINT_HELPER_DECL(helper_mul)
 588{
 589 LLINT_BEGIN();
 590 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) * LLINT_OP_C(3).jsValue().toNumber(exec)));
 591}
 592
 593LLINT_HELPER_DECL(helper_sub)
 594{
 595 LLINT_BEGIN();
 596 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) - LLINT_OP_C(3).jsValue().toNumber(exec)));
 597}
 598
 599LLINT_HELPER_DECL(helper_div)
 600{
 601 LLINT_BEGIN();
 602 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) / LLINT_OP_C(3).jsValue().toNumber(exec)));
 603}
 604
 605LLINT_HELPER_DECL(helper_mod)
 606{
 607 LLINT_BEGIN();
 608 LLINT_RETURN(jsNumber(fmod(LLINT_OP_C(2).jsValue().toNumber(exec), LLINT_OP_C(3).jsValue().toNumber(exec))));
 609}
 610
 611LLINT_HELPER_DECL(helper_lshift)
 612{
 613 LLINT_BEGIN();
 614 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) << (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
 615}
 616
 617LLINT_HELPER_DECL(helper_rshift)
 618{
 619 LLINT_BEGIN();
 620 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) >> (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
 621}
 622
 623LLINT_HELPER_DECL(helper_urshift)
 624{
 625 LLINT_BEGIN();
 626 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toUInt32(exec) >> (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
 627}
 628
 629LLINT_HELPER_DECL(helper_bitand)
 630{
 631 LLINT_BEGIN();
 632 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) & LLINT_OP_C(3).jsValue().toInt32(exec)));
 633}
 634
 635LLINT_HELPER_DECL(helper_bitor)
 636{
 637 LLINT_BEGIN();
 638 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) | LLINT_OP_C(3).jsValue().toInt32(exec)));
 639}
 640
 641LLINT_HELPER_DECL(helper_bitxor)
 642{
 643 LLINT_BEGIN();
 644 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) ^ LLINT_OP_C(3).jsValue().toInt32(exec)));
 645}
 646
 647LLINT_HELPER_DECL(helper_bitnot)
 648{
 649 LLINT_BEGIN();
 650 LLINT_RETURN(jsNumber(~LLINT_OP_C(2).jsValue().toInt32(exec)));
 651}
 652
 653LLINT_HELPER_DECL(helper_check_has_instance)
 654{
 655 LLINT_BEGIN();
 656 JSValue baseVal = LLINT_OP_C(1).jsValue();
 657#ifndef NDEBUG
 658 TypeInfo typeInfo(UnspecifiedType);
 659 ASSERT(!baseVal.isObject()
 660 || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance());
 661#endif
 662 LLINT_THROW(createInvalidParamError(exec, "instanceof", baseVal));
 663}
 664
 665LLINT_HELPER_DECL(helper_instanceof)
 666{
 667 LLINT_BEGIN();
 668 LLINT_RETURN(jsBoolean(CommonSlowPaths::opInstanceOfSlow(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue())));
 669}
 670
 671LLINT_HELPER_DECL(helper_typeof)
 672{
 673 LLINT_BEGIN();
 674 LLINT_RETURN(jsTypeStringForValue(exec, LLINT_OP_C(2).jsValue()));
 675}
 676
 677LLINT_HELPER_DECL(helper_is_undefined)
 678{
 679 LLINT_BEGIN();
 680 JSValue v = LLINT_OP_C(2).jsValue();
 681 LLINT_RETURN(jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined()));
 682}
 683
 684LLINT_HELPER_DECL(helper_is_boolean)
 685{
 686 LLINT_BEGIN();
 687 LLINT_RETURN(jsBoolean(LLINT_OP_C(2).jsValue().isBoolean()));
 688}
 689
 690LLINT_HELPER_DECL(helper_is_number)
 691{
 692 LLINT_BEGIN();
 693 LLINT_RETURN(jsBoolean(LLINT_OP_C(2).jsValue().isNumber()));
 694}
 695
 696LLINT_HELPER_DECL(helper_is_string)
 697{
 698 LLINT_BEGIN();
 699 LLINT_RETURN(jsBoolean(isJSString(LLINT_OP_C(2).jsValue())));
 700}
 701
 702LLINT_HELPER_DECL(helper_is_object)
 703{
 704 LLINT_BEGIN();
 705 LLINT_RETURN(jsBoolean(jsIsObjectType(LLINT_OP_C(2).jsValue())));
 706}
 707
 708LLINT_HELPER_DECL(helper_is_function)
 709{
 710 LLINT_BEGIN();
 711 LLINT_RETURN(jsBoolean(jsIsFunctionType(LLINT_OP_C(2).jsValue())));
 712}
 713
 714LLINT_HELPER_DECL(helper_in)
 715{
 716 LLINT_BEGIN();
 717 LLINT_RETURN(jsBoolean(CommonSlowPaths::opIn(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
 718}
 719
 720LLINT_HELPER_DECL(helper_resolve)
 721{
 722 LLINT_BEGIN();
 723 LLINT_RETURN_PROFILED(op_resolve, CommonSlowPaths::opResolve(exec, exec->codeBlock()->identifier(pc[2].u.operand)));
 724}
 725
 726LLINT_HELPER_DECL(helper_resolve_skip)
 727{
 728 LLINT_BEGIN();
 729 LLINT_RETURN_PROFILED(
 730 op_resolve_skip,
 731 CommonSlowPaths::opResolveSkip(
 732 exec,
 733 exec->codeBlock()->identifier(pc[2].u.operand),
 734 pc[3].u.operand));
 735}
 736
 737static JSValue resolveGlobal(ExecState* exec, Instruction* pc)
 738{
 739 CodeBlock* codeBlock = exec->codeBlock();
 740 JSGlobalObject* globalObject = codeBlock->globalObject();
 741 ASSERT(globalObject->isGlobalObject());
 742 int property = pc[2].u.operand;
 743 Structure* structure = pc[3].u.structure.get();
 744
 745 ASSERT_UNUSED(structure, structure != globalObject->structure());
 746
 747 Identifier& ident = codeBlock->identifier(property);
 748 PropertySlot slot(globalObject);
 749
 750 if (globalObject->getPropertySlot(exec, ident, slot)) {
 751 JSValue result = slot.getValue(exec, ident);
 752 if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary()
 753 && slot.slotBase() == globalObject) {
 754 pc[3].u.structure.set(
 755 exec->globalData(), codeBlock->ownerExecutable(), globalObject->structure());
 756 pc[4] = slot.cachedOffset();
 757 }
 758
 759 return result;
 760 }
 761
 762 exec->globalData().exception = createUndefinedVariableError(exec, ident);
 763 return JSValue();
 764}
 765
 766LLINT_HELPER_DECL(helper_resolve_global)
 767{
 768 LLINT_BEGIN();
 769 LLINT_RETURN_PROFILED(op_resolve_global, resolveGlobal(exec, pc));
 770}
 771
 772LLINT_HELPER_DECL(helper_resolve_global_dynamic)
 773{
 774 LLINT_BEGIN();
 775 LLINT_RETURN_PROFILED(op_resolve_global_dynamic, resolveGlobal(exec, pc));
 776}
 777
 778LLINT_HELPER_DECL(helper_resolve_for_resolve_global_dynamic)
 779{
 780 LLINT_BEGIN();
 781 LLINT_RETURN_PROFILED(op_resolve_global_dynamic, CommonSlowPaths::opResolve(exec, exec->codeBlock()->identifier(pc[2].u.operand)));
 782}
 783
 784LLINT_HELPER_DECL(helper_resolve_base)
 785{
 786 LLINT_BEGIN();
 787 Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
 788 if (pc[3].u.operand) {
 789 JSValue base = JSC::resolveBase(exec, ident, exec->scopeChain(), true);
 790 if (!base)
 791 LLINT_THROW(createErrorForInvalidGlobalAssignment(exec, ident.ustring()));
 792 LLINT_RETURN(base);
 793 }
 794
 795 LLINT_RETURN_PROFILED(op_resolve_base, JSC::resolveBase(exec, ident, exec->scopeChain(), false));
 796}
 797
 798LLINT_HELPER_DECL(helper_ensure_property_exists)
 799{
 800 LLINT_BEGIN();
 801 JSObject* object = asObject(LLINT_OP(1).jsValue());
 802 PropertySlot slot(object);
 803 Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
 804 if (!object->getPropertySlot(exec, ident, slot))
 805 LLINT_THROW(createErrorForInvalidGlobalAssignment(exec, ident.ustring()));
 806 LLINT_END();
 807}
 808
 809LLINT_HELPER_DECL(helper_resolve_with_base)
 810{
 811 LLINT_BEGIN();
 812 JSValue result = CommonSlowPaths::opResolveWithBase(exec, exec->codeBlock()->identifier(pc[3].u.operand), LLINT_OP(1));
 813 LLINT_CHECK_EXCEPTION();
 814 LLINT_OP(2) = result;
 815 // FIXME: technically should have profiling, but we don't do it because the DFG won't use it.
 816 LLINT_END();
 817}
 818
 819LLINT_HELPER_DECL(helper_resolve_with_this)
 820{
 821 LLINT_BEGIN();
 822 JSValue result = CommonSlowPaths::opResolveWithThis(exec, exec->codeBlock()->identifier(pc[3].u.operand), LLINT_OP(1));
 823 LLINT_CHECK_EXCEPTION();
 824 LLINT_OP(2) = result;
 825 // FIXME: technically should have profiling, but we don't do it because the DFG won't use it.
 826 LLINT_END();
 827}
 828
 829LLINT_HELPER_DECL(helper_get_by_id)
 830{
 831 LLINT_BEGIN();
 832 CodeBlock* codeBlock = exec->codeBlock();
 833 Identifier& ident = codeBlock->identifier(pc[3].u.operand);
 834 JSValue baseValue = LLINT_OP_C(2).jsValue();
 835 PropertySlot slot(baseValue);
 836
 837 JSValue result = baseValue.get(exec, ident, slot);
 838 LLINT_CHECK_EXCEPTION();
 839 LLINT_OP(1) = result;
 840
 841 if (baseValue.isCell()
 842 && slot.isCacheable()
 843 && slot.slotBase() == baseValue
 844 && slot.cachedPropertyType() == PropertySlot::Value) {
 845
 846 JSCell* baseCell = baseValue.asCell();
 847 Structure* structure = baseCell->structure();
 848
 849 if (!structure->isUncacheableDictionary()
 850 && !structure->typeInfo().prohibitsPropertyCaching()) {
 851 pc[4].u.structure.set(
 852 exec->globalData(), codeBlock->ownerExecutable(), structure);
 853 pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue);
 854 }
 855 }
 856
 857 pc[OPCODE_LENGTH(op_get_by_id) - 1].u.profile->m_buckets[0] = JSValue::encode(result);
 858 LLINT_END();
 859}
 860
 861LLINT_HELPER_DECL(helper_get_arguments_length)
 862{
 863 LLINT_BEGIN();
 864 CodeBlock* codeBlock = exec->codeBlock();
 865 Identifier& ident = codeBlock->identifier(pc[3].u.operand);
 866 JSValue baseValue = LLINT_OP(2).jsValue();
 867 PropertySlot slot(baseValue);
 868 LLINT_RETURN(baseValue.get(exec, ident, slot));
 869}
 870
 871LLINT_HELPER_DECL(helper_put_by_id)
 872{
 873 LLINT_BEGIN();
 874 CodeBlock* codeBlock = exec->codeBlock();
 875 Identifier& ident = codeBlock->identifier(pc[2].u.operand);
 876
 877 JSValue baseValue = LLINT_OP_C(1).jsValue();
 878 PutPropertySlot slot(codeBlock->isStrictMode());
 879 if (pc[8].u.operand)
 880 asObject(baseValue)->putDirect(exec->globalData(), ident, LLINT_OP_C(3).jsValue(), slot);
 881 else
 882 baseValue.put(exec, ident, LLINT_OP_C(3).jsValue(), slot);
 883 LLINT_CHECK_EXCEPTION();
 884
 885 if (baseValue.isCell()
 886 && slot.isCacheable()) {
 887
 888 JSCell* baseCell = baseValue.asCell();
 889 Structure* structure = baseCell->structure();
 890
 891 if (!structure->isUncacheableDictionary()
 892 && !structure->typeInfo().prohibitsPropertyCaching()
 893 && baseCell == slot.base()) {
 894
 895 if (slot.type() == PutPropertySlot::NewProperty) {
 896 if (!structure->isDictionary() && structure->previousID()->propertyStorageCapacity() == structure->propertyStorageCapacity()) {
 897 // This is needed because some of the methods we call
 898 // below may GC.
 899 pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id);
 900
 901 normalizePrototypeChain(exec, baseCell);
 902
 903 ASSERT(structure->previousID()->isObject());
 904 pc[4].u.structure.set(
 905 exec->globalData(), codeBlock->ownerExecutable(), structure->previousID());
 906 pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue);
 907 pc[6].u.structure.set(
 908 exec->globalData(), codeBlock->ownerExecutable(), structure);
 909 StructureChain* chain = structure->prototypeChain(exec);
 910 ASSERT(chain);
 911 pc[7].u.structureChain.set(
 912 exec->globalData(), codeBlock->ownerExecutable(), chain);
 913
 914 if (pc[8].u.operand)
 915 pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id_transition_direct);
 916 else
 917 pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id_transition_normal);
 918 }
 919 } else {
 920 pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id);
 921 pc[4].u.structure.set(
 922 exec->globalData(), codeBlock->ownerExecutable(), structure);
 923 pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue);
 924 }
 925 }
 926 }
 927
 928 LLINT_END();
 929}
 930
 931LLINT_HELPER_DECL(helper_del_by_id)
 932{
 933 LLINT_BEGIN();
 934 CodeBlock* codeBlock = exec->codeBlock();
 935 JSObject* baseObject = LLINT_OP_C(2).jsValue().toObject(exec);
 936 bool couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, codeBlock->identifier(pc[3].u.operand));
 937 LLINT_CHECK_EXCEPTION();
 938 if (!couldDelete && codeBlock->isStrictMode())
 939 LLINT_THROW(createTypeError(exec, "Unable to delete property."));
 940 LLINT_RETURN(jsBoolean(couldDelete));
 941}
 942
 943inline JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript)
 944{
 945 if (LIKELY(baseValue.isCell() && subscript.isString())) {
 946 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(exec, asString(subscript)->value(exec)))
 947 return result;
 948 }
 949
 950 if (subscript.isUInt32()) {
 951 uint32_t i = subscript.asUInt32();
 952 if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
 953 return asString(baseValue)->getIndex(exec, i);
 954
 955 if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i))
 956 return asByteArray(baseValue)->getIndex(exec, i);
 957
 958 return baseValue.get(exec, i);
 959 }
 960
 961 Identifier property(exec, subscript.toString(exec)->value(exec));
 962 return baseValue.get(exec, property);
 963}
 964
 965LLINT_HELPER_DECL(helper_get_by_val)
 966{
 967 LLINT_BEGIN();
 968 LLINT_RETURN_PROFILED(op_get_by_val, getByVal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue()));
 969}
 970
 971LLINT_HELPER_DECL(helper_get_argument_by_val)
 972{
 973 LLINT_BEGIN();
 974 JSValue arguments = LLINT_OP(2).jsValue();
 975 if (!arguments) {
 976 arguments = Arguments::create(exec->globalData(), exec);
 977 LLINT_CHECK_EXCEPTION();
 978 LLINT_OP(2) = arguments;
 979 exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)) = arguments;
 980 }
 981
 982 LLINT_RETURN(getByVal(exec, arguments, LLINT_OP_C(3).jsValue()));
 983}
 984
 985LLINT_HELPER_DECL(helper_get_by_pname)
 986{
 987 LLINT_BEGIN();
 988 LLINT_RETURN(getByVal(exec, LLINT_OP(2).jsValue(), LLINT_OP(3).jsValue()));
 989}
 990
 991LLINT_HELPER_DECL(helper_put_by_val)
 992{
 993 LLINT_BEGIN();
 994 JSGlobalData& globalData = exec->globalData();
 995
 996 JSValue baseValue = LLINT_OP_C(1).jsValue();
 997 JSValue subscript = LLINT_OP_C(2).jsValue();
 998 JSValue value = LLINT_OP_C(3).jsValue();
 999
 1000 if (LIKELY(subscript.isUInt32())) {
 1001 uint32_t i = subscript.asUInt32();
 1002 if (isJSArray(baseValue)) {
 1003 JSArray* jsArray = asArray(baseValue);
 1004 if (jsArray->canSetIndex(i))
 1005 jsArray->setIndex(globalData, i, value);
 1006 else
 1007 JSArray::putByIndex(jsArray, exec, i, value);
 1008 LLINT_END();
 1009 }
 1010 if (isJSByteArray(baseValue)
 1011 && asByteArray(baseValue)->canAccessIndex(i)) {
 1012 JSByteArray* jsByteArray = asByteArray(baseValue);
 1013 if (value.isInt32()) {
 1014 jsByteArray->setIndex(i, value.asInt32());
 1015 LLINT_END();
 1016 }
 1017 if (value.isNumber()) {
 1018 jsByteArray->setIndex(i, value.asNumber());
 1019 LLINT_END();
 1020 }
 1021 }
 1022 baseValue.put(exec, i, value);
 1023 LLINT_END();
 1024 }
 1025
 1026 Identifier property(exec, subscript.toString(exec)->value(exec));
 1027 LLINT_CHECK_EXCEPTION();
 1028 PutPropertySlot slot(exec->codeBlock()->isStrictMode());
 1029 baseValue.put(exec, property, value, slot);
 1030 LLINT_END();
 1031}
 1032
 1033LLINT_HELPER_DECL(helper_del_by_val)
 1034{
 1035 LLINT_BEGIN();
 1036 JSValue baseValue = LLINT_OP_C(2).jsValue();
 1037 JSObject* baseObject = baseValue.toObject(exec);
 1038
 1039 JSValue subscript = LLINT_OP_C(3).jsValue();
 1040
 1041 bool couldDelete;
 1042
 1043 uint32_t i;
 1044 if (subscript.getUInt32(i))
 1045 couldDelete = baseObject->methodTable()->deletePropertyByIndex(baseObject, exec, i);
 1046 else {
 1047 LLINT_CHECK_EXCEPTION();
 1048 Identifier property(exec, subscript.toString(exec)->value(exec));
 1049 LLINT_CHECK_EXCEPTION();
 1050 couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, property);
 1051 }
 1052
 1053 if (!couldDelete && exec->codeBlock()->isStrictMode())
 1054 LLINT_THROW(createTypeError(exec, "Unable to delete property."));
 1055
 1056 LLINT_RETURN(jsBoolean(couldDelete));
 1057}
 1058
 1059LLINT_HELPER_DECL(helper_put_by_index)
 1060{
 1061 LLINT_BEGIN();
 1062 LLINT_OP_C(1).jsValue().put(exec, pc[2].u.operand, LLINT_OP_C(3).jsValue());
 1063 LLINT_END();
 1064}
 1065
 1066LLINT_HELPER_DECL(helper_put_getter_setter)
 1067{
 1068 LLINT_BEGIN();
 1069 ASSERT(LLINT_OP(1).jsValue().isObject());
 1070 JSObject* baseObj = asObject(LLINT_OP(1).jsValue());
 1071
 1072 GetterSetter* accessor = GetterSetter::create(exec);
 1073 LLINT_CHECK_EXCEPTION();
 1074
 1075 JSValue getter = LLINT_OP(3).jsValue();
 1076 JSValue setter = LLINT_OP(4).jsValue();
 1077 ASSERT(getter.isObject() || getter.isUndefined());
 1078 ASSERT(setter.isObject() || setter.isUndefined());
 1079 ASSERT(getter.isObject() || setter.isObject());
 1080
 1081 if (!getter.isUndefined())
 1082 accessor->setGetter(exec->globalData(), asObject(getter));
 1083 if (!setter.isUndefined())
 1084 accessor->setSetter(exec->globalData(), asObject(setter));
 1085 baseObj->putDirectAccessor(
 1086 exec->globalData(),
 1087 exec->codeBlock()->identifier(pc[2].u.operand),
 1088 accessor, Accessor);
 1089 LLINT_END();
 1090}
 1091
 1092LLINT_HELPER_DECL(helper_jmp_scopes)
 1093{
 1094 LLINT_BEGIN();
 1095 unsigned count = pc[1].u.operand;
 1096 ScopeChainNode* tmp = exec->scopeChain();
 1097 while (count--)
 1098 tmp = tmp->pop();
 1099 exec->setScopeChain(tmp);
 1100 pc += pc[2].u.operand;
 1101 LLINT_END();
 1102}
 1103
 1104LLINT_HELPER_DECL(helper_jtrue)
 1105{
 1106 LLINT_BEGIN();
 1107 LLINT_BRANCH(op_jtrue, LLINT_OP_C(1).jsValue().toBoolean(exec));
 1108}
 1109
 1110LLINT_HELPER_DECL(helper_jfalse)
 1111{
 1112 LLINT_BEGIN();
 1113 LLINT_BRANCH(op_jfalse, !LLINT_OP_C(1).jsValue().toBoolean(exec));
 1114}
 1115
 1116LLINT_HELPER_DECL(helper_jless)
 1117{
 1118 LLINT_BEGIN();
 1119 LLINT_BRANCH(op_jless, jsLess<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
 1120}
 1121
 1122LLINT_HELPER_DECL(helper_jnless)
 1123{
 1124 LLINT_BEGIN();
 1125 LLINT_BRANCH(op_jnless, !jsLess<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
 1126}
 1127
 1128LLINT_HELPER_DECL(helper_jgreater)
 1129{
 1130 LLINT_BEGIN();
 1131 LLINT_BRANCH(op_jgreater, jsLess<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
 1132}
 1133
 1134LLINT_HELPER_DECL(helper_jngreater)
 1135{
 1136 LLINT_BEGIN();
 1137 LLINT_BRANCH(op_jngreater, !jsLess<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
 1138}
 1139
 1140LLINT_HELPER_DECL(helper_jlesseq)
 1141{
 1142 LLINT_BEGIN();
 1143 LLINT_BRANCH(op_jlesseq, jsLessEq<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
 1144}
 1145
 1146LLINT_HELPER_DECL(helper_jnlesseq)
 1147{
 1148 LLINT_BEGIN();
 1149 LLINT_BRANCH(op_jnlesseq, !jsLessEq<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
 1150}
 1151
 1152LLINT_HELPER_DECL(helper_jgreatereq)
 1153{
 1154 LLINT_BEGIN();
 1155 LLINT_BRANCH(op_jgreatereq, jsLessEq<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
 1156}
 1157
 1158LLINT_HELPER_DECL(helper_jngreatereq)
 1159{
 1160 LLINT_BEGIN();
 1161 LLINT_BRANCH(op_jngreatereq, !jsLessEq<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
 1162}
 1163
 1164LLINT_HELPER_DECL(helper_switch_imm)
 1165{
 1166 LLINT_BEGIN();
 1167 JSValue scrutinee = LLINT_OP_C(3).jsValue();
 1168 ASSERT(scrutinee.isDouble());
 1169 double value = scrutinee.asDouble();
 1170 int32_t intValue = static_cast<int32_t>(value);
 1171 int defaultOffset = pc[2].u.operand;
 1172 if (value == intValue) {
 1173 CodeBlock* codeBlock = exec->codeBlock();
 1174 pc += codeBlock->immediateSwitchJumpTable(pc[1].u.operand).offsetForValue(intValue, defaultOffset);
 1175 } else
 1176 pc += defaultOffset;
 1177 LLINT_END();
 1178}
 1179
 1180LLINT_HELPER_DECL(helper_switch_string)
 1181{
 1182 LLINT_BEGIN();
 1183 JSValue scrutinee = LLINT_OP_C(3).jsValue();
 1184 int defaultOffset = pc[2].u.operand;
 1185 if (!scrutinee.isString())
 1186 pc += defaultOffset;
 1187 else {
 1188 CodeBlock* codeBlock = exec->codeBlock();
 1189 pc += codeBlock->stringSwitchJumpTable(pc[1].u.operand).offsetForValue(asString(scrutinee)->value(exec).impl(), defaultOffset);
 1190 }
 1191 LLINT_END();
 1192}
 1193
 1194LLINT_HELPER_DECL(helper_new_func)
 1195{
 1196 LLINT_BEGIN();
 1197 CodeBlock* codeBlock = exec->codeBlock();
 1198 ASSERT(codeBlock->codeType() != FunctionCode
 1199 || !codeBlock->needsFullScopeChain()
 1200 || exec->uncheckedR(codeBlock->activationRegister()).jsValue());
 1201#if LLINT_HELPER_TRACING
 1202 dataLog("Creating function!\n");
 1203#endif
 1204 LLINT_RETURN(codeBlock->functionDecl(pc[2].u.operand)->make(exec, exec->scopeChain()));
 1205}
 1206
 1207LLINT_HELPER_DECL(helper_new_func_exp)
 1208{
 1209 LLINT_BEGIN();
 1210 CodeBlock* codeBlock = exec->codeBlock();
 1211 FunctionExecutable* function = codeBlock->functionExpr(pc[2].u.operand);
 1212 JSFunction* func = function->make(exec, exec->scopeChain());
 1213
 1214 if (!function->name().isNull()) {
 1215 JSStaticScopeObject* functionScopeObject = JSStaticScopeObject::create(exec, function->name(), func, ReadOnly | DontDelete);
 1216 func->setScope(exec->globalData(), func->scope()->push(functionScopeObject));
 1217 }
 1218
 1219 LLINT_RETURN(func);
 1220}
 1221
 1222static HelperReturnType handleHostCall(ExecState* execCallee, Instruction* pc, JSValue callee, CodeSpecializationKind kind)
 1223{
 1224 ExecState* exec = execCallee->callerFrame();
 1225 JSGlobalData* globalData = &exec->globalData();
 1226
 1227 execCallee->setScopeChain(exec->scopeChain());
 1228 execCallee->setCodeBlock(0);
 1229
 1230 if (kind == CodeForCall) {
 1231 CallData callData;
 1232 CallType callType = getCallData(callee, callData);
 1233
 1234 ASSERT(callType != CallTypeJS);
 1235
 1236 if (callType == CallTypeHost) {
 1237 globalData->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
 1238
 1239 LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
 1240 }
 1241
 1242#if LLINT_HELPER_TRACING
 1243 dataLog("Call callee is not a function: %s\n", callee.description());
 1244#endif
 1245
 1246 ASSERT(callType == CallTypeNone);
 1247 LLINT_CALL_THROW(exec, pc, createNotAFunctionError(exec, callee));
 1248 }
 1249
 1250 ASSERT(kind == CodeForConstruct);
 1251
 1252 ConstructData constructData;
 1253 ConstructType constructType = getConstructData(callee, constructData);
 1254
 1255 ASSERT(constructType != ConstructTypeJS);
 1256
 1257 if (constructType == ConstructTypeHost) {
 1258 globalData->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
 1259
 1260 LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
 1261 }
 1262
 1263#if LLINT_HELPER_TRACING
 1264 dataLog("Constructor callee is not a function: %s\n", callee.description());
 1265#endif
 1266
 1267 ASSERT(constructType == ConstructTypeNone);
 1268 LLINT_CALL_THROW(exec, pc, createNotAConstructorError(exec, callee));
 1269}
 1270
 1271inline HelperReturnType setUpCall(ExecState* execCallee, Instruction* pc, CodeSpecializationKind kind, JSValue calleeAsValue, LLIntCallLinkInfo* callLinkInfo = 0)
 1272{
 1273 JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
 1274 if (!calleeAsFunctionCell)
 1275 return handleHostCall(execCallee, pc, calleeAsValue, kind);
 1276
 1277 JSFunction* callee = asFunction(calleeAsFunctionCell);
 1278 execCallee->setScopeChain(callee->scopeUnchecked());
 1279 ExecutableBase* executable = callee->executable();
 1280
 1281 MacroAssemblerCodePtr codePtr;
 1282 CodeBlock* codeBlock = 0;
 1283 if (executable->isHostFunction())
 1284 codePtr = executable->generatedJITCodeFor(kind).addressForCall();
 1285 else {
 1286 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
 1287 JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind);
 1288 if (error)
 1289 LLINT_CALL_THROW(execCallee->callerFrame(), pc, error);
 1290 codeBlock = &functionExecutable->generatedBytecodeFor(kind);
 1291 ASSERT(codeBlock);
 1292 if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
 1293 codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
 1294 else
 1295 codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
 1296 }
 1297
 1298 if (callLinkInfo) {
 1299 if (callLinkInfo->isOnList())
 1300 callLinkInfo->remove();
 1301 ExecState* execCaller = execCallee->callerFrame();
 1302 callLinkInfo->callee.set(execCaller->globalData(), execCaller->codeBlock()->ownerExecutable(), callee);
 1303 callLinkInfo->lastSeenCallee.set(execCaller->globalData(), execCaller->codeBlock()->ownerExecutable(), callee);
 1304 callLinkInfo->machineCodeTarget = codePtr;
 1305 if (codeBlock)
 1306 codeBlock->linkIncomingCall(callLinkInfo);
 1307 }
 1308
 1309 LLINT_CALL_RETURN(execCallee, pc, codePtr.executableAddress());
 1310}
 1311
 1312inline HelperReturnType genericCall(ExecState* exec, Instruction* pc, CodeSpecializationKind kind)
 1313{
 1314 // This needs to:
 1315 // - Set up a call frame.
 1316 // - Figure out what to call and compile it if necessary.
 1317 // - If possible, link the call's inline cache.
 1318 // - Return a tuple of machine code address to call and the new call frame.
 1319
 1320 JSValue calleeAsValue = LLINT_OP_C(1).jsValue();
 1321
 1322 ExecState* execCallee = exec + pc[3].u.operand;
 1323
 1324 execCallee->setArgumentCountIncludingThis(pc[2].u.operand);
 1325 execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue;
 1326 execCallee->setCallerFrame(exec);
 1327
 1328 ASSERT(pc[4].u.callLinkInfo);
 1329 return setUpCall(execCallee, pc, kind, calleeAsValue, pc[4].u.callLinkInfo);
 1330}
 1331
 1332LLINT_HELPER_DECL(helper_call)
 1333{
 1334 LLINT_BEGIN();
 1335 return genericCall(exec, pc, CodeForCall);
 1336}
 1337
 1338LLINT_HELPER_DECL(helper_construct)
 1339{
 1340 LLINT_BEGIN();
 1341 return genericCall(exec, pc, CodeForConstruct);
 1342}
 1343
 1344LLINT_HELPER_DECL(helper_call_varargs)
 1345{
 1346 LLINT_BEGIN();
 1347 // This needs to:
 1348 // - Set up a call frame while respecting the variable arguments.
 1349 // - Figure out what to call and compile it if necessary.
 1350 // - Return a tuple of machine code address to call and the new call frame.
 1351
 1352 JSValue calleeAsValue = LLINT_OP_C(1).jsValue();
 1353
 1354 ExecState* execCallee = loadVarargs(
 1355 exec, &exec->globalData().interpreter->registerFile(),
 1356 LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue(), pc[4].u.operand);
 1357 LLINT_CALL_CHECK_EXCEPTION(exec, pc);
 1358
 1359 execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue;
 1360 execCallee->setCallerFrame(exec);
 1361 exec->uncheckedR(RegisterFile::ArgumentCount).tag() = bitwise_cast<int32_t>(pc + OPCODE_LENGTH(op_call_varargs));
 1362
 1363 return setUpCall(execCallee, pc, CodeForCall, calleeAsValue);
 1364}
 1365
 1366LLINT_HELPER_DECL(helper_call_eval)
 1367{
 1368 LLINT_BEGIN();
 1369 JSValue calleeAsValue = LLINT_OP(1).jsValue();
 1370
 1371 ExecState* execCallee = exec + pc[3].u.operand;
 1372 JSGlobalData& globalData = exec->globalData();
 1373
 1374 execCallee->setArgumentCountIncludingThis(pc[2].u.operand);
 1375 execCallee->setCallerFrame(exec);
 1376 execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue;
 1377 execCallee->setScopeChain(exec->scopeChain());
 1378 execCallee->setReturnPC(bitwise_cast<Instruction*>(&llint_generic_return_point));
 1379 execCallee->setCodeBlock(0);
 1380 exec->uncheckedR(RegisterFile::ArgumentCount).tag() = bitwise_cast<int32_t>(pc + OPCODE_LENGTH(op_call_eval));
 1381
 1382 if (!isHostFunction(calleeAsValue, globalFuncEval))
 1383 return setUpCall(execCallee, pc, CodeForCall, calleeAsValue);
 1384
 1385 globalData.hostCallReturnValue = eval(execCallee);
 1386 LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
 1387}
 1388
 1389LLINT_HELPER_DECL(helper_tear_off_activation)
 1390{
 1391 LLINT_BEGIN();
 1392 ASSERT(exec->codeBlock()->needsFullScopeChain());
 1393 JSValue activationValue = LLINT_OP(1).jsValue();
 1394 if (!activationValue) {
 1395 if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)).jsValue()) {
 1396 if (!exec->codeBlock()->isStrictMode())
 1397 asArguments(v)->tearOff(exec);
 1398 }
 1399 LLINT_END();
 1400 }
 1401 JSActivation* activation = asActivation(activationValue);
 1402 activation->tearOff(exec->globalData());
 1403 if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)).jsValue())
 1404 asArguments(v)->didTearOffActivation(exec->globalData(), activation);
 1405 LLINT_END();
 1406}
 1407
 1408LLINT_HELPER_DECL(helper_tear_off_arguments)
 1409{
 1410 LLINT_BEGIN();
 1411 ASSERT(exec->codeBlock()->usesArguments() && !exec->codeBlock()->needsFullScopeChain());
 1412 asArguments(exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)).jsValue())->tearOff(exec);
 1413 LLINT_END();
 1414}
 1415
 1416LLINT_HELPER_DECL(helper_strcat)
 1417{
 1418 LLINT_BEGIN();
 1419 LLINT_RETURN(jsString(exec, &LLINT_OP(2), pc[3].u.operand));
 1420}
 1421
 1422LLINT_HELPER_DECL(helper_to_primitive)
 1423{
 1424 LLINT_BEGIN();
 1425 LLINT_RETURN(LLINT_OP_C(2).jsValue().toPrimitive(exec));
 1426}
 1427
 1428LLINT_HELPER_DECL(helper_get_pnames)
 1429{
 1430 LLINT_BEGIN();
 1431 JSValue v = LLINT_OP(2).jsValue();
 1432 if (v.isUndefinedOrNull()) {
 1433 pc += pc[5].u.operand;
 1434 LLINT_END();
 1435 }
 1436
 1437 JSObject* o = v.toObject(exec);
 1438 Structure* structure = o->structure();
 1439 JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
 1440 if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(exec))
 1441 jsPropertyNameIterator = JSPropertyNameIterator::create(exec, o);
 1442
 1443 LLINT_OP(1) = JSValue(jsPropertyNameIterator);
 1444 LLINT_OP(2) = JSValue(o);
 1445 LLINT_OP(3) = Register::withInt(0);
 1446 LLINT_OP(4) = Register::withInt(jsPropertyNameIterator->size());
 1447
 1448 pc += OPCODE_LENGTH(op_get_pnames);
 1449 LLINT_END();
 1450}
 1451
 1452LLINT_HELPER_DECL(helper_next_pname)
 1453{
 1454 LLINT_BEGIN();
 1455 JSObject* base = asObject(LLINT_OP(2).jsValue());
 1456 JSString* property = asString(LLINT_OP(1).jsValue());
 1457 if (base->hasProperty(exec, Identifier(exec, property->value(exec)))) {
 1458 // Go to target.
 1459 pc += pc[6].u.operand;
 1460 } // Else, don't change the PC, so the interpreter will reloop.
 1461 LLINT_END();
 1462}
 1463
 1464LLINT_HELPER_DECL(helper_push_scope)
 1465{
 1466 LLINT_BEGIN();
 1467 JSValue v = LLINT_OP(1).jsValue();
 1468 JSObject* o = v.toObject(exec);
 1469 LLINT_CHECK_EXCEPTION();
 1470
 1471 LLINT_OP(1) = o;
 1472 exec->setScopeChain(exec->scopeChain()->push(o));
 1473
 1474 LLINT_END();
 1475}
 1476
 1477LLINT_HELPER_DECL(helper_pop_scope)
 1478{
 1479 LLINT_BEGIN();
 1480 exec->setScopeChain(exec->scopeChain()->pop());
 1481 LLINT_END();
 1482}
 1483
 1484LLINT_HELPER_DECL(helper_push_new_scope)
 1485{
 1486 LLINT_BEGIN();
 1487 CodeBlock* codeBlock = exec->codeBlock();
 1488 JSObject* scope = JSStaticScopeObject::create(exec, codeBlock->identifier(pc[2].u.operand), LLINT_OP(3).jsValue(), DontDelete);
 1489 exec->setScopeChain(exec->scopeChain()->push(scope));
 1490 LLINT_RETURN(scope);
 1491}
 1492
 1493LLINT_HELPER_DECL(helper_throw)
 1494{
 1495 LLINT_BEGIN();
 1496 LLINT_THROW(LLINT_OP_C(1).jsValue());
 1497}
 1498
 1499LLINT_HELPER_DECL(helper_throw_reference_error)
 1500{
 1501 LLINT_BEGIN();
 1502 LLINT_THROW(createReferenceError(exec, LLINT_OP_C(1).jsValue().toString(exec)->value(exec)));
 1503}
 1504
 1505LLINT_HELPER_DECL(helper_debug)
 1506{
 1507 LLINT_BEGIN();
 1508 int debugHookID = pc[1].u.operand;
 1509 int firstLine = pc[2].u.operand;
 1510 int lastLine = pc[3].u.operand;
 1511
 1512 exec->globalData().interpreter->debug(exec, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
 1513
 1514 LLINT_END();
 1515}
 1516
 1517LLINT_HELPER_DECL(helper_profile_will_call)
 1518{
 1519 LLINT_BEGIN();
 1520 (*Profiler::enabledProfilerReference())->willExecute(exec, LLINT_OP(1).jsValue());
 1521 LLINT_END();
 1522}
 1523
 1524LLINT_HELPER_DECL(helper_profile_did_call)
 1525{
 1526 LLINT_BEGIN();
 1527 (*Profiler::enabledProfilerReference())->didExecute(exec, LLINT_OP(1).jsValue());
 1528 LLINT_END();
 1529}
 1530
 1531} } // namespace JSC::LLInt
 1532
 1533#endif // ENABLE(LLINT)
0

Source/JavaScriptCore/llint/LLIntHelpers.h

 1/*
 2 * Copyright (C) 2011 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef LLIntHelpers_h
 27#define LLIntHelpers_h
 28
 29#include <wtf/Platform.h>
 30#include <wtf/StdLibExtras.h>
 31
 32#if ENABLE(LLINT)
 33
 34namespace JSC {
 35
 36class ExecState;
 37struct Instruction;
 38
 39namespace LLInt {
 40
 41typedef int64_t HelperReturnType;
 42
 43extern "C" HelperReturnType llint_trace_operand(ExecState*, Instruction*, int fromWhere, int operand);
 44extern "C" HelperReturnType llint_trace_value(ExecState*, Instruction*, int fromWhere, int operand);
 45
 46#define LLINT_HELPER_DECL(name) \
 47 extern "C" HelperReturnType llint_##name(ExecState* exec, Instruction* pc)
 48
 49LLINT_HELPER_DECL(trace_prologue);
 50LLINT_HELPER_DECL(trace_prologue_function_for_call);
 51LLINT_HELPER_DECL(trace_prologue_function_for_construct);
 52LLINT_HELPER_DECL(trace_arityCheck_for_call);
 53LLINT_HELPER_DECL(trace_arityCheck_for_construct);
 54LLINT_HELPER_DECL(trace);
 55LLINT_HELPER_DECL(special_trace);
 56LLINT_HELPER_DECL(entry_osr);
 57LLINT_HELPER_DECL(entry_osr_function_for_call);
 58LLINT_HELPER_DECL(entry_osr_function_for_construct);
 59LLINT_HELPER_DECL(entry_osr_function_for_call_arityCheck);
 60LLINT_HELPER_DECL(entry_osr_function_for_construct_arityCheck);
 61LLINT_HELPER_DECL(loop_osr);
 62LLINT_HELPER_DECL(replace);
 63LLINT_HELPER_DECL(register_file_check);
 64LLINT_HELPER_DECL(helper_call_arityCheck);
 65LLINT_HELPER_DECL(helper_construct_arityCheck);
 66LLINT_HELPER_DECL(helper_create_activation);
 67LLINT_HELPER_DECL(helper_create_arguments);
 68LLINT_HELPER_DECL(helper_create_this);
 69LLINT_HELPER_DECL(helper_convert_this);
 70LLINT_HELPER_DECL(helper_new_object);
 71LLINT_HELPER_DECL(helper_new_array);
 72LLINT_HELPER_DECL(helper_new_array_buffer);
 73LLINT_HELPER_DECL(helper_new_regexp);
 74LLINT_HELPER_DECL(helper_not);
 75LLINT_HELPER_DECL(helper_eq);
 76LLINT_HELPER_DECL(helper_neq);
 77LLINT_HELPER_DECL(helper_stricteq);
 78LLINT_HELPER_DECL(helper_nstricteq);
 79LLINT_HELPER_DECL(helper_less);
 80LLINT_HELPER_DECL(helper_lesseq);
 81LLINT_HELPER_DECL(helper_greater);
 82LLINT_HELPER_DECL(helper_greatereq);
 83LLINT_HELPER_DECL(helper_pre_inc);
 84LLINT_HELPER_DECL(helper_pre_dec);
 85LLINT_HELPER_DECL(helper_post_inc);
 86LLINT_HELPER_DECL(helper_post_dec);
 87LLINT_HELPER_DECL(helper_to_jsnumber);
 88LLINT_HELPER_DECL(helper_negate);
 89LLINT_HELPER_DECL(helper_add);
 90LLINT_HELPER_DECL(helper_mul);
 91LLINT_HELPER_DECL(helper_sub);
 92LLINT_HELPER_DECL(helper_div);
 93LLINT_HELPER_DECL(helper_mod);
 94LLINT_HELPER_DECL(helper_lshift);
 95LLINT_HELPER_DECL(helper_rshift);
 96LLINT_HELPER_DECL(helper_urshift);
 97LLINT_HELPER_DECL(helper_bitand);
 98LLINT_HELPER_DECL(helper_bitor);
 99LLINT_HELPER_DECL(helper_bitxor);
 100LLINT_HELPER_DECL(helper_bitnot);
 101LLINT_HELPER_DECL(helper_check_has_instance);
 102LLINT_HELPER_DECL(helper_instanceof);
 103LLINT_HELPER_DECL(helper_typeof);
 104LLINT_HELPER_DECL(helper_is_undefined);
 105LLINT_HELPER_DECL(helper_is_boolean);
 106LLINT_HELPER_DECL(helper_is_number);
 107LLINT_HELPER_DECL(helper_is_string);
 108LLINT_HELPER_DECL(helper_is_object);
 109LLINT_HELPER_DECL(helper_is_function);
 110LLINT_HELPER_DECL(helper_in);
 111LLINT_HELPER_DECL(helper_resolve);
 112LLINT_HELPER_DECL(helper_resolve_skip);
 113LLINT_HELPER_DECL(helper_resolve_global);
 114LLINT_HELPER_DECL(helper_resolve_global_dynamic);
 115LLINT_HELPER_DECL(helper_resolve_for_resolve_global_dynamic);
 116LLINT_HELPER_DECL(helper_resolve_base);
 117LLINT_HELPER_DECL(helper_ensure_property_exists);
 118LLINT_HELPER_DECL(helper_resolve_with_base);
 119LLINT_HELPER_DECL(helper_resolve_with_this);
 120LLINT_HELPER_DECL(helper_get_by_id);
 121LLINT_HELPER_DECL(helper_get_arguments_length);
 122LLINT_HELPER_DECL(helper_put_by_id);
 123LLINT_HELPER_DECL(helper_del_by_id);
 124LLINT_HELPER_DECL(helper_get_by_val);
 125LLINT_HELPER_DECL(helper_get_argument_by_val);
 126LLINT_HELPER_DECL(helper_get_by_pname);
 127LLINT_HELPER_DECL(helper_put_by_val);
 128LLINT_HELPER_DECL(helper_del_by_val);
 129LLINT_HELPER_DECL(helper_put_by_index);
 130LLINT_HELPER_DECL(helper_put_getter_setter);
 131LLINT_HELPER_DECL(helper_jmp_scopes);
 132LLINT_HELPER_DECL(helper_jtrue);
 133LLINT_HELPER_DECL(helper_jfalse);
 134LLINT_HELPER_DECL(helper_jless);
 135LLINT_HELPER_DECL(helper_jnless);
 136LLINT_HELPER_DECL(helper_jgreater);
 137LLINT_HELPER_DECL(helper_jngreater);
 138LLINT_HELPER_DECL(helper_jlesseq);
 139LLINT_HELPER_DECL(helper_jnlesseq);
 140LLINT_HELPER_DECL(helper_jgreatereq);
 141LLINT_HELPER_DECL(helper_jngreatereq);
 142LLINT_HELPER_DECL(helper_switch_imm);
 143LLINT_HELPER_DECL(helper_switch_char);
 144LLINT_HELPER_DECL(helper_switch_string);
 145LLINT_HELPER_DECL(helper_new_func);
 146LLINT_HELPER_DECL(helper_new_func_exp);
 147LLINT_HELPER_DECL(helper_call);
 148LLINT_HELPER_DECL(helper_construct);
 149LLINT_HELPER_DECL(helper_call_varargs);
 150LLINT_HELPER_DECL(helper_call_eval);
 151LLINT_HELPER_DECL(helper_tear_off_activation);
 152LLINT_HELPER_DECL(helper_tear_off_arguments);
 153LLINT_HELPER_DECL(helper_strcat);
 154LLINT_HELPER_DECL(helper_to_primitive);
 155LLINT_HELPER_DECL(helper_get_pnames);
 156LLINT_HELPER_DECL(helper_next_pname);
 157LLINT_HELPER_DECL(helper_push_scope);
 158LLINT_HELPER_DECL(helper_pop_scope);
 159LLINT_HELPER_DECL(helper_push_new_scope);
 160LLINT_HELPER_DECL(helper_throw);
 161LLINT_HELPER_DECL(helper_throw_reference_error);
 162LLINT_HELPER_DECL(helper_debug);
 163LLINT_HELPER_DECL(helper_profile_will_call);
 164LLINT_HELPER_DECL(helper_profile_did_call);
 165
 166} } // namespace JSC::LLInt
 167
 168#endif // ENABLE(LLINT)
 169
 170#endif // LLIntHelpers_h
 171
0

Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h

 1/*
 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef LLIntOfflineAsmConfig_h
 27#define LLIntOfflineAsmConfig_h
 28
 29#include "LLIntCommon.h"
 30#include <wtf/Assertions.h>
 31#include <wtf/InlineAsm.h>
 32#include <wtf/Platform.h>
 33
 34#if CPU(X86)
 35#define OFFLINE_ASM_X86 1
 36#else
 37#define OFFLINE_ASM_X86 0
 38#endif
 39
 40#if CPU(ARM_THUMB2)
 41#define OFFLINE_ASM_ARMv7 1
 42#else
 43#define OFFLINE_ASM_ARMv7 0
 44#endif
 45
 46#if !ASSERT_DISABLED
 47#define OFFLINE_ASM_ASSERT_ENABLED 1
 48#else
 49#define OFFLINE_ASM_ASSERT_ENABLED 0
 50#endif
 51
 52#if CPU(BIG_ENDIAN)
 53#define OFFLINE_ASM_BIG_ENDIAN 1
 54#else
 55#define OFFLINE_ASM_BIG_ENDIAN 0
 56#endif
 57
 58#if ENABLE(LLINT_OSR_TO_JIT)
 59#define OFFLINE_ASM_JIT_ENABLED 1
 60#else
 61#define OFFLINE_ASM_JIT_ENABLED 0
 62#endif
 63
 64#if LLINT_EXECUTION_TRACING
 65#define OFFLINE_ASM_EXECUTION_TRACING 1
 66#else
 67#define OFFLINE_ASM_EXECUTION_TRACING 0
 68#endif
 69
 70#if LLINT_ALWAYS_ALLOCATE_SLOW
 71#define OFFLINE_ASM_ALWAYS_ALLOCATE_SLOW 1
 72#else
 73#define OFFLINE_ASM_ALWAYS_ALLOCATE_SLOW 0
 74#endif
 75
 76#if CPU(ARM_THUMB2)
 77#define OFFLINE_ASM_GLOBAL_LABEL(label) \
 78 ".globl " SYMBOL_STRING(label) "\n" \
 79 HIDE_SYMBOL(name) "\n" \
 80 ".thumb\n" \
 81 ".thumb_func " THUMB_FUNC_PARAM(label) "\n" \
 82 SYMBOL_STRING(label) ":\n"
 83#else
 84#define OFFLINE_ASM_GLOBAL_LABEL(label) \
 85 ".globl " SYMBOL_STRING(label) "\n" \
 86 HIDE_SYMBOL(name) "\n" \
 87 SYMBOL_STRING(label) ":\n"
 88#endif
 89
 90#endif // LLIntOfflineAsmConfig_h
0

Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp

 1/*
 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27
 28#include "CodeBlock.h"
 29#include "Executable.h"
 30#include "Heap.h"
 31#include "Interpreter.h"
 32#include "JITStubs.h"
 33#include "JSArray.h"
 34#include "JSCell.h"
 35#include "JSFunction.h"
 36#include "JSGlobalData.h"
 37#include "JSGlobalObject.h"
 38#include "JSObject.h"
 39#include "JSPropertyNameIterator.h"
 40#include "JSString.h"
 41#include "JSTypeInfo.h"
 42#include "JSVariableObject.h"
 43#include "JumpTable.h"
 44#include "LLIntOfflineAsmConfig.h"
 45#include "MarkedSpace.h"
 46#include "RegisterFile.h"
 47#include "ScopeChain.h"
 48#include "Structure.h"
 49#include "StructureChain.h"
 50#include "ValueProfile.h"
 51#include <wtf/text/StringImpl.h>
 52
 53namespace JSC {
 54
 55#define OFFLINE_ASM_OFFSETOF(clazz, field) OBJECT_OFFSETOF(clazz, field)
 56
 57class LLIntOffsetsExtractor {
 58public:
 59 static const unsigned* dummy();
 60};
 61
 62const unsigned* LLIntOffsetsExtractor::dummy()
 63{
 64// This is a file generated by offlineasm/generate_offsets_extractor.rb, and contains code
 65// to create a table of offsets, sizes, and a header identifying what combination of
 66// Platform.h macros we have set. We include it inside of a method on LLIntOffsetsExtractor
 67// because the fields whose offsets we're extracting are mostly private. So we make their
 68// classes friends with LLIntOffsetsExtractor, and include the header here, to get the C++
 69// compiler to kindly step aside and yield to our best intentions.
 70#include "LLIntDesiredOffsets.h"
 71 return extractorTable;
 72}
 73
 74} // namespace JSC
 75
 76int main(int, char**)
 77{
 78 // Out of an abundance of caution, make sure that LLIntOffsetsExtractor::dummy() is live,
 79 // and the extractorTable is live, too.
 80 printf("%p\n", JSC::LLIntOffsetsExtractor::dummy());
 81 return 0;
 82}
0

Source/JavaScriptCore/llint/LLIntThunks.cpp

 1/*
 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27#include "LLIntThunks.h"
 28
 29#if ENABLE(LLINT)
 30
 31#include "JSInterfaceJIT.h"
 32#include "LinkBuffer.h"
 33#include "LowLevelInterpreter.h"
 34
 35namespace JSC { namespace LLInt {
 36
 37static MacroAssemblerCodeRef generateThunkWithJumpTo(JSGlobalData* globalData, void (*target)())
 38{
 39 JSInterfaceJIT jit;
 40
 41 // FIXME: there's probably a better way to do it on X86, but I'm not sure I care.
 42 jit.move(JSInterfaceJIT::TrustedImmPtr(bitwise_cast<void*>(target)), JSInterfaceJIT::regT0);
 43 jit.jump(JSInterfaceJIT::regT0);
 44
 45 LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
 46 return patchBuffer.finalizeCode();
 47}
 48
 49MacroAssemblerCodeRef functionForCallEntryThunkGenerator(JSGlobalData* globalData)
 50{
 51 return generateThunkWithJumpTo(globalData, llint_function_for_call_prologue);
 52}
 53
 54MacroAssemblerCodeRef functionForConstructEntryThunkGenerator(JSGlobalData* globalData)
 55{
 56 return generateThunkWithJumpTo(globalData, llint_function_for_construct_prologue);
 57}
 58
 59MacroAssemblerCodeRef functionForCallArityCheckThunkGenerator(JSGlobalData* globalData)
 60{
 61 return generateThunkWithJumpTo(globalData, llint_function_for_call_arity_check);
 62}
 63
 64MacroAssemblerCodeRef functionForConstructArityCheckThunkGenerator(JSGlobalData* globalData)
 65{
 66 return generateThunkWithJumpTo(globalData, llint_function_for_construct_arity_check);
 67}
 68
 69MacroAssemblerCodeRef evalEntryThunkGenerator(JSGlobalData* globalData)
 70{
 71 return generateThunkWithJumpTo(globalData, llint_eval_prologue);
 72}
 73
 74MacroAssemblerCodeRef programEntryThunkGenerator(JSGlobalData* globalData)
 75{
 76 return generateThunkWithJumpTo(globalData, llint_program_prologue);
 77}
 78
 79} } // namespace JSC::LLInt
 80
 81#endif // ENABLE(LLINT)
0

Source/JavaScriptCore/llint/LLIntThunks.h

 1/*
 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef LLIntThunks_h
 27#define LLIntThunks_h
 28
 29#include <wtf/Platform.h>
 30
 31#if ENABLE(LLINT)
 32
 33#include "MacroAssemblerCodeRef.h"
 34
 35namespace JSC {
 36
 37class JSGlobalData;
 38
 39namespace LLInt {
 40
 41MacroAssemblerCodeRef functionForCallEntryThunkGenerator(JSGlobalData*);
 42MacroAssemblerCodeRef functionForConstructEntryThunkGenerator(JSGlobalData*);
 43MacroAssemblerCodeRef functionForCallArityCheckThunkGenerator(JSGlobalData*);
 44MacroAssemblerCodeRef functionForConstructArityCheckThunkGenerator(JSGlobalData*);
 45MacroAssemblerCodeRef evalEntryThunkGenerator(JSGlobalData*);
 46MacroAssemblerCodeRef programEntryThunkGenerator(JSGlobalData*);
 47
 48} } // namespace JSC::LLInt
 49
 50#endif // ENABLE(LLINT)
 51
 52#endif // LLIntThunks_h
0

Source/JavaScriptCore/llint/LowLevelInterpreter.asm

 1# Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
 2#
 3# Redistribution and use in source and binary forms, with or without
 4# modification, are permitted provided that the following conditions
 5# are met:
 6# 1. Redistributions of source code must retain the above copyright
 7# notice, this list of conditions and the following disclaimer.
 8# 2. Redistributions in binary form must reproduce the above copyright
 9# notice, this list of conditions and the following disclaimer in the
 10# documentation and/or other materials provided with the distribution.
 11#
 12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 22# THE POSSIBILITY OF SUCH DAMAGE.
 23
 24
 25# Crash course on the language that this is written in (which I just call
 26# "assembly" even though it's more than that):
 27#
 28# - Mostly gas-style operand ordering. The last operand tends to be the
 29# destination. So "a := b" is written as "mov b, a". But unlike gas,
 30# comparisons are in-order, so "if (a < b)" is written as
 31# "bilt a, b, ...".
 32#
 33# - "b" = byte, "h" = 16-bit word, "i" = 32-bit word, "p" = pointer.
 34# Currently this is just 32-bit so "i" and "p" are interchangeable
 35# except when an op supports one but not the other.
 36#
 37# - In general, valid operands for macro invocations and instructions are
 38# registers (eg "t0"), addresses (eg "4[t0]"), base-index addresses
 39# (eg "7[t0, t1, 2]"), absolute addresses (eg "0xa0000000[]"), or labels
 40# (eg "_foo" or ".foo"). Macro invocations can also take anonymous
 41# macros as operands. Instructions cannot take anonymous macros.
 42#
 43# - Labels must have names that begin with either "_" or ".". A "." label
 44# is local and gets renamed before code gen to minimize namespace
 45# pollution. A "_" label is an extern symbol (i.e. ".globl"). The "_"
 46# may or may not be removed during code gen depending on whether the asm
 47# conventions for C name mangling on the target platform mandate a "_"
 48# prefix.
 49#
 50# - A "macro" is a lambda expression, which may be either anonymous or
 51# named. But this has caveats. "macro" can take zero or more arguments,
 52# which may be macros or any valid operands, but it can only return
 53# code. But you can do Turing-complete things via continuation passing
 54# style: "macro foo (a, b) b(a) end foo(foo, foo)". Actually, don't do
 55# that, since you'll just crash the assembler.
 56#
 57# - An "if" is a conditional on settings. Any identifier supplied in the
 58# predicate of an "if" is assumed to be a #define that is available
 59# during code gen. So you can't use "if" for computation in a macro, but
 60# you can use it to select different pieces of code for different
 61# platforms.
 62#
 63# - Arguments to macros follow lexical scoping rather than dynamic scoping.
 64# Const's also follow lexical scoping and may override (hide) arguments
 65# or other consts. All variables (arguments and constants) can be bound
 66# to operands. Additionally, arguments (but not constants) can be bound
 67# to macros.
 68
 69
 70# These declarations must match interpreter/RegisterFile.h.
 71const CallFrameHeaderSize = 48
 72const ArgumentCount = -48
 73const CallerFrame = -40
 74const Callee = -32
 75const ScopeChain = -24
 76const ReturnPC = -16
 77const CodeBlock = -8
 78
 79const ThisArgumentOffset = -CallFrameHeaderSize - 8
 80
 81# Declare some aliases for the registers we will use.
 82const PC = t4
 83
 84# Offsets needed for reasoning about value representation.
 85if BIG_ENDIAN
 86 const TagOffset = 0
 87 const PayloadOffset = 4
 88else
 89 const TagOffset = 4
 90 const PayloadOffset = 0
 91end
 92
 93# Value representation constants.
 94const Int32Tag = -1
 95const BooleanTag = -2
 96const NullTag = -3
 97const UndefinedTag = -4
 98const CellTag = -5
 99const EmptyValueTag = -6
 100const DeletedValueTag = -7
 101const LowestTag = DeletedValueTag
 102
 103# Type constants.
 104const StringType = 5
 105const ObjectType = 10
 106
 107# Type flags constants.
 108const MasqueradesAsUndefined = 1
 109const ImplementsHasInstance = 2
 110const ImplementsDefaultHasInstance = 8
 111
 112# Heap allocation constants.
 113const JSFinalObjectSizeClassIndex = 3
 114
 115# Bytecode operand constants.
 116const FirstConstantRegisterIndex = 0x40000000
 117
 118# Code type constants.
 119const GlobalCode = 0
 120const EvalCode = 1
 121const FunctionCode = 2
 122
 123# The interpreter steals the tag word of the argument count.
 124const LLIntReturnPC = ArgumentCount + TagOffset
 125
 126# This must match wtf/Vector.h.
 127const VectorSizeOffset = 0
 128const VectorBufferOffset = 4
 129
 130# String flags.
 131const HashFlags8BitBuffer = 64
 132
 133# Utilities
 134macro crash()
 135 storei 0, 0xbbadbeef[]
 136 move 0, t0
 137 call t0
 138end
 139
 140macro assert(assertion)
 141 if ASSERT_ENABLED
 142 assertion(.ok)
 143 crash()
 144 .ok:
 145 end
 146end
 147
 148macro preserveReturnAddressAfterCall(destinationRegister)
 149 if ARMv7
 150 move lr, destinationRegister
 151 elsif X86
 152 pop destinationRegister
 153 else
 154 error
 155 end
 156end
 157
 158macro restoreReturnAddressBeforeReturn(sourceRegister)
 159 if ARMv7
 160 move sourceRegister, lr
 161 elsif X86
 162 push sourceRegister
 163 else
 164 error
 165 end
 166end
 167
 168macro dispatch(advance)
 169 addp advance * 4, PC
 170 jmp [PC]
 171end
 172
 173macro dispatchBranchWithOffset(pcOffset)
 174 lshifti 2, pcOffset
 175 addp pcOffset, PC
 176 jmp [PC]
 177end
 178
 179macro dispatchBranch(pcOffset)
 180 loadi pcOffset, t0
 181 dispatchBranchWithOffset(t0)
 182end
 183
 184macro dispatchAfterCall()
 185 loadi ArgumentCount + TagOffset[cfr], PC
 186 jmp [PC]
 187end
 188
 189macro cCall2(function, arg1, arg2)
 190 if ARMv7
 191 move arg1, t0
 192 move arg2, t1
 193 elsif X86
 194 poke arg1, 0
 195 poke arg2, 1
 196 else
 197 error
 198 end
 199 call function
 200end
 201
 202# This barely works. arg3 and arg4 should probably be immediates.
 203macro cCall4(function, arg1, arg2, arg3, arg4)
 204 if ARMv7
 205 move arg1, t0
 206 move arg2, t1
 207 move arg3, t2
 208 move arg4, t3
 209 elsif X86
 210 poke arg1, 0
 211 poke arg2, 1
 212 poke arg3, 2
 213 poke arg4, 3
 214 else
 215 error
 216 end
 217 call function
 218end
 219
 220macro callHelper(helper)
 221 cCall2(helper, cfr, PC)
 222 move t0, PC
 223 move t1, cfr
 224end
 225
 226# Debugging operation if you'd like to print an operand in the instruction stream. fromWhere
 227# should be an immediate integer - any integer you like; use it to identify the place you're
 228# debugging from. operand should likewise be an immediate, and should identify the operand
 229# in the instruction stream you'd like to print out.
 230macro traceOperand(fromWhere, operand)
 231 cCall4(_llint_trace_operand, cfr, PC, fromWhere, operand)
 232 move t0, PC
 233 move t1, cfr
 234end
 235
 236# Debugging operation if you'd like to print the value of an operand in the instruction
 237# stream. Same as traceOperand(), but assumes that the operand is a register, and prints its
 238# value.
 239macro traceValue(fromWhere, operand)
 240 cCall4(_llint_trace_value, cfr, PC, fromWhere, operand)
 241 move t0, PC
 242 move t1, cfr
 243end
 244
 245macro traceExecution()
 246 if EXECUTION_TRACING
 247 callHelper(_llint_trace)
 248 end
 249end
 250
 251# Call a helper for call opcodes.
 252macro callCallHelper(advance, helper, action)
 253 addp advance * 4, PC, t0
 254 storep t0, ArgumentCount + TagOffset[cfr]
 255 cCall2(helper, cfr, PC)
 256 move t1, cfr
 257 action(t0)
 258end
 259
 260macro slowPathForCall(advance, helper)
 261 callCallHelper(
 262 advance,
 263 helper,
 264 macro (callee)
 265 call callee
 266 dispatchAfterCall()
 267 end)
 268end
 269
 270macro checkSwitchToJIT(increment, action)
 271 if JIT_ENABLED
 272 loadp CodeBlock[cfr], t0
 273 baddis increment, CodeBlock::m_llintExecuteCounter[t0], .continue
 274 action()
 275 .continue:
 276 end
 277end
 278
 279macro checkSwitchToJITForLoop()
 280 checkSwitchToJIT(
 281 1,
 282 macro ()
 283 storei PC, ArgumentCount + TagOffset[cfr]
 284 cCall2(_llint_loop_osr, cfr, PC)
 285 move t1, cfr
 286 btpz t0, .recover
 287 jmp t0
 288 .recover:
 289 loadi ArgumentCount + TagOffset[cfr], PC
 290 end)
 291end
 292
 293macro checkSwitchToJITForEpilogue()
 294 checkSwitchToJIT(
 295 10,
 296 macro ()
 297 callHelper(_llint_replace)
 298 end)
 299end
 300
 301macro assertNotConstant(index)
 302 assert(macro (ok) bilt index, FirstConstantRegisterIndex, ok end)
 303end
 304
 305# Index, tag, and payload must be different registers. Index is not
 306# changed.
 307macro loadConstantOrVariable(index, tag, payload)
 308 bigteq index, FirstConstantRegisterIndex, .constant
 309 loadi TagOffset[cfr, index, 8], tag
 310 loadi PayloadOffset[cfr, index, 8], payload
 311 jmp .done
 312.constant:
 313 loadp CodeBlock[cfr], payload
 314 loadp CodeBlock::m_constantRegisters + VectorBufferOffset[payload], payload
 315 # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex,
 316 # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3.
 317 loadp TagOffset[payload, index, 8], tag
 318 loadp PayloadOffset[payload, index, 8], payload
 319.done:
 320end
 321
 322# Index and payload may be the same register. Index may be clobbered.
 323macro loadConstantOrVariable2Reg(index, tag, payload)
 324 bigteq index, FirstConstantRegisterIndex, .constant
 325 loadi TagOffset[cfr, index, 8], tag
 326 loadi PayloadOffset[cfr, index, 8], payload
 327 jmp .done
 328.constant:
 329 loadp CodeBlock[cfr], tag
 330 loadp CodeBlock::m_constantRegisters + VectorBufferOffset[tag], tag
 331 # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex,
 332 # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3.
 333 lshifti 3, index
 334 addp index, tag
 335 loadp PayloadOffset[tag], payload
 336 loadp TagOffset[tag], tag
 337.done:
 338end
 339
 340macro loadConstantOrVariablePayloadTagCustom(index, tagCheck, payload)
 341 bigteq index, FirstConstantRegisterIndex, .constant
 342 tagCheck(TagOffset[cfr, index, 8])
 343 loadi PayloadOffset[cfr, index, 8], payload
 344 jmp .done
 345.constant:
 346 loadp CodeBlock[cfr], payload
 347 loadp CodeBlock::m_constantRegisters + VectorBufferOffset[payload], payload
 348 # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex,
 349 # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3.
 350 tagCheck(TagOffset[payload, index, 8])
 351 loadp PayloadOffset[payload, index, 8], payload
 352.done:
 353end
 354
 355# Index and payload must be different registers. Index is not mutated. Use
 356# this if you know what the tag of the variable should be. Doing the tag
 357# test as part of loading the variable reduces register use, but may not
 358# be faster than doing loadConstantOrVariable followed by a branch on the
 359# tag.
 360macro loadConstantOrVariablePayload(index, expectedTag, payload, slow)
 361 loadConstantOrVariablePayloadTagCustom(
 362 index,
 363 macro (actualTag) bineq actualTag, expectedTag, slow end,
 364 payload)
 365end
 366
 367macro loadConstantOrVariablePayloadUnchecked(index, payload)
 368 loadConstantOrVariablePayloadTagCustom(
 369 index,
 370 macro (actualTag) end,
 371 payload)
 372end
 373
 374macro writeBarrier(tag, payload)
 375 # Nothing to do, since we don't have a generational or incremental collector.
 376end
 377
 378macro valueProfile(tag, payload, profile)
 379 storei tag, ValueProfile::m_buckets + TagOffset[profile]
 380 storei payload, ValueProfile::m_buckets + PayloadOffset[profile]
 381end
 382
 383
 384# Indicate the beginning of LLInt.
 385_llint_begin:
 386 crash()
 387
 388
 389# Entrypoints into the interpreter
 390
 391macro functionForCallCodeBlockGetter(targetRegister)
 392 loadp Callee[cfr], targetRegister
 393 loadp JSFunction::m_executable[targetRegister], targetRegister
 394 loadp FunctionExecutable::m_codeBlockForCall[targetRegister], targetRegister
 395end
 396
 397macro functionForConstructCodeBlockGetter(targetRegister)
 398 loadp Callee[cfr], targetRegister
 399 loadp JSFunction::m_executable[targetRegister], targetRegister
 400 loadp FunctionExecutable::m_codeBlockForConstruct[targetRegister], targetRegister
 401end
 402
 403macro notFunctionCodeBlockGetter(targetRegister)
 404 loadp CodeBlock[cfr], targetRegister
 405end
 406
 407macro functionCodeBlockSetter(sourceRegister)
 408 storep sourceRegister, CodeBlock[cfr]
 409end
 410
 411macro notFunctionCodeBlockSetter(sourceRegister)
 412 # Nothing to do!
 413end
 414
 415# Do the bare minimum required to execute code. Sets up the PC, leave the CodeBlock*
 416# in t1. May also trigger prologue entry OSR.
 417macro prologue(codeBlockGetter, codeBlockSetter, osrHelper, traceHelper)
 418 preserveReturnAddressAfterCall(t2)
 419
 420 # Set up the call frame and check if we should OSR.
 421 storep t2, ReturnPC[cfr]
 422 if EXECUTION_TRACING
 423 callHelper(traceHelper)
 424 end
 425 codeBlockGetter(t1)
 426 if JIT_ENABLED
 427 baddis 5, CodeBlock::m_llintExecuteCounter[t1], .continue
 428 cCall2(osrHelper, cfr, PC)
 429 move t1, cfr
 430 btpz t0, .recover
 431 loadp ReturnPC[cfr], t2
 432 restoreReturnAddressBeforeReturn(t2)
 433 jmp t0
 434 .recover:
 435 codeBlockGetter(t1)
 436 .continue:
 437 end
 438 codeBlockSetter(t1)
 439
 440 # Set up the PC.
 441 loadp CodeBlock::m_instructions[t1], t0
 442 loadp CodeBlock::Instructions::m_instructions + VectorBufferOffset[t0], PC
 443end
 444
 445# Expects that CodeBlock is in t1, which is what prologue() leaves behind.
 446# Must call dispatch(0) after calling this.
 447macro functionInitialization(profileArgSkip)
 448 # Profile the arguments. Unfortunately, we have no choice but to do this. This
 449 # code is pretty horrendous because of the difference in ordering between
 450 # arguments and value profiles, the desire to have a simple loop-down-to-zero
 451 # loop, and the desire to use only three registers so as to preserve the PC and
 452 # the code block. It is likely that this code should be rewritten in a more
 453 # optimal way for architectures that have more than five registers available
 454 # for arbitrary use in the interpreter.
 455 loadi CodeBlock::m_numParameters[t1], t0
 456 addi -profileArgSkip, t0 # Use addi because that's what has the peephole
 457 assert(macro (ok) bigteq t0, 0, ok end)
 458 btiz t0, .argumentProfileDone
 459 loadp CodeBlock::m_argumentValueProfiles + VectorBufferOffset[t1], t3
 460 muli sizeof ValueProfile, t0, t2 # Aaaaahhhh! Need strength reduction!
 461 negi t0
 462 lshifti 3, t0
 463 addp t2, t3
 464.argumentProfileLoop:
 465 loadi ThisArgumentOffset + TagOffset + 8 - profileArgSkip * 8[cfr, t0], t2
 466 subp sizeof ValueProfile, t3
 467 storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + TagOffset[t3]
 468 loadi ThisArgumentOffset + PayloadOffset + 8 - profileArgSkip * 8[cfr, t0], t2
 469 storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + PayloadOffset[t3]
 470 baddinz 8, t0, .argumentProfileLoop
 471.argumentProfileDone:
 472
 473 # Check stack height.
 474 loadi CodeBlock::m_numCalleeRegisters[t1], t0
 475 loadp CodeBlock::m_globalData[t1], t2
 476 loadp JSGlobalData::interpreter[t2], t2 # FIXME: Can get to the RegisterFile from the JITStackFrame
 477 lshifti 3, t0
 478 addp t0, cfr, t0
 479 bpaeq Interpreter::m_registerFile + RegisterFile::m_end[t2], t0, .stackHeightOK
 480
 481 # Stack height check failed - need to call a helper.
 482 callHelper(_llint_register_file_check)
 483.stackHeightOK:
 484end
 485
 486# Expects that CodeBlock is in t1, which is what prologue() leaves behind.
 487macro functionArityCheck(doneLabel, helper)
 488 loadi PayloadOffset + ArgumentCount[cfr], t0
 489 biaeq t0, CodeBlock::m_numParameters[t1], doneLabel
 490 cCall2(helper, cfr, PC) # This helper has a simple protocol: t0 = 0 => no error, t0 != 0 => error
 491 move t1, cfr
 492 btiz t0, .continue
 493 loadp JITStackFrame::globalData[sp], t1
 494 loadp JSGlobalData::callFrameForThrow[t1], t0
 495 jmp JSGlobalData::targetMachinePCForThrow[t1]
 496.continue:
 497 # Reload CodeBlock and PC, since the helper clobbered it.
 498 loadp CodeBlock[cfr], t1
 499 loadp CodeBlock::m_instructions[t1], t0
 500 loadp CodeBlock::Instructions::m_instructions + VectorBufferOffset[t0], PC
 501 jmp doneLabel
 502end
 503
 504_llint_program_prologue:
 505 prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
 506 dispatch(0)
 507
 508
 509_llint_eval_prologue:
 510 prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
 511 dispatch(0)
 512
 513
 514_llint_function_for_call_prologue:
 515 prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call, _llint_trace_prologue_function_for_call)
 516.functionForCallBegin:
 517 functionInitialization(0)
 518 dispatch(0)
 519
 520
 521_llint_function_for_construct_prologue:
 522 prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct, _llint_trace_prologue_function_for_construct)
 523.functionForConstructBegin:
 524 functionInitialization(1)
 525 dispatch(0)
 526
 527
 528_llint_function_for_call_arity_check:
 529 prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call_arityCheck, _llint_trace_arityCheck_for_call)
 530 functionArityCheck(.functionForCallBegin, _llint_helper_call_arityCheck)
 531
 532
 533_llint_function_for_construct_arity_check:
 534 prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct_arityCheck, _llint_trace_arityCheck_for_construct)
 535 functionArityCheck(.functionForConstructBegin, _llint_helper_construct_arityCheck)
 536
 537# Instruction implementations
 538
 539_llint_op_enter:
 540 traceExecution()
 541 loadp CodeBlock[cfr], t2
 542 loadi CodeBlock::m_numVars[t2], t2
 543 btiz t2, .opEnterDone
 544 move UndefinedTag, t0
 545 move 0, t1
 546.opEnterLoop:
 547 subi 1, t2
 548 storei t0, TagOffset[cfr, t2, 8]
 549 storei t1, PayloadOffset[cfr, t2, 8]
 550 btinz t2, .opEnterLoop
 551.opEnterDone:
 552 dispatch(1)
 553
 554
 555_llint_op_create_activation:
 556 traceExecution()
 557 loadi 4[PC], t0
 558 bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opCreateActivationDone
 559 callHelper(_llint_helper_create_activation)
 560.opCreateActivationDone:
 561 dispatch(2)
 562
 563
 564_llint_op_init_lazy_reg:
 565 traceExecution()
 566 loadi 4[PC], t0
 567 storei EmptyValueTag, TagOffset[cfr, t0, 8]
 568 storei 0, PayloadOffset[cfr, t0, 8]
 569 dispatch(2)
 570
 571
 572_llint_op_create_arguments:
 573 traceExecution()
 574 loadi 4[PC], t0
 575 bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opCreateArgumentsDone
 576 callHelper(_llint_helper_create_arguments)
 577.opCreateArgumentsDone:
 578 dispatch(2)
 579
 580
 581macro allocateBasicJSObject(sizeClassIndex, classInfoOffset, structure, result, scratch1, scratch2, slowCase)
 582 if ALWAYS_ALLOCATE_SLOW
 583 jmp slowCase
 584 else
 585 const offsetOfMySizeClass =
 586 JSGlobalData::heap +
 587 Heap::m_objectSpace +
 588 MarkedSpace::m_normalSpace +
 589 MarkedSpace::Subspace::preciseAllocators +
 590 sizeClassIndex * sizeof MarkedAllocator
 591
 592 # FIXME: we can get the global data in one load from the stack.
 593 loadp CodeBlock[cfr], scratch1
 594 loadp CodeBlock::m_globalData[scratch1], scratch1
 595
 596 # Get the object from the free list.
 597 loadp offsetOfMySizeClass + MarkedAllocator::m_firstFreeCell[scratch1], result
 598 btpz result, slowCase
 599
 600 # Remove the object from the free list.
 601 loadp [result], scratch2
 602 storep scratch2, offsetOfMySizeClass + MarkedAllocator::m_firstFreeCell[scratch1]
 603
 604 # Initialize the object.
 605 loadp classInfoOffset[scratch1], scratch2
 606 storep scratch2, [result]
 607 storep structure, JSCell::m_structure[result]
 608 storep 0, JSObject::m_inheritorID[result]
 609 addp sizeof JSObject, result, scratch1
 610 storep scratch1, JSObject::m_propertyStorage[result]
 611 end
 612end
 613
 614_llint_op_create_this:
 615 traceExecution()
 616 loadi 8[PC], t0
 617 assertNotConstant(t0)
 618 bineq TagOffset[cfr, t0, 8], CellTag, .opCreateThisSlow
 619 loadi PayloadOffset[cfr, t0, 8], t0
 620 loadp JSCell::m_structure[t0], t1
 621 bbb Structure::m_typeInfo + TypeInfo::m_type[t1], ObjectType, .opCreateThisSlow
 622 loadp JSObject::m_inheritorID[t0], t2
 623 btpz t2, .opCreateThisSlow
 624 allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t2, t0, t1, t3, .opCreateThisSlow)
 625 loadi 4[PC], t1
 626 storei CellTag, TagOffset[cfr, t1, 8]
 627 storei t0, PayloadOffset[cfr, t1, 8]
 628 dispatch(3)
 629
 630.opCreateThisSlow:
 631 callHelper(_llint_helper_create_this)
 632 dispatch(3)
 633
 634
 635_llint_op_get_callee:
 636 traceExecution()
 637 loadi 4[PC], t0
 638 loadp PayloadOffset + Callee[cfr], t1
 639 storei CellTag, TagOffset[cfr, t0, 8]
 640 storei t1, PayloadOffset[cfr, t0, 8]
 641 dispatch(2)
 642
 643
 644_llint_op_convert_this:
 645 traceExecution()
 646 loadi 4[PC], t0
 647 bineq TagOffset[cfr, t0, 8], CellTag, .opConvertThisSlow
 648 loadi PayloadOffset[cfr, t0, 8], t0
 649 loadp JSCell::m_structure[t0], t0
 650 bbb Structure::m_typeInfo + TypeInfo::m_type[t0], ObjectType, .opConvertThisSlow
 651 dispatch(2)
 652
 653.opConvertThisSlow:
 654 callHelper(_llint_helper_convert_this)
 655 dispatch(2)
 656
 657
 658_llint_op_new_object:
 659 traceExecution()
 660 loadp CodeBlock[cfr], t0
 661 loadp CodeBlock::m_globalObject[t0], t0
 662 loadp JSGlobalObject::m_emptyObjectStructure[t0], t1
 663 allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t1, t0, t2, t3, .opNewObjectSlow)
 664 loadi 4[PC], t1
 665 storei CellTag, TagOffset[cfr, t1, 8]
 666 storei t0, PayloadOffset[cfr, t1, 8]
 667 dispatch(2)
 668
 669.opNewObjectSlow:
 670 callHelper(_llint_helper_new_object)
 671 dispatch(2)
 672
 673
 674_llint_op_new_array:
 675 traceExecution()
 676 callHelper(_llint_helper_new_array)
 677 dispatch(4)
 678
 679
 680_llint_op_new_array_buffer:
 681 traceExecution()
 682 callHelper(_llint_helper_new_array_buffer)
 683 dispatch(4)
 684
 685
 686_llint_op_new_regexp:
 687 traceExecution()
 688 callHelper(_llint_helper_new_regexp)
 689 dispatch(3)
 690
 691
 692_llint_op_mov:
 693 traceExecution()
 694 loadi 8[PC], t1
 695 loadi 4[PC], t0
 696 loadConstantOrVariable(t1, t2, t3)
 697 storei t2, TagOffset[cfr, t0, 8]
 698 storei t3, PayloadOffset[cfr, t0, 8]
 699 dispatch(3)
 700
 701
 702_llint_op_not:
 703 traceExecution()
 704 loadi 8[PC], t0
 705 loadi 4[PC], t1
 706 loadConstantOrVariable(t0, t2, t3)
 707 bineq t2, BooleanTag, .opNotSlow
 708 xori 1, t3
 709 storei t2, TagOffset[cfr, t1, 8]
 710 storei t3, PayloadOffset[cfr, t1, 8]
 711 dispatch(3)
 712
 713.opNotSlow:
 714 callHelper(_llint_helper_not)
 715 dispatch(3)
 716
 717
 718_llint_op_eq:
 719 traceExecution()
 720 loadi 12[PC], t2
 721 loadi 8[PC], t0
 722 loadConstantOrVariable(t2, t3, t1)
 723 loadConstantOrVariable2Reg(t0, t2, t0)
 724 bineq t2, t3, .opEqSlow
 725 bieq t2, CellTag, .opEqSlow
 726 bib t2, LowestTag, .opEqSlow
 727 loadi 4[PC], t2
 728 cieq t0, t1, t0
 729 storei BooleanTag, TagOffset[cfr, t2, 8]
 730 storei t0, PayloadOffset[cfr, t2, 8]
 731 dispatch(4)
 732
 733.opEqSlow:
 734 callHelper(_llint_helper_eq)
 735 dispatch(4)
 736
 737
 738_llint_op_eq_null:
 739 traceExecution()
 740 loadi 8[PC], t0
 741 loadi 4[PC], t3
 742 assertNotConstant(t0)
 743 loadi TagOffset[cfr, t0, 8], t1
 744 loadi PayloadOffset[cfr, t0, 8], t0
 745 bineq t1, CellTag, .opEqNullImmediate
 746 loadp JSCell::m_structure[t0], t1
 747 tbnz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1
 748 jmp .opEqNullNotImmediate
 749.opEqNullImmediate:
 750 cieq t1, NullTag, t2
 751 cieq t1, UndefinedTag, t1
 752 ori t2, t1
 753.opEqNullNotImmediate:
 754 storei BooleanTag, TagOffset[cfr, t3, 8]
 755 storei t1, PayloadOffset[cfr, t3, 8]
 756 dispatch(3)
 757
 758
 759_llint_op_neq:
 760 traceExecution()
 761 loadi 12[PC], t2
 762 loadi 8[PC], t0
 763 loadConstantOrVariable(t2, t3, t1)
 764 loadConstantOrVariable2Reg(t0, t2, t0)
 765 bineq t2, t3, .opNeqSlow
 766 bieq t2, CellTag, .opNeqSlow
 767 bib t2, LowestTag, .opNeqSlow
 768 loadi 4[PC], t2
 769 cineq t0, t1, t0
 770 storei BooleanTag, TagOffset[cfr, t2, 8]
 771 storei t0, PayloadOffset[cfr, t2, 8]
 772 dispatch(4)
 773
 774.opNeqSlow:
 775 callHelper(_llint_helper_neq)
 776 dispatch(4)
 777
 778
 779_llint_op_neq_null:
 780 traceExecution()
 781 loadi 8[PC], t0
 782 loadi 4[PC], t3
 783 assertNotConstant(t0)
 784 loadi TagOffset[cfr, t0, 8], t1
 785 loadi PayloadOffset[cfr, t0, 8], t0
 786 bineq t1, CellTag, .opNeqNullImmediate
 787 loadp JSCell::m_structure[t0], t1
 788 tbz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1
 789 jmp .opNeqNullNotImmediate
 790.opNeqNullImmediate:
 791 cineq t1, NullTag, t2
 792 cineq t1, UndefinedTag, t1
 793 andi t2, t1
 794.opNeqNullNotImmediate:
 795 storei BooleanTag, TagOffset[cfr, t3, 8]
 796 storei t1, PayloadOffset[cfr, t3, 8]
 797 dispatch(3)
 798
 799
 800macro strictEq(equalityOperation, helper)
 801 loadi 12[PC], t2
 802 loadi 8[PC], t0
 803 loadConstantOrVariable(t2, t3, t1)
 804 loadConstantOrVariable2Reg(t0, t2, t0)
 805 bineq t2, t3, .slow
 806 bib t2, LowestTag, .slow
 807 bineq t2, CellTag, .notString
 808 loadp JSCell::m_structure[t0], t2
 809 loadp JSCell::m_structure[t1], t3
 810 bbneq Structure::m_typeInfo + TypeInfo::m_type[t2], StringType, .notString
 811 bbeq Structure::m_typeInfo + TypeInfo::m_type[t3], StringType, .slow
 812.notString:
 813 loadi 4[PC], t2
 814 equalityOperation(t0, t1, t0)
 815 storei BooleanTag, TagOffset[cfr, t2, 8]
 816 storei t0, PayloadOffset[cfr, t2, 8]
 817 dispatch(4)
 818
 819.slow:
 820 callHelper(helper)
 821 dispatch(4)
 822end
 823
 824_llint_op_stricteq:
 825 traceExecution()
 826 strictEq(macro (left, right, result) cieq left, right, result end, _llint_helper_stricteq)
 827
 828
 829_llint_op_nstricteq:
 830 traceExecution()
 831 strictEq(macro (left, right, result) cineq left, right, result end, _llint_helper_nstricteq)
 832
 833
 834_llint_op_less:
 835 traceExecution()
 836 callHelper(_llint_helper_less)
 837 dispatch(4)
 838
 839
 840_llint_op_lesseq:
 841 traceExecution()
 842 callHelper(_llint_helper_lesseq)
 843 dispatch(4)
 844
 845
 846_llint_op_greater:
 847 traceExecution()
 848 callHelper(_llint_helper_greater)
 849 dispatch(4)
 850
 851
 852_llint_op_greatereq:
 853 traceExecution()
 854 callHelper(_llint_helper_greatereq)
 855 dispatch(4)
 856
 857
 858_llint_op_pre_inc:
 859 traceExecution()
 860 loadi 4[PC], t0
 861 bineq TagOffset[cfr, t0, 8], Int32Tag, .opPreIncSlow
 862 loadi PayloadOffset[cfr, t0, 8], t1
 863 baddio 1, t1, .opPreIncSlow
 864 storei t1, PayloadOffset[cfr, t0, 8]
 865 dispatch(2)
 866
 867.opPreIncSlow:
 868 callHelper(_llint_helper_pre_inc)
 869 dispatch(2)
 870
 871
 872_llint_op_pre_dec:
 873 traceExecution()
 874 loadi 4[PC], t0
 875 bineq TagOffset[cfr, t0, 8], Int32Tag, .opPreDecSlow
 876 loadi PayloadOffset[cfr, t0, 8], t1
 877 bsubio 1, t1, .opPreDecSlow
 878 storei t1, PayloadOffset[cfr, t0, 8]
 879 dispatch(2)
 880
 881.opPreDecSlow:
 882 callHelper(_llint_helper_pre_dec)
 883 dispatch(2)
 884
 885
 886_llint_op_post_inc:
 887 traceExecution()
 888 loadi 8[PC], t0
 889 loadi 4[PC], t1
 890 bineq TagOffset[cfr, t0, 8], Int32Tag, .opPostIncSlow
 891 bieq t0, t1, .opPostIncDone
 892 loadi PayloadOffset[cfr, t0, 8], t2
 893 move t2, t3
 894 baddio 1, t3, .opPostIncSlow
 895 storei Int32Tag, TagOffset[cfr, t1, 8]
 896 storei t2, PayloadOffset[cfr, t1, 8]
 897 storei t3, PayloadOffset[cfr, t0, 8]
 898.opPostIncDone:
 899 dispatch(3)
 900
 901.opPostIncSlow:
 902 callHelper(_llint_helper_post_inc)
 903 dispatch(3)
 904
 905
 906_llint_op_post_dec:
 907 traceExecution()
 908 loadi 8[PC], t0
 909 loadi 4[PC], t1
 910 bineq TagOffset[cfr, t0, 8], Int32Tag, .opPostDecSlow
 911 bieq t0, t1, .opPostDecDone
 912 loadi PayloadOffset[cfr, t0, 8], t2
 913 move t2, t3
 914 bsubio 1, t3, .opPostDecSlow
 915 storei Int32Tag, TagOffset[cfr, t1, 8]
 916 storei t2, PayloadOffset[cfr, t1, 8]
 917 storei t3, PayloadOffset[cfr, t0, 8]
 918.opPostDecDone:
 919 dispatch(3)
 920
 921.opPostDecSlow:
 922 callHelper(_llint_helper_post_dec)
 923 dispatch(3)
 924
 925
 926_llint_op_to_jsnumber:
 927 traceExecution()
 928 loadi 8[PC], t0
 929 loadi 4[PC], t1
 930 loadConstantOrVariable(t0, t2, t3)
 931 bieq t2, Int32Tag, .opToJsnumberIsInt
 932 biaeq t2, EmptyValueTag, .opToJsnumberSlow
 933.opToJsnumberIsInt:
 934 storei t2, TagOffset[cfr, t1, 8]
 935 storei t3, PayloadOffset[cfr, t1, 8]
 936 dispatch(3)
 937
 938.opToJsnumberSlow:
 939 callHelper(_llint_helper_to_jsnumber)
 940 dispatch(3)
 941
 942
 943_llint_op_negate:
 944 traceExecution()
 945 loadi 8[PC], t0
 946 loadi 4[PC], t3
 947 loadConstantOrVariable(t0, t1, t2)
 948 bineq t1, Int32Tag, .opNegateSrcNotInt
 949 btiz t2, 0x7fffffff, .opNegateSlow
 950 negi t2
 951 storei Int32Tag, TagOffset[cfr, t3, 8]
 952 storei t2, PayloadOffset[cfr, t3, 8]
 953 dispatch(3)
 954.opNegateSrcNotInt:
 955 bia t1, LowestTag, .opNegateSlow
 956 xori 0x80000000, t1
 957 storei t1, TagOffset[cfr, t3, 8]
 958 storei t2, PayloadOffset[cfr, t3, 8]
 959 dispatch(3)
 960
 961.opNegateSlow:
 962 callHelper(_llint_helper_negate)
 963 dispatch(3)
 964
 965
 966macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, helper)
 967 loadi 12[PC], t2
 968 loadi 8[PC], t0
 969 loadConstantOrVariable(t2, t3, t1)
 970 loadConstantOrVariable2Reg(t0, t2, t0)
 971 bineq t2, Int32Tag, .op1NotInt
 972 bineq t3, Int32Tag, .op2NotInt
 973 loadi 4[PC], t2
 974 integerOperationAndStore(t3, t1, t0, .slow, t2)
 975 dispatch(5)
 976
 977.op1NotInt:
 978 # First operand is definitely not an int, the second operand could be anything.
 979 bia t2, LowestTag, .slow
 980 bib t3, LowestTag, .op1NotIntOp2Double
 981 bineq t3, Int32Tag, .slow
 982 ci2d t1, ft1
 983 jmp .op1NotIntReady
 984.op1NotIntOp2Double:
 985 fii2d t1, t3, ft1
 986.op1NotIntReady:
 987 loadi 4[PC], t1
 988 fii2d t0, t2, ft0
 989 doubleOperation(ft1, ft0)
 990 stored ft0, [cfr, t1, 8]
 991 dispatch(5)
 992
 993.op2NotInt:
 994 # First operand is definitely an int, the second operand is definitely not.
 995 loadi 4[PC], t2
 996 bia t3, LowestTag, .slow
 997 ci2d t0, ft0
 998 fii2d t1, t3, ft1
 999 doubleOperation(ft1, ft0)
 1000 stored ft0, [cfr, t2, 8]
 1001 dispatch(5)
 1002
 1003.slow:
 1004 callHelper(helper)
 1005 dispatch(5)
 1006end
 1007
 1008macro binaryOp(integerOperation, doubleOperation, helper)
 1009 binaryOpCustomStore(
 1010 macro (int32Tag, left, right, slow, index)
 1011 integerOperation(left, right, slow)
 1012 storei int32Tag, TagOffset[cfr, index, 8]
 1013 storei right, PayloadOffset[cfr, index, 8]
 1014 end,
 1015 doubleOperation, helper)
 1016end
 1017
 1018_llint_op_add:
 1019 traceExecution()
 1020 binaryOp(
 1021 macro (left, right, slow) baddio left, right, slow end,
 1022 macro (left, right) addd left, right end,
 1023 _llint_helper_add)
 1024
 1025
 1026_llint_op_mul:
 1027 traceExecution()
 1028 binaryOpCustomStore(
 1029 macro (int32Tag, left, right, slow, index)
 1030 const scratch = int32Tag # We know that we can reuse the int32Tag register since it has a constant.
 1031 move right, scratch
 1032 bmulio left, scratch, slow
 1033 btinz scratch, .done
 1034 bilt left, 0, slow
 1035 bilt right, 0, slow
 1036 .done:
 1037 storei Int32Tag, TagOffset[cfr, index, 8]
 1038 storei scratch, PayloadOffset[cfr, index, 8]
 1039 end,
 1040 macro (left, right) muld left, right end,
 1041 _llint_helper_mul)
 1042
 1043
 1044_llint_op_sub:
 1045 traceExecution()
 1046 binaryOp(
 1047 macro (left, right, slow) bsubio left, right, slow end,
 1048 macro (left, right) subd left, right end,
 1049 _llint_helper_sub)
 1050
 1051
 1052_llint_op_div:
 1053 traceExecution()
 1054 binaryOpCustomStore(
 1055 macro (int32Tag, left, right, slow, index)
 1056 ci2d left, ft0
 1057 ci2d right, ft1
 1058 divd ft0, ft1
 1059 bcd2i ft1, right, .notInt
 1060 storei int32Tag, TagOffset[cfr, index, 8]
 1061 storei right, PayloadOffset[cfr, index, 8]
 1062 jmp .done
 1063 .notInt:
 1064 stored ft1, [cfr, index, 8]
 1065 .done:
 1066 end,
 1067 macro (left, right) divd left, right end,
 1068 _llint_helper_div)
 1069
 1070
 1071_llint_op_mod:
 1072 traceExecution()
 1073 callHelper(_llint_helper_mod)
 1074 dispatch(4)
 1075
 1076
 1077macro bitOp(operation, helper, advance)
 1078 loadi 12[PC], t2
 1079 loadi 8[PC], t0
 1080 loadConstantOrVariable(t2, t3, t1)
 1081 loadConstantOrVariable2Reg(t0, t2, t0)
 1082 bineq t3, Int32Tag, .slow
 1083 bineq t2, Int32Tag, .slow
 1084 loadi 4[PC], t2
 1085 operation(t1, t0, .slow)
 1086 storei t3, TagOffset[cfr, t2, 8]
 1087 storei t0, PayloadOffset[cfr, t2, 8]
 1088 dispatch(advance)
 1089
 1090.slow:
 1091 callHelper(helper)
 1092 dispatch(advance)
 1093end
 1094
 1095_llint_op_lshift:
 1096 traceExecution()
 1097 bitOp(
 1098 macro (left, right, slow) lshifti left, right end,
 1099 _llint_helper_lshift,
 1100 4)
 1101
 1102
 1103_llint_op_rshift:
 1104 traceExecution()
 1105 bitOp(
 1106 macro (left, right, slow) rshifti left, right end,
 1107 _llint_helper_rshift,
 1108 4)
 1109
 1110
 1111_llint_op_urshift:
 1112 traceExecution()
 1113 bitOp(
 1114 macro (left, right, slow)
 1115 urshifti left, right
 1116 bilt right, 0, slow
 1117 end,
 1118 _llint_helper_urshift,
 1119 4)
 1120
 1121
 1122_llint_op_bitand:
 1123 traceExecution()
 1124 bitOp(
 1125 macro (left, right, slow) andi left, right end,
 1126 _llint_helper_bitand,
 1127 5)
 1128
 1129
 1130_llint_op_bitxor:
 1131 traceExecution()
 1132 bitOp(
 1133 macro (left, right, slow) xori left, right end,
 1134 _llint_helper_bitxor,
 1135 5)
 1136
 1137
 1138_llint_op_bitor:
 1139 traceExecution()
 1140 bitOp(
 1141 macro (left, right, slow) ori left, right end,
 1142 _llint_helper_bitor,
 1143 5)
 1144
 1145
 1146_llint_op_bitnot:
 1147 traceExecution()
 1148 loadi 8[PC], t1
 1149 loadi 4[PC], t0
 1150 loadConstantOrVariable(t1, t2, t3)
 1151 bineq t2, Int32Tag, .opBitnotSlow
 1152 noti t3
 1153 storei t2, TagOffset[cfr, t0, 8]
 1154 storei t3, PayloadOffset[cfr, t0, 8]
 1155 dispatch(3)
 1156
 1157.opBitnotSlow:
 1158 callHelper(_llint_helper_bitnot)
 1159 dispatch(3)
 1160
 1161
 1162_llint_op_check_has_instance:
 1163 traceExecution()
 1164 loadi 4[PC], t1
 1165 loadConstantOrVariablePayload(t1, CellTag, t0, .opCheckHasInstanceSlow)
 1166 loadp JSCell::m_structure[t0], t0
 1167 btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsHasInstance, .opCheckHasInstanceSlow
 1168 dispatch(2)
 1169
 1170.opCheckHasInstanceSlow:
 1171 callHelper(_llint_helper_check_has_instance)
 1172 dispatch(2)
 1173
 1174
 1175_llint_op_instanceof:
 1176 traceExecution()
 1177 # Check that baseVal implements the default HasInstance behavior.
 1178 # FIXME: This should be deprecated.
 1179 loadi 12[PC], t1
 1180 loadConstantOrVariablePayloadUnchecked(t1, t0)
 1181 loadp JSCell::m_structure[t0], t0
 1182 btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsDefaultHasInstance, .opInstanceofSlow
 1183
 1184 # Actually do the work.
 1185 loadi 16[PC], t0
 1186 loadi 4[PC], t3
 1187 loadConstantOrVariablePayload(t0, CellTag, t1, .opInstanceofSlow)
 1188 loadp JSCell::m_structure[t1], t2
 1189 bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opInstanceofSlow
 1190 loadi 8[PC], t0
 1191 loadConstantOrVariablePayload(t0, CellTag, t2, .opInstanceofSlow)
 1192
 1193 # Register state: t1 = prototype, t2 = value
 1194 move 1, t0
 1195.opInstanceofLoop:
 1196 loadp JSCell::m_structure[t2], t2
 1197 loadi Structure::m_prototype + PayloadOffset[t2], t2
 1198 bpeq t2, t1, .opInstanceofDone
 1199 btinz t2, .opInstanceofLoop
 1200
 1201 move 0, t0
 1202.opInstanceofDone:
 1203 storei BooleanTag, TagOffset[cfr, t3, 8]
 1204 storei t0, PayloadOffset[cfr, t3, 8]
 1205 dispatch(5)
 1206
 1207.opInstanceofSlow:
 1208 callHelper(_llint_helper_instanceof)
 1209 dispatch(5)
 1210
 1211
 1212_llint_op_typeof:
 1213 traceExecution()
 1214 callHelper(_llint_helper_typeof)
 1215 dispatch(3)
 1216
 1217
 1218_llint_op_is_undefined:
 1219 traceExecution()
 1220 callHelper(_llint_helper_is_undefined)
 1221 dispatch(3)
 1222
 1223
 1224_llint_op_is_boolean:
 1225 traceExecution()
 1226 callHelper(_llint_helper_is_boolean)
 1227 dispatch(3)
 1228
 1229
 1230_llint_op_is_number:
 1231 traceExecution()
 1232 callHelper(_llint_helper_is_number)
 1233 dispatch(3)
 1234
 1235
 1236_llint_op_is_string:
 1237 traceExecution()
 1238 callHelper(_llint_helper_is_string)
 1239 dispatch(3)
 1240
 1241
 1242_llint_op_is_object:
 1243 traceExecution()
 1244 callHelper(_llint_helper_is_object)
 1245 dispatch(3)
 1246
 1247
 1248_llint_op_is_function:
 1249 traceExecution()
 1250 callHelper(_llint_helper_is_function)
 1251 dispatch(3)
 1252
 1253
 1254_llint_op_in:
 1255 traceExecution()
 1256 callHelper(_llint_helper_in)
 1257 dispatch(4)
 1258
 1259
 1260_llint_op_resolve:
 1261 traceExecution()
 1262 callHelper(_llint_helper_resolve)
 1263 dispatch(4)
 1264
 1265
 1266_llint_op_resolve_skip:
 1267 traceExecution()
 1268 callHelper(_llint_helper_resolve_skip)
 1269 dispatch(5)
 1270
 1271
 1272macro resolveGlobal(size, slow)
 1273 # Operands are as follows:
 1274 # 4[PC] Destination for the load.
 1275 # 8[PC] Property identifier index in the code block.
 1276 # 12[PC] Structure pointer, initialized to 0 by bytecode generator.
 1277 # 16[PC] Offset in global object, initialized to 0 by bytecode generator.
 1278 loadp CodeBlock[cfr], t0
 1279 loadp CodeBlock::m_globalObject[t0], t0
 1280 loadp JSCell::m_structure[t0], t1
 1281 bpneq t1, 12[PC], slow
 1282 loadi 16[PC], t1
 1283 loadp JSObject::m_propertyStorage[t0], t0
 1284 loadi TagOffset[t0, t1, 8], t2
 1285 loadi PayloadOffset[t0, t1, 8], t3
 1286 loadi 4[PC], t0
 1287 storei t2, TagOffset[cfr, t0, 8]
 1288 storei t3, PayloadOffset[cfr, t0, 8]
 1289 loadi (size - 1) * 4[PC], t0
 1290 valueProfile(t2, t3, t0)
 1291end
 1292
 1293_llint_op_resolve_global:
 1294 traceExecution()
 1295 resolveGlobal(6, .opResolveGlobalSlow)
 1296 dispatch(6)
 1297
 1298.opResolveGlobalSlow:
 1299 callHelper(_llint_helper_resolve_global)
 1300 dispatch(6)
 1301
 1302
 1303# Gives you the scope in t0, while allowing you to optionally perform additional checks on the
 1304# scopes as they are traversed. scopeCheck() is called with two arguments: the register
 1305# holding the scope, and a register that can be used for scratch. Note that this does not
 1306# use t3, so you can hold stuff in t3 if need be.
 1307macro getScope(deBruijinIndexOperand, scopeCheck)
 1308 loadp ScopeChain + PayloadOffset[cfr], t0
 1309 loadi deBruijinIndexOperand, t2
 1310
 1311 btiz t2, .done
 1312
 1313 loadp CodeBlock[cfr], t1
 1314 bineq CodeBlock::m_codeType[t1], FunctionCode, .loop
 1315 btbz CodeBlock::m_needsFullScopeChain[t1], .loop
 1316
 1317 loadi CodeBlock::m_activationRegister[t1], t1
 1318
 1319 # Need to conditionally skip over one scope.
 1320 bieq TagOffset[cfr, t1, 8], EmptyValueTag, .noActivation
 1321 scopeCheck(t0, t1)
 1322 loadp ScopeChainNode::next[t0], t0
 1323.noActivation:
 1324 subi 1, t2
 1325
 1326 btiz t2, .done
 1327.loop:
 1328 scopeCheck(t0, t1)
 1329 loadp ScopeChainNode::next[t0], t0
 1330 subi 1, t2
 1331 btinz t2, .loop
 1332
 1333.done:
 1334end
 1335
 1336_llint_op_resolve_global_dynamic:
 1337 traceExecution()
 1338 loadp JITStackFrame::globalData[sp], t3
 1339 loadp JSGlobalData::activationStructure[t3], t3
 1340 getScope(
 1341 20[PC],
 1342 macro (scope, scratch)
 1343 loadp ScopeChainNode::object[scope], scratch
 1344 bpneq JSCell::m_structure[scratch], t3, .opResolveGlobalDynamicSuperSlow
 1345 end)
 1346 resolveGlobal(7, .opResolveGlobalDynamicSlow)
 1347 dispatch(7)
 1348
 1349.opResolveGlobalDynamicSuperSlow:
 1350 callHelper(_llint_helper_resolve_for_resolve_global_dynamic)
 1351 dispatch(7)
 1352
 1353.opResolveGlobalDynamicSlow:
 1354 callHelper(_llint_helper_resolve_global_dynamic)
 1355 dispatch(7)
 1356
 1357
 1358_llint_op_get_scoped_var:
 1359 traceExecution()
 1360 # Operands are as follows:
 1361 # 4[PC] Destination for the load.
 1362 # 8[PC] Index of register in the scope.
 1363 # 12[PC] De Bruijin index.
 1364 getScope(12[PC], macro (scope, scratch) end)
 1365 loadi 4[PC], t1
 1366 loadi 8[PC], t2
 1367 loadp ScopeChainNode::object[t0], t0
 1368 loadp JSVariableObject::m_registers[t0], t0
 1369 loadi TagOffset[t0, t2, 8], t3
 1370 loadi PayloadOffset[t0, t2, 8], t0
 1371 storei t3, TagOffset[cfr, t1, 8]
 1372 storei t0, PayloadOffset[cfr, t1, 8]
 1373 loadi 16[PC], t1
 1374 valueProfile(t3, t0, t1)
 1375 dispatch(5)
 1376
 1377
 1378_llint_op_put_scoped_var:
 1379 traceExecution()
 1380 getScope(8[PC], macro (scope, scratch) end)
 1381 loadi 12[PC], t1
 1382 loadConstantOrVariable(t1, t3, t2)
 1383 loadi 4[PC], t1
 1384 writeBarrier(t3, t2)
 1385 loadp ScopeChainNode::object[t0], t0
 1386 loadp JSVariableObject::m_registers[t0], t0
 1387 storei t3, TagOffset[t0, t1, 8]
 1388 storei t2, PayloadOffset[t0, t1, 8]
 1389 dispatch(4)
 1390
 1391
 1392_llint_op_get_global_var:
 1393 traceExecution()
 1394 loadi 8[PC], t1
 1395 loadi 4[PC], t3
 1396 loadp CodeBlock[cfr], t0
 1397 loadp CodeBlock::m_globalObject[t0], t0
 1398 loadp JSGlobalObject::m_registers[t0], t0
 1399 loadi TagOffset[t0, t1, 8], t2
 1400 loadi PayloadOffset[t0, t1, 8], t1
 1401 storei t2, TagOffset[cfr, t3, 8]
 1402 storei t1, PayloadOffset[cfr, t3, 8]
 1403 loadi 12[PC], t3
 1404 valueProfile(t2, t1, t3)
 1405 dispatch(4)
 1406
 1407
 1408_llint_op_put_global_var:
 1409 traceExecution()
 1410 loadi 8[PC], t1
 1411 loadp CodeBlock[cfr], t0
 1412 loadp CodeBlock::m_globalObject[t0], t0
 1413 loadp JSGlobalObject::m_registers[t0], t0
 1414 loadConstantOrVariable(t1, t2, t3)
 1415 loadi 4[PC], t1
 1416 writeBarrier(t2, t3)
 1417 storei t2, TagOffset[t0, t1, 8]
 1418 storei t3, PayloadOffset[t0, t1, 8]
 1419 dispatch(3)
 1420
 1421
 1422_llint_op_resolve_base:
 1423 traceExecution()
 1424 callHelper(_llint_helper_resolve_base)
 1425 dispatch(5)
 1426
 1427
 1428_llint_op_ensure_property_exists:
 1429 traceExecution()
 1430 callHelper(_llint_helper_ensure_property_exists)
 1431 dispatch(3)
 1432
 1433
 1434_llint_op_resolve_with_base:
 1435 traceExecution()
 1436 callHelper(_llint_helper_resolve_with_base)
 1437 dispatch(5)
 1438
 1439
 1440_llint_op_resolve_with_this:
 1441 traceExecution()
 1442 callHelper(_llint_helper_resolve_with_this)
 1443 dispatch(5)
 1444
 1445
 1446_llint_op_get_by_id:
 1447 traceExecution()
 1448 # We only do monomorphic get_by_id caching for now, and we do not modify the
 1449 # opcode. We do, however, allow for the cache to change anytime if fails, since
 1450 # ping-ponging is free. At best we get lucky and the get_by_id will continue
 1451 # to take fast path on the new cache. At worst we take slow path, which is what
 1452 # we would have been doing anyway.
 1453 loadi 8[PC], t0
 1454 loadi 16[PC], t1
 1455 loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdSlow)
 1456 loadi 20[PC], t2
 1457 loadp JSObject::m_propertyStorage[t3], t0
 1458 bpneq JSCell::m_structure[t3], t1, .opGetByIdSlow
 1459 loadi 4[PC], t1
 1460 loadi TagOffset[t0, t2], t3
 1461 loadi PayloadOffset[t0, t2], t2
 1462 storei t3, TagOffset[cfr, t1, 8]
 1463 storei t2, PayloadOffset[cfr, t1, 8]
 1464 loadi 32[PC], t1
 1465 valueProfile(t3, t2, t1)
 1466 dispatch(9)
 1467
 1468.opGetByIdSlow:
 1469 callHelper(_llint_helper_get_by_id)
 1470 dispatch(9)
 1471
 1472
 1473_llint_op_get_arguments_length:
 1474 traceExecution()
 1475 loadi 8[PC], t0
 1476 loadi 4[PC], t1
 1477 bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opGetArgumentsLengthSlow
 1478 loadi ArgumentCount + PayloadOffset[cfr], t2
 1479 subi 1, t2
 1480 storei Int32Tag, TagOffset[cfr, t1, 8]
 1481 storei t2, PayloadOffset[cfr, t1, 8]
 1482 dispatch(4)
 1483
 1484.opGetArgumentsLengthSlow:
 1485 callHelper(_llint_helper_get_arguments_length)
 1486 dispatch(4)
 1487
 1488
 1489_llint_op_put_by_id:
 1490 traceExecution()
 1491 loadi 4[PC], t3
 1492 loadi 16[PC], t1
 1493 loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow)
 1494 loadi 12[PC], t2
 1495 loadp JSObject::m_propertyStorage[t0], t3
 1496 bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow
 1497 loadi 20[PC], t1
 1498 loadConstantOrVariable2Reg(t2, t0, t2)
 1499 writeBarrier(t0, t2)
 1500 storei t0, TagOffset[t3, t1]
 1501 storei t2, PayloadOffset[t3, t1]
 1502 dispatch(9)
 1503
 1504.opPutByIdSlow:
 1505 callHelper(_llint_helper_put_by_id)
 1506 dispatch(9)
 1507
 1508
 1509macro putByIdTransition(additionalChecks)
 1510 traceExecution()
 1511 loadi 4[PC], t3
 1512 loadi 16[PC], t1
 1513 loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow)
 1514 loadi 12[PC], t2
 1515 bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow
 1516 additionalChecks(t1, t3, .opPutByIdSlow)
 1517 loadi 20[PC], t1
 1518 loadp JSObject::m_propertyStorage[t0], t3
 1519 addp t1, t3
 1520 loadConstantOrVariable2Reg(t2, t1, t2)
 1521 writeBarrier(t1, t2)
 1522 storei t1, TagOffset[t3]
 1523 loadi 24[PC], t1
 1524 storei t2, PayloadOffset[t3]
 1525 storep t1, JSCell::m_structure[t0]
 1526 dispatch(9)
 1527end
 1528
 1529_llint_op_put_by_id_transition_direct:
 1530 putByIdTransition(macro (oldStructure, scratch, slow) end)
 1531
 1532
 1533_llint_op_put_by_id_transition_normal:
 1534 putByIdTransition(
 1535 macro (oldStructure, scratch, slow)
 1536 const protoCell = oldStructure # Reusing the oldStructure register for the proto
 1537
 1538 loadp 28[PC], scratch
 1539 assert(macro (ok) btpnz scratch, ok end)
 1540 loadp StructureChain::m_vector[scratch], scratch
 1541 assert(macro (ok) btpnz scratch, ok end)
 1542 bieq Structure::m_prototype + TagOffset[oldStructure], NullTag, .done
 1543 .loop:
 1544 loadi Structure::m_prototype + PayloadOffset[oldStructure], protoCell
 1545 loadp JSCell::m_structure[protoCell], oldStructure
 1546 bpneq oldStructure, [scratch], slow
 1547 addp 4, scratch
 1548 bineq Structure::m_prototype + TagOffset[oldStructure], NullTag, .loop
 1549 .done:
 1550 end)
 1551
 1552
 1553_llint_op_del_by_id:
 1554 traceExecution()
 1555 callHelper(_llint_helper_del_by_id)
 1556 dispatch(4)
 1557
 1558
 1559_llint_op_get_by_val:
 1560 traceExecution()
 1561 loadp CodeBlock[cfr], t1
 1562 loadi 8[PC], t2
 1563 loadi 12[PC], t3
 1564 loadp CodeBlock::m_globalData[t1], t1
 1565 loadConstantOrVariablePayload(t2, CellTag, t0, .opGetByValSlow)
 1566 loadp JSGlobalData::jsArrayClassInfo[t1], t2
 1567 loadConstantOrVariablePayload(t3, Int32Tag, t1, .opGetByValSlow)
 1568 bpneq [t0], t2, .opGetByValSlow
 1569 loadp JSArray::m_storage[t0], t3
 1570 biaeq t1, JSArray::m_vectorLength[t0], .opGetByValSlow
 1571 loadi 4[PC], t0
 1572 loadi ArrayStorage::m_vector + TagOffset[t3, t1, 8], t2
 1573 loadi ArrayStorage::m_vector + PayloadOffset[t3, t1, 8], t1
 1574 bieq t2, EmptyValueTag, .opGetByValSlow
 1575 storei t2, TagOffset[cfr, t0, 8]
 1576 storei t1, PayloadOffset[cfr, t0, 8]
 1577 loadi 16[PC], t0
 1578 valueProfile(t2, t1, t0)
 1579 dispatch(5)
 1580
 1581.opGetByValSlow:
 1582 callHelper(_llint_helper_get_by_val)
 1583 dispatch(5)
 1584
 1585
 1586_llint_op_get_argument_by_val:
 1587 traceExecution()
 1588 loadi 8[PC], t0
 1589 loadi 12[PC], t1
 1590 bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opGetArgumentByValSlow
 1591 loadConstantOrVariablePayload(t1, Int32Tag, t2, .opGetArgumentByValSlow)
 1592 addi 1, t2
 1593 loadi ArgumentCount + PayloadOffset[cfr], t1
 1594 biaeq t2, t1, .opGetArgumentByValSlow
 1595 negi t2
 1596 loadi 4[PC], t3
 1597 loadi ThisArgumentOffset + TagOffset[cfr, t2, 8], t0
 1598 loadi ThisArgumentOffset + PayloadOffset[cfr, t2, 8], t1
 1599 storei t0, TagOffset[cfr, t3, 8]
 1600 storei t1, PayloadOffset[cfr, t3, 8]
 1601 dispatch(5)
 1602
 1603.opGetArgumentByValSlow:
 1604 callHelper(_llint_helper_get_argument_by_val)
 1605 dispatch(5)
 1606
 1607
 1608_llint_op_get_by_pname:
 1609 traceExecution()
 1610 loadi 12[PC], t0
 1611 loadConstantOrVariablePayload(t0, CellTag, t1, .opGetByPnameSlow)
 1612 loadi 16[PC], t0
 1613 bpneq t1, PayloadOffset[cfr, t0, 8], .opGetByPnameSlow
 1614 loadi 8[PC], t0
 1615 loadConstantOrVariablePayload(t0, CellTag, t2, .opGetByPnameSlow)
 1616 loadi 20[PC], t0
 1617 loadi PayloadOffset[cfr, t0, 8], t3
 1618 loadp JSCell::m_structure[t2], t0
 1619 bpneq t0, JSPropertyNameIterator::m_cachedStructure[t3], .opGetByPnameSlow
 1620 loadi 24[PC], t0
 1621 loadi [cfr, t0, 8], t0
 1622 subi 1, t0
 1623 biaeq t0, JSPropertyNameIterator::m_numCacheableSlots[t3], .opGetByPnameSlow
 1624 loadp JSObject::m_propertyStorage[t2], t2
 1625 loadi TagOffset[t2, t0, 8], t1
 1626 loadi PayloadOffset[t2, t0, 8], t3
 1627 loadi 4[PC], t0
 1628 storei t1, TagOffset[cfr, t0, 8]
 1629 storei t3, PayloadOffset[cfr, t0, 8]
 1630 dispatch(7)
 1631
 1632.opGetByPnameSlow:
 1633 callHelper(_llint_helper_get_by_pname)
 1634 dispatch(7)
 1635
 1636
 1637_llint_op_put_by_val:
 1638 traceExecution()
 1639 loadi 4[PC], t0
 1640 loadConstantOrVariablePayload(t0, CellTag, t1, .opPutByValSlow)
 1641 loadi 8[PC], t0
 1642 loadConstantOrVariablePayload(t0, Int32Tag, t2, .opPutByValSlow)
 1643 loadp CodeBlock[cfr], t0
 1644 loadp CodeBlock::m_globalData[t0], t0
 1645 loadp JSGlobalData::jsArrayClassInfo[t0], t0
 1646 bpneq [t1], t0, .opPutByValSlow
 1647 biaeq t2, JSArray::m_vectorLength[t1], .opPutByValSlow
 1648 loadp JSArray::m_storage[t1], t0
 1649 bieq ArrayStorage::m_vector + TagOffset[t0, t2, 8], EmptyValueTag, .opPutByValEmpty
 1650.opPutByValStoreResult:
 1651 loadi 12[PC], t3
 1652 loadConstantOrVariable2Reg(t3, t1, t3)
 1653 writeBarrier(t1, t3)
 1654 storei t1, ArrayStorage::m_vector + TagOffset[t0, t2, 8]
 1655 storei t3, ArrayStorage::m_vector + PayloadOffset[t0, t2, 8]
 1656 dispatch(4)
 1657
 1658.opPutByValEmpty:
 1659 addi 1, ArrayStorage::m_numValuesInVector[t0]
 1660 bib t2, ArrayStorage::m_length[t0], .opPutByValStoreResult
 1661 addi 1, t2, t1
 1662 storei t1, ArrayStorage::m_length[t0]
 1663 jmp .opPutByValStoreResult
 1664
 1665.opPutByValSlow:
 1666 callHelper(_llint_helper_put_by_val)
 1667 dispatch(4)
 1668
 1669
 1670_llint_op_del_by_val:
 1671 traceExecution()
 1672 callHelper(_llint_helper_del_by_val)
 1673 dispatch(4)
 1674
 1675
 1676_llint_op_put_by_index:
 1677 traceExecution()
 1678 callHelper(_llint_helper_put_by_index)
 1679 dispatch(4)
 1680
 1681
 1682_llint_op_put_getter_setter:
 1683 traceExecution()
 1684 callHelper(_llint_helper_put_getter_setter)
 1685 dispatch(5)
 1686
 1687
 1688_llint_op_loop:
 1689 nop
 1690_llint_op_jmp:
 1691 traceExecution()
 1692 dispatchBranch(4[PC])
 1693
 1694
 1695_llint_op_jmp_scopes:
 1696 traceExecution()
 1697 callHelper(_llint_helper_jmp_scopes)
 1698 dispatch(0)
 1699
 1700
 1701macro jumpTrueOrFalse(conditionOp, slow)
 1702 loadi 4[PC], t1
 1703 loadConstantOrVariablePayload(t1, BooleanTag, t0, .slow)
 1704 conditionOp(t0, .target)
 1705 dispatch(3)
 1706
 1707.target:
 1708 dispatchBranch(8[PC])
 1709
 1710.slow:
 1711 callHelper(slow)
 1712 dispatch(0)
 1713end
 1714
 1715_llint_op_loop_if_true:
 1716 nop
 1717_llint_op_jtrue:
 1718 traceExecution()
 1719 jumpTrueOrFalse(
 1720 macro (value, target) btinz value, target end,
 1721 _llint_helper_jtrue)
 1722
 1723
 1724_llint_op_loop_if_false:
 1725 nop
 1726_llint_op_jfalse:
 1727 traceExecution()
 1728 jumpTrueOrFalse(
 1729 macro (value, target) btiz value, target end,
 1730 _llint_helper_jfalse)
 1731
 1732
 1733macro equalNull(cellHandler, immediateHandler)
 1734 loadi 4[PC], t0
 1735 loadi TagOffset[cfr, t0, 8], t1
 1736 loadi PayloadOffset[cfr, t0, 8], t0
 1737 bineq t1, CellTag, .immediate
 1738 loadp JSCell::m_structure[t0], t2
 1739 cellHandler(Structure::m_typeInfo + TypeInfo::m_flags[t2], .target)
 1740 dispatch(3)
 1741
 1742.target:
 1743 dispatchBranch(8[PC])
 1744
 1745.immediate:
 1746 ori 1, t1
 1747 immediateHandler(t1, .target)
 1748 dispatch(3)
 1749end
 1750
 1751_llint_op_jeq_null:
 1752 traceExecution()
 1753 equalNull(
 1754 macro (value, target) btbnz value, MasqueradesAsUndefined, target end,
 1755 macro (value, target) bieq value, NullTag, target end)
 1756
 1757
 1758_llint_op_jneq_null:
 1759 traceExecution()
 1760 equalNull(
 1761 macro (value, target) btbz value, MasqueradesAsUndefined, target end,
 1762 macro (value, target) bineq value, NullTag, target end)
 1763
 1764
 1765_llint_op_jneq_ptr:
 1766 traceExecution()
 1767 loadi 4[PC], t0
 1768 loadi 8[PC], t1
 1769 bineq TagOffset[cfr, t0, 8], CellTag, .opJneqPtrBranch
 1770 bpeq PayloadOffset[cfr, t0, 8], t1, .opJneqPtrFallThrough
 1771.opJneqPtrBranch:
 1772 dispatchBranch(12[PC])
 1773.opJneqPtrFallThrough:
 1774 dispatch(4)
 1775
 1776
 1777macro compare(integerCompare, doubleCompare, helper)
 1778 loadi 4[PC], t2
 1779 loadi 8[PC], t3
 1780 loadConstantOrVariable(t2, t0, t1)
 1781 loadConstantOrVariable2Reg(t3, t2, t3)
 1782 bineq t0, Int32Tag, .op1NotInt
 1783 bineq t2, Int32Tag, .op2NotInt
 1784 integerCompare(t1, t3, .jumpTarget)
 1785 dispatch(4)
 1786
 1787.op1NotInt:
 1788 bia t0, LowestTag, .slow
 1789 bib t2, LowestTag, .op1NotIntOp2Double
 1790 bineq t2, Int32Tag, .slow
 1791 ci2d t3, ft1
 1792 jmp .op1NotIntReady
 1793.op1NotIntOp2Double:
 1794 fii2d t3, t2, ft1
 1795.op1NotIntReady:
 1796 fii2d t1, t0, ft0
 1797 doubleCompare(ft0, ft1, .jumpTarget)
 1798 dispatch(4)
 1799
 1800.op2NotInt:
 1801 ci2d t1, ft0
 1802 bia t2, LowestTag, .slow
 1803 fii2d t3, t2, ft1
 1804 doubleCompare(ft0, ft1, .jumpTarget)
 1805 dispatch(4)
 1806
 1807.jumpTarget:
 1808 dispatchBranch(12[PC])
 1809
 1810.slow:
 1811 callHelper(helper)
 1812 dispatch(0)
 1813end
 1814
 1815_llint_op_loop_if_less:
 1816 nop
 1817_llint_op_jless:
 1818 traceExecution()
 1819 compare(
 1820 macro (left, right, target) bilt left, right, target end,
 1821 macro (left, right, target) bdlt left, right, target end,
 1822 _llint_helper_jless)
 1823
 1824
 1825_llint_op_jnless:
 1826 traceExecution()
 1827 compare(
 1828 macro (left, right, target) bigteq left, right, target end,
 1829 macro (left, right, target) bdgtequn left, right, target end,
 1830 _llint_helper_jnless)
 1831
 1832
 1833_llint_op_loop_if_greater:
 1834 nop
 1835_llint_op_jgreater:
 1836 traceExecution()
 1837 compare(
 1838 macro (left, right, target) bigt left, right, target end,
 1839 macro (left, right, target) bdgt left, right, target end,
 1840 _llint_helper_jgreater)
 1841
 1842
 1843_llint_op_jngreater:
 1844 traceExecution()
 1845 compare(
 1846 macro (left, right, target) bilteq left, right, target end,
 1847 macro (left, right, target) bdltequn left, right, target end,
 1848 _llint_helper_jngreater)
 1849
 1850
 1851_llint_op_loop_if_lesseq:
 1852 nop
 1853_llint_op_jlesseq:
 1854 traceExecution()
 1855 compare(
 1856 macro (left, right, target) bilteq left, right, target end,
 1857 macro (left, right, target) bdlteq left, right, target end,
 1858 _llint_helper_jlesseq)
 1859
 1860
 1861_llint_op_jnlesseq:
 1862 traceExecution()
 1863 compare(
 1864 macro (left, right, target) bigt left, right, target end,
 1865 macro (left, right, target) bdgtun left, right, target end,
 1866 _llint_helper_jnlesseq)
 1867
 1868
 1869_llint_op_loop_if_greatereq:
 1870 nop
 1871_llint_op_jgreatereq:
 1872 traceExecution()
 1873 compare(
 1874 macro (left, right, target) bigteq left, right, target end,
 1875 macro (left, right, target) bdgteq left, right, target end,
 1876 _llint_helper_jgreatereq)
 1877
 1878
 1879_llint_op_jngreatereq:
 1880 traceExecution()
 1881 compare(
 1882 macro (left, right, target) bilt left, right, target end,
 1883 macro (left, right, target) bdltun left, right, target end,
 1884 _llint_helper_jngreatereq)
 1885
 1886
 1887_llint_op_loop_hint:
 1888 traceExecution()
 1889 checkSwitchToJITForLoop()
 1890 dispatch(1)
 1891
 1892
 1893_llint_op_switch_imm:
 1894 traceExecution()
 1895 loadi 12[PC], t2
 1896 loadi 4[PC], t3
 1897 loadConstantOrVariable(t2, t1, t0)
 1898 loadp CodeBlock[cfr], t2
 1899 loadp CodeBlock::m_rareData[t2], t2
 1900 muli sizeof SimpleJumpTable, t3 # FIXME: would be nice to peephole this!
 1901 loadp CodeBlock::RareData::m_immediateSwitchJumpTables + VectorBufferOffset[t2], t2
 1902 addp t3, t2
 1903 bineq t1, Int32Tag, .opSwitchImmNotInt
 1904 subi SimpleJumpTable::min[t2], t0
 1905 biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchImmFallThrough
 1906 loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t3
 1907 loadi [t3, t0, 4], t1
 1908 btiz t1, .opSwitchImmFallThrough
 1909 dispatchBranchWithOffset(t1)
 1910
 1911.opSwitchImmNotInt:
 1912 bib t1, LowestTag, .opSwitchImmSlow # Go to slow path if it's a double.
 1913.opSwitchImmFallThrough:
 1914 dispatchBranch(8[PC])
 1915
 1916.opSwitchImmSlow:
 1917 callHelper(_llint_helper_switch_imm)
 1918 dispatch(0)
 1919
 1920
 1921_llint_op_switch_char:
 1922 traceExecution()
 1923 loadi 12[PC], t2
 1924 loadi 4[PC], t3
 1925 loadConstantOrVariable(t2, t1, t0)
 1926 loadp CodeBlock[cfr], t2
 1927 loadp CodeBlock::m_rareData[t2], t2
 1928 muli sizeof SimpleJumpTable, t3
 1929 loadp CodeBlock::RareData::m_characterSwitchJumpTables + VectorBufferOffset[t2], t2
 1930 addp t3, t2
 1931 bineq t1, CellTag, .opSwitchCharFallThrough
 1932 loadp JSCell::m_structure[t0], t1
 1933 bbneq Structure::m_typeInfo + TypeInfo::m_type[t1], StringType, .opSwitchCharFallThrough
 1934 loadp JSString::m_value[t0], t0
 1935 bineq StringImpl::m_length[t0], 1, .opSwitchCharFallThrough
 1936 loadp StringImpl::m_data8[t0], t1
 1937 btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit
 1938 loadh [t1], t0
 1939 jmp .opSwitchCharReady
 1940.opSwitchChar8Bit:
 1941 loadb [t1], t0
 1942.opSwitchCharReady:
 1943 subi SimpleJumpTable::min[t2], t0
 1944 biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchCharFallThrough
 1945 loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t2
 1946 loadi [t2, t0, 4], t1
 1947 btiz t1, .opSwitchImmFallThrough
 1948 dispatchBranchWithOffset(t1)
 1949
 1950.opSwitchCharFallThrough:
 1951 dispatchBranch(8[PC])
 1952
 1953
 1954_llint_op_switch_string:
 1955 traceExecution()
 1956 callHelper(_llint_helper_switch_string)
 1957 dispatch(0)
 1958
 1959
 1960_llint_op_new_func:
 1961 traceExecution()
 1962 btiz 12[PC], .opNewFuncUnchecked
 1963 loadi 4[PC], t1
 1964 bineq TagOffset[cfr, t1, 8], EmptyValueTag, .opNewFuncDone
 1965.opNewFuncUnchecked:
 1966 callHelper(_llint_helper_new_func)
 1967.opNewFuncDone:
 1968 dispatch(4)
 1969
 1970
 1971_llint_op_new_func_exp:
 1972 traceExecution()
 1973 callHelper(_llint_helper_new_func_exp)
 1974 dispatch(3)
 1975
 1976
 1977macro doCall(helper)
 1978 loadi 4[PC], t0
 1979 loadi 16[PC], t1
 1980 loadp LLIntCallLinkInfo::callee[t1], t2
 1981 loadConstantOrVariablePayload(t0, CellTag, t3, .opCallSlow)
 1982 bineq t3, t2, .opCallSlow
 1983 loadi 12[PC], t3
 1984 addp 24, PC
 1985 lshifti 3, t3
 1986 addp cfr, t3 # t3 contains the new value of cfr
 1987 loadp JSFunction::m_scopeChain[t2], t0
 1988 storei t2, Callee + PayloadOffset[t3]
 1989 storei t0, ScopeChain + PayloadOffset[t3]
 1990 loadi 8 - 24[PC], t2
 1991 storei PC, ArgumentCount + TagOffset[cfr]
 1992 storep cfr, CallerFrame[t3]
 1993 storei t2, ArgumentCount + PayloadOffset[t3]
 1994 storei CellTag, Callee + TagOffset[t3]
 1995 storei CellTag, ScopeChain + TagOffset[t3]
 1996 move t3, cfr
 1997 call LLIntCallLinkInfo::machineCodeTarget[t1]
 1998 dispatchAfterCall()
 1999
 2000.opCallSlow:
 2001 slowPathForCall(6, helper)
 2002end
 2003
 2004_llint_op_call:
 2005 traceExecution()
 2006 doCall(_llint_helper_call)
 2007
 2008
 2009_llint_op_construct:
 2010 traceExecution()
 2011 doCall(_llint_helper_construct)
 2012
 2013
 2014_llint_op_call_varargs:
 2015 traceExecution()
 2016 slowPathForCall(6, _llint_helper_call_varargs)
 2017
 2018
 2019_llint_op_call_eval:
 2020 traceExecution()
 2021
 2022 # Eval is executed in one of two modes:
 2023 #
 2024 # 1) We find that we're really invoking eval() in which case the
 2025 # execution is perfomed entirely inside the helper, and it
 2026 # returns the PC of a function that just returns the return value
 2027 # that the eval returned.
 2028 #
 2029 # 2) We find that we're invoking something called eval() that is not
 2030 # the real eval. Then the helper returns the PC of the thing to
 2031 # call, and we call it.
 2032 #
 2033 # This allows us to handle two cases, which would require a total of
 2034 # up to four pieces of state that cannot be easily packed into two
 2035 # registers (C functions can return up to two registers, easily):
 2036 #
 2037 # - The call frame register. This may or may not have been modified
 2038 # by the helper, but the convention is that it returns it. It's not
 2039 # totally clear if that's necessary, since the cfr is callee save.
 2040 # But that's our style in this here interpreter so we stick with it.
 2041 #
 2042 # - A bit to say if the helper successfully executed the eval and has
 2043 # the return value, or did not execute the eval but has a PC for us
 2044 # to call.
 2045 #
 2046 # - Either:
 2047 # - The JS return value (two registers), or
 2048 #
 2049 # - The PC to call.
 2050 #
 2051 # It turns out to be easier to just always have this return the cfr
 2052 # and a PC to call, and that PC may be a dummy thunk that just
 2053 # returns the JS value that the eval returned.
 2054
 2055 slowPathForCall(4, _llint_helper_call_eval)
 2056
 2057
 2058_llint_generic_return_point:
 2059 dispatchAfterCall()
 2060
 2061
 2062_llint_op_tear_off_activation:
 2063 traceExecution()
 2064 loadi 4[PC], t0
 2065 loadi 8[PC], t1
 2066 bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opTearOffActivationCreated
 2067 bieq TagOffset[cfr, t1, 8], EmptyValueTag, .opTearOffActivationNotCreated
 2068.opTearOffActivationCreated:
 2069 callHelper(_llint_helper_tear_off_activation)
 2070.opTearOffActivationNotCreated:
 2071 dispatch(3)
 2072
 2073
 2074_llint_op_tear_off_arguments:
 2075 traceExecution()
 2076 loadi 4[PC], t0
 2077 subi 1, t0 # Get the unmodifiedArgumentsRegister
 2078 bieq TagOffset[cfr, t0, 8], EmptyValueTag, .opTearOffArgumentsNotCreated
 2079 callHelper(_llint_helper_tear_off_arguments)
 2080.opTearOffArgumentsNotCreated:
 2081 dispatch(2)
 2082
 2083
 2084macro doReturn()
 2085 loadp ReturnPC[cfr], t2
 2086 loadp CallerFrame[cfr], cfr
 2087 restoreReturnAddressBeforeReturn(t2)
 2088 ret
 2089end
 2090
 2091_llint_op_ret:
 2092 traceExecution()
 2093 checkSwitchToJITForEpilogue()
 2094 loadi 4[PC], t2
 2095 loadConstantOrVariable(t2, t1, t0)
 2096 doReturn()
 2097
 2098
 2099_llint_op_call_put_result:
 2100 loadi 4[PC], t2
 2101 loadi 8[PC], t3
 2102 storei t1, TagOffset[cfr, t2, 8]
 2103 storei t0, PayloadOffset[cfr, t2, 8]
 2104 valueProfile(t1, t0, t3)
 2105 traceExecution() # Needs to be here because it would clobber t1, t0
 2106 dispatch(3)
 2107
 2108
 2109_llint_op_ret_object_or_this:
 2110 traceExecution()
 2111 checkSwitchToJITForEpilogue()
 2112 loadi 4[PC], t2
 2113 loadConstantOrVariable(t2, t1, t0)
 2114 bineq t1, CellTag, .opRetObjectOrThisNotObject
 2115 loadp JSCell::m_structure[t0], t2
 2116 bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opRetObjectOrThisNotObject
 2117 doReturn()
 2118
 2119.opRetObjectOrThisNotObject:
 2120 loadi 8[PC], t2
 2121 loadConstantOrVariable(t2, t1, t0)
 2122 doReturn()
 2123
 2124
 2125_llint_op_method_check:
 2126 traceExecution()
 2127 # We ignore method checks and use normal get_by_id optimizations.
 2128 dispatch(1)
 2129
 2130
 2131_llint_op_strcat:
 2132 traceExecution()
 2133 callHelper(_llint_helper_strcat)
 2134 dispatch(4)
 2135
 2136
 2137_llint_op_to_primitive:
 2138 traceExecution()
 2139 loadi 8[PC], t2
 2140 loadi 4[PC], t3
 2141 loadConstantOrVariable(t2, t1, t0)
 2142 bineq t1, CellTag, .opToPrimitiveIsImm
 2143 loadp JSCell::m_structure[t0], t2
 2144 bbneq Structure::m_typeInfo + TypeInfo::m_type[t2], StringType, .opToPrimitiveSlowCase
 2145.opToPrimitiveIsImm:
 2146 storei t1, TagOffset[cfr, t3, 8]
 2147 storei t0, PayloadOffset[cfr, t3, 8]
 2148 dispatch(3)
 2149
 2150.opToPrimitiveSlowCase:
 2151 callHelper(_llint_helper_to_primitive)
 2152 dispatch(3)
 2153
 2154
 2155_llint_op_get_pnames:
 2156 traceExecution()
 2157 callHelper(_llint_helper_get_pnames)
 2158 dispatch(0) # The helper either advances the PC or jumps us to somewhere else.
 2159
 2160
 2161_llint_op_next_pname:
 2162 traceExecution()
 2163 loadi 12[PC], t1
 2164 loadi 16[PC], t2
 2165 loadi PayloadOffset[cfr, t1, 8], t0
 2166 bieq t0, PayloadOffset[cfr, t2, 8], .opNextPnameEnd
 2167 loadi 20[PC], t2
 2168 loadi PayloadOffset[cfr, t2, 8], t2
 2169 loadp JSPropertyNameIterator::m_jsStrings[t2], t3
 2170 loadi [t3, t0, 8], t3
 2171 addi 1, t0
 2172 storei t0, PayloadOffset[cfr, t1, 8]
 2173 loadi 4[PC], t1
 2174 storei CellTag, TagOffset[cfr, t1, 8]
 2175 storei t3, PayloadOffset[cfr, t1, 8]
 2176 loadi 8[PC], t3
 2177 loadi PayloadOffset[cfr, t3, 8], t3
 2178 loadp JSCell::m_structure[t3], t1
 2179 bpneq t1, JSPropertyNameIterator::m_cachedStructure[t2], .opNextPnameSlow
 2180 loadp JSPropertyNameIterator::m_cachedPrototypeChain[t2], t0
 2181 loadp StructureChain::m_vector[t0], t0
 2182 btpz [t0], .opNextPnameTarget
 2183.opNextPnameCheckPrototypeLoop:
 2184 bieq Structure::m_prototype + TagOffset[t1], NullTag, .opNextPnameSlow
 2185 loadp Structure::m_prototype + PayloadOffset[t1], t2
 2186 loadp JSCell::m_structure[t2], t1
 2187 bpneq t1, [t0], .opNextPnameSlow
 2188 addp 4, t0
 2189 btpnz [t0], .opNextPnameCheckPrototypeLoop
 2190.opNextPnameTarget:
 2191 dispatchBranch(24[PC])
 2192
 2193.opNextPnameEnd:
 2194 dispatch(7)
 2195
 2196.opNextPnameSlow:
 2197 callHelper(_llint_helper_next_pname) # This either keeps the PC where it was (causing us to loop) or sets it to target.
 2198 dispatch(0)
 2199
 2200
 2201_llint_op_push_scope:
 2202 traceExecution()
 2203 callHelper(_llint_helper_push_scope)
 2204 dispatch(2)
 2205
 2206
 2207_llint_op_pop_scope:
 2208 traceExecution()
 2209 callHelper(_llint_helper_pop_scope)
 2210 dispatch(1)
 2211
 2212
 2213_llint_op_push_new_scope:
 2214 traceExecution()
 2215 callHelper(_llint_helper_push_new_scope)
 2216 dispatch(4)
 2217
 2218
 2219_llint_op_catch:
 2220 # This is where we end up from the JIT's throw trampoline (because the
 2221 # machine code return address will be set to _llint_op_catch), and from
 2222 # the interpreter's throw trampoline (see _llint_throw_trampoline).
 2223 # The JIT throwing protocol calls for the cfr to be in t0. The throwing
 2224 # code must have known that we were throwing to the interpreter, and have
 2225 # set JSGlobalData::targetInterpreterPCForThrow.
 2226 move t0, cfr
 2227 loadp JITStackFrame::globalData[sp], t3
 2228 loadi JSGlobalData::targetInterpreterPCForThrow[t3], PC
 2229 loadi JSGlobalData::exception + PayloadOffset[t3], t0
 2230 loadi JSGlobalData::exception + TagOffset[t3], t1
 2231 storei 0, JSGlobalData::exception + PayloadOffset[t3]
 2232 storei EmptyValueTag, JSGlobalData::exception + TagOffset[t3]
 2233 loadi 4[PC], t2
 2234 storei t0, PayloadOffset[cfr, t2, 8]
 2235 storei t1, TagOffset[cfr, t2, 8]
 2236 traceExecution() # This needs to be here because we don't want to clobber t0, t1, t2, t3 above.
 2237 dispatch(2)
 2238
 2239
 2240_llint_op_throw:
 2241 traceExecution()
 2242 callHelper(_llint_helper_throw)
 2243 dispatch(2)
 2244
 2245
 2246_llint_op_throw_reference_error:
 2247 traceExecution()
 2248 callHelper(_llint_helper_throw_reference_error)
 2249 dispatch(2)
 2250
 2251
 2252_llint_op_jsr:
 2253 traceExecution()
 2254 loadi 4[PC], t0
 2255 addi 3 * 4, PC, t1
 2256 storei t1, [cfr, t0, 8]
 2257 dispatchBranch(8[PC])
 2258
 2259
 2260_llint_op_sret:
 2261 traceExecution()
 2262 loadi 4[PC], t0
 2263 loadp [cfr, t0, 8], PC
 2264 dispatch(0)
 2265
 2266
 2267_llint_op_debug:
 2268 traceExecution()
 2269 callHelper(_llint_helper_debug)
 2270 dispatch(4)
 2271
 2272
 2273_llint_op_profile_will_call:
 2274 traceExecution()
 2275 loadp JITStackFrame::enabledProfilerReference[sp], t0
 2276 btpz [t0], .opProfileWillCallDone
 2277 callHelper(_llint_helper_profile_will_call)
 2278.opProfileWillCallDone:
 2279 dispatch(2)
 2280
 2281
 2282_llint_op_profile_did_call:
 2283 traceExecution()
 2284 loadp JITStackFrame::enabledProfilerReference[sp], t0
 2285 btpz [t0], .opProfileWillCallDone
 2286 callHelper(_llint_helper_profile_did_call)
 2287.opProfileDidCallDone:
 2288 dispatch(2)
 2289
 2290
 2291_llint_op_end:
 2292 traceExecution()
 2293 checkSwitchToJITForEpilogue()
 2294 loadi 4[PC], t0
 2295 loadi TagOffset[cfr, t0, 8], t1
 2296 loadi PayloadOffset[cfr, t0, 8], t0
 2297 doReturn()
 2298
 2299
 2300_llint_throw_from_helper_trampoline:
 2301 # When throwing from the interpreter (i.e. throwing from LLIntHelpers), so
 2302 # the throw target is not necessarily interpreted code, we come to here.
 2303 # This essentially emulates the JIT's throwing protocol.
 2304 loadp JITStackFrame::globalData[sp], t1
 2305 loadp JSGlobalData::callFrameForThrow[t1], t0
 2306 jmp JSGlobalData::targetMachinePCForThrow[t1]
 2307
 2308
 2309_llint_throw_during_call_trampoline:
 2310 preserveReturnAddressAfterCall(t2)
 2311 loadp JITStackFrame::globalData[sp], t1
 2312 loadp JSGlobalData::callFrameForThrow[t1], t0
 2313 jmp JSGlobalData::targetMachinePCForThrow[t1]
 2314
 2315
 2316# Lastly, make sure that we can link even though we don't support all opcodes.
 2317# These opcodes should never arise when using LLInt or either JIT. We assert
 2318# as much.
 2319
 2320macro notSupported()
 2321 if ASSERT_ENABLED
 2322 crash()
 2323 else
 2324 # We should use whatever the smallest possible instruction is, just to
 2325 # ensure that there is a gap between instruction labels. If multiple
 2326 # smallest instructions exist, we should pick the one that is most
 2327 # likely result in execution being halted. Currently that is the break
 2328 # instruction on all architectures we're interested in. (Break is int3
 2329 # on Intel, which is 1 byte, and bkpt on ARMv7, which is 2 bytes.)
 2330 break
 2331 end
 2332end
 2333
 2334_llint_op_get_array_length:
 2335 notSupported()
 2336
 2337_llint_op_get_by_id_chain:
 2338 notSupported()
 2339
 2340_llint_op_get_by_id_custom_chain:
 2341 notSupported()
 2342
 2343_llint_op_get_by_id_custom_proto:
 2344 notSupported()
 2345
 2346_llint_op_get_by_id_custom_self:
 2347 notSupported()
 2348
 2349_llint_op_get_by_id_generic:
 2350 notSupported()
 2351
 2352_llint_op_get_by_id_getter_chain:
 2353 notSupported()
 2354
 2355_llint_op_get_by_id_getter_proto:
 2356 notSupported()
 2357
 2358_llint_op_get_by_id_getter_self:
 2359 notSupported()
 2360
 2361_llint_op_get_by_id_proto:
 2362 notSupported()
 2363
 2364_llint_op_get_by_id_self:
 2365 notSupported()
 2366
 2367_llint_op_get_string_length:
 2368 notSupported()
 2369
 2370_llint_op_put_by_id_generic:
 2371 notSupported()
 2372
 2373_llint_op_put_by_id_replace:
 2374 notSupported()
 2375
 2376_llint_op_put_by_id_transition:
 2377 notSupported()
 2378
 2379
 2380# Indicate the end of LLInt.
 2381_llint_end:
 2382 crash()
 2383
0

Source/JavaScriptCore/llint/LowLevelInterpreter.cpp

 1/*
 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27#include "LowLevelInterpreter.h"
 28
 29#if ENABLE(LLINT)
 30
 31#include "LLIntOfflineAsmConfig.h"
 32#include <wtf/InlineASM.h>
 33
 34// This is a file generated by offlineasm, which contains all of the assembly code
 35// for the interpreter, as compiled from LowLevelInterpreter.asm.
 36#include "LLIntAssembly.h"
 37
 38#endif // ENABLE(LLINT)
0

Source/JavaScriptCore/llint/LowLevelInterpreter.h

 1/*
 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef LowLevelInterpreter_h
 27#define LowLevelInterpreter_h
 28
 29#include <wtf/Platform.h>
 30
 31#if ENABLE(LLINT)
 32
 33#include "Opcode.h"
 34
 35#define LLINT_INSTRUCTION_DECL(opcode, length) extern "C" void llint_##opcode();
 36 FOR_EACH_OPCODE_ID(LLINT_INSTRUCTION_DECL);
 37#undef LLINT_INSTRUCTION_DECL
 38
 39extern "C" void llint_begin();
 40extern "C" void llint_end();
 41extern "C" void llint_program_prologue();
 42extern "C" void llint_eval_prologue();
 43extern "C" void llint_function_for_call_prologue();
 44extern "C" void llint_function_for_construct_prologue();
 45extern "C" void llint_function_for_call_arity_check();
 46extern "C" void llint_function_for_construct_arity_check();
 47extern "C" void llint_generic_return_point();
 48extern "C" void llint_throw_from_helper_trampoline();
 49extern "C" void llint_throw_during_call_trampoline();
 50
 51#endif // ENABLE(LLINT)
 52
 53#endif // LowLevelInterpreter_h
0

Source/JavaScriptCore/offlineasm/armv7.rb

 1# Copyright (C) 2011 Apple Inc. All rights reserved.
 2#
 3# Redistribution and use in source and binary forms, with or without
 4# modification, are permitted provided that the following conditions
 5# are met:
 6# 1. Redistributions of source code must retain the above copyright
 7# notice, this list of conditions and the following disclaimer.
 8# 2. Redistributions in binary form must reproduce the above copyright
 9# notice, this list of conditions and the following disclaimer in the
 10# documentation and/or other materials provided with the distribution.
 11#
 12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 22# THE POSSIBILITY OF SUCH DAMAGE.
 23
 24require "ast"
 25require "opt"
 26
 27class Node
 28 def armV7Single
 29 doubleOperand = armV7Operand
 30 raise "Bogus register name #{doubleOperand}" unless doubleOperand =~ /^d/
 31 "s" + ($~.post_match.to_i * 2).to_s
 32 end
 33end
 34
 35class SpecialRegister < NoChildren
 36 def initialize(name)
 37 @name = name
 38 end
 39
 40 def armV7Operand
 41 @name
 42 end
 43
 44 def address?
 45 false
 46 end
 47
 48 def label?
 49 false
 50 end
 51
 52 def immediate?
 53 false
 54 end
 55
 56 def register?
 57 true
 58 end
 59end
 60
 61ARMv7_EXTRA_GPRS = [SpecialRegister.new("r9"), SpecialRegister.new("r8"), SpecialRegister.new("r3")]
 62ARMv7_EXTRA_FPRS = [SpecialRegister.new("d7")]
 63ARMv7_SCRATCH_FPR = SpecialRegister.new("d8")
 64
 65def armV7MoveImmediate(value, register)
 66 # Currently we only handle the simple cases, and fall back to mov/movt for the complex ones.
 67 if value >= 0 && value < 256
 68 $asm.puts "movw #{register.armV7Operand}, \##{value}"
 69 elsif (~value) >= 0 && (~value) < 256
 70 $asm.puts "mvn #{register.armV7Operand}, \##{~value}"
 71 else
 72 $asm.puts "movw #{register.armV7Operand}, \##{value & 0xffff}"
 73 if (value & 0xffff0000) != 0
 74 $asm.puts "movt #{register.armV7Operand}, \##{value >> 16}"
 75 end
 76 end
 77end
 78
 79class RegisterID
 80 def armV7Operand
 81 case name
 82 when "t0", "a0", "r0"
 83 "r0"
 84 when "t1", "a1", "r1"
 85 "r1"
 86 when "t2", "a2"
 87 "r2"
 88 when "a3"
 89 "r3"
 90 when "t3"
 91 "r4"
 92 when "t4"
 93 "r7"
 94 when "cfr"
 95 "r5"
 96 when "lr"
 97 "lr"
 98 when "sp"
 99 "sp"
 100 else
 101 raise "Bad register #{name} for ARMv7 at #{codeOriginString}"
 102 end
 103 end
 104end
 105
 106class FPRegisterID
 107 def armV7Operand
 108 case name
 109 when "ft0", "fr"
 110 "d0"
 111 when "ft1"
 112 "d1"
 113 when "ft2"
 114 "d2"
 115 when "ft3"
 116 "d3"
 117 when "ft4"
 118 "d4"
 119 when "ft5"
 120 "d5"
 121 else
 122 raise "Bad register #{name} for ARMv7 at #{codeOriginString}"
 123 end
 124 end
 125end
 126
 127class Immediate
 128 def armV7Operand
 129 raise "Invalid immediate #{value} at #{codeOriginString}" if value < 0 or value > 255
 130 "\##{value}"
 131 end
 132end
 133
 134class Address
 135 def armV7Operand
 136 raise "Bad offset at #{codeOriginString}" if offset.value < -0xff or offset.value > 0xfff
 137 "[#{base.armV7Operand}, \##{offset.value}]"
 138 end
 139end
 140
 141class BaseIndex
 142 def armV7Operand
 143 raise "Bad offset at #{codeOriginString}" if offset.value != 0
 144 "[#{base.armV7Operand}, #{index.armV7Operand}, lsl \##{scaleShift}]"
 145 end
 146end
 147
 148class AbsoluteAddress
 149 def armV7Operand
 150 raise "Unconverted absolute address at #{codeOriginString}"
 151 end
 152end
 153
 154#
 155# Lowering of branch ops. For example:
 156#
 157# baddiz foo, bar, baz
 158#
 159# will become:
 160#
 161# addi foo, bar
 162# bz baz
 163#
 164
 165def armV7LowerBranchOps(list)
 166 newList = []
 167 list.each {
 168 | node |
 169 if node.is_a? Instruction
 170 case node.opcode
 171 when /^b(addi|subi|ori|addp)/
 172 op = $1
 173 branch = "b" + $~.post_match
 174
 175 case op
 176 when "addi", "addp"
 177 op = "addis"
 178 when "subi"
 179 op = "subis"
 180 when "ori"
 181 op = "oris"
 182 end
 183
 184 newList << Instruction.new(node.codeOrigin, op, node.operands[0..-2])
 185 newList << Instruction.new(node.codeOrigin, branch, [node.operands[-1]])
 186 when "bmulio"
 187 tmp1 = Tmp.new(node.codeOrigin, :gpr)
 188 tmp2 = Tmp.new(node.codeOrigin, :gpr)
 189 newList << Instruction.new(node.codeOrigin, "smulli", [node.operands[0], node.operands[1], node.operands[1], tmp1])
 190 newList << Instruction.new(node.codeOrigin, "rshifti", [node.operands[-2], Immediate.new(node.codeOrigin, 31), tmp2])
 191 newList << Instruction.new(node.codeOrigin, "bineq", [tmp1, tmp2, node.operands[-1]])
 192 when /^bmuli/
 193 condition = $~.post_match
 194 newList << Instruction.new(node.codeOrigin, "muli", node.operands[0..-2])
 195 newList << Instruction.new(node.codeOrigin, "bti" + condition, [node.operands[-2], node.operands[-1]])
 196 else
 197 newList << node
 198 end
 199 else
 200 newList << node
 201 end
 202 }
 203 newList
 204end
 205
 206#
 207# Lowering of shift ops. For example:
 208#
 209# lshifti foo, bar
 210#
 211# will become:
 212#
 213# andi foo, 31, tmp
 214# lshifti tmp, bar
 215#
 216
 217def armV7SanitizeShift(operand, list)
 218 return operand if operand.immediate?
 219
 220 tmp = Tmp.new(operand.codeOrigin, :gpr)
 221 list << Instruction.new(operand.codeOrigin, "andi", [operand, Immediate.new(operand.codeOrigin, 31), tmp])
 222 tmp
 223end
 224
 225def armV7LowerShiftOps(list)
 226 newList = []
 227 list.each {
 228 | node |
 229 if node.is_a? Instruction
 230 case node.opcode
 231 when "lshifti", "rshifti", "urshifti"
 232 if node.operands.size == 2
 233 newList << Instruction.new(node.codeOrigin, node.opcode, [armV7SanitizeShift(node.operands[0], newList), node.operands[1]])
 234 else
 235 newList << Instruction.new(node.codeOrigin, node.opcode, [node.operands[0], armV7SanitizeShift(node.operands[1], newList), node.operands[2]])
 236 raise "Wrong number of operands for shift at #{node.codeOriginString}" unless node.operands.size == 3
 237 end
 238 else
 239 newList << node
 240 end
 241 else
 242 newList << node
 243 end
 244 }
 245 newList
 246end
 247
 248#
 249# Lowering of malformed addresses. For example:
 250#
 251# loadp 10000[foo], bar
 252#
 253# will become:
 254#
 255# move 10000, tmp
 256# addp foo, tmp
 257# loadp 0[tmp], bar
 258#
 259
 260class Node
 261 def armV7LowerMalformedAddressesRecurse(list)
 262 mapChildren {
 263 | node |
 264 node.armV7LowerMalformedAddressesRecurse(list)
 265 }
 266 end
 267end
 268
 269class Address
 270 def armV7LowerMalformedAddressesRecurse(list)
 271 if offset.value < -0xff or offset.value > 0xfff
 272 tmp = Tmp.new(codeOrigin, :gpr)
 273 list << Instruction.new(codeOrigin, "move", [offset, tmp])
 274 list << Instruction.new(codeOrigin, "addp", [base, tmp])
 275 Address.new(codeOrigin, tmp, Immediate.new(codeOrigin, 0))
 276 else
 277 self
 278 end
 279 end
 280end
 281
 282class BaseIndex
 283 def armV7LowerMalformedAddressesRecurse(list)
 284 if offset.value != 0
 285 tmp = Tmp.new(codeOrigin, :gpr)
 286 list << Instruction.new(codeOrigin, "move", [offset, tmp])
 287 list << Instruction.new(codeOrigin, "addp", [base, tmp])
 288 BaseIndex.new(codeOrigin, tmp, index, scale, Immediate.new(codeOrigin, 0))
 289 else
 290 self
 291 end
 292 end
 293end
 294
 295class AbsoluteAddress
 296 def armV7LowerMalformedAddressesRecurse(list)
 297 tmp = Tmp.new(codeOrigin, :gpr)
 298 list << Instruction.new(codeOrigin, "move", [address, tmp])
 299 Address.new(codeOrigin, tmp, Immediate.new(codeOrigin, 0))
 300 end
 301end
 302
 303def armV7LowerMalformedAddresses(list)
 304 newList = []
 305 list.each {
 306 | node |
 307 newList << node.armV7LowerMalformedAddressesRecurse(newList)
 308 }
 309 newList
 310end
 311
 312#
 313# Lowering of malformed addresses in double loads and stores. For example:
 314#
 315# loadd [foo, bar, 8], baz
 316#
 317# becomes:
 318#
 319# leap [foo, bar, 8], tmp
 320# loadd [tmp], baz
 321#
 322
 323class Node
 324 def armV7DoubleAddress(list)
 325 self
 326 end
 327end
 328
 329class BaseIndex
 330 def armV7DoubleAddress(list)
 331 tmp = Tmp.new(codeOrigin, :gpr)
 332 list << Instruction.new(codeOrigin, "leap", [self, tmp])
 333 Address.new(codeOrigin, tmp, Immediate.new(codeOrigin, 0))
 334 end
 335end
 336
 337def armV7LowerMalformedAddressesDouble(list)
 338 newList = []
 339 list.each {
 340 | node |
 341 if node.is_a? Instruction
 342 case node.opcode
 343 when "loadd"
 344 newList << Instruction.new(node.codeOrigin, "loadd", [node.operands[0].armV7DoubleAddress(newList), node.operands[1]])
 345 when "stored"
 346 newList << Instruction.new(node.codeOrigin, "stored", [node.operands[0], node.operands[1].armV7DoubleAddress(newList)])
 347 else
 348 newList << node
 349 end
 350 else
 351 newList << node
 352 end
 353 }
 354 newList
 355end
 356
 357#
 358# Lowering of misplaced immediates. For example:
 359#
 360# storei 0, [foo]
 361#
 362# will become:
 363#
 364# move 0, tmp
 365# storei tmp, [foo]
 366#
 367
 368def armV7LowerMisplacedImmediates(list)
 369 newList = []
 370 list.each {
 371 | node |
 372 if node.is_a? Instruction
 373 case node.opcode
 374 when "storei", "storep"
 375 operands = node.operands
 376 newOperands = []
 377 operands.each {
 378 | operand |
 379 if operand.is_a? Immediate
 380 tmp = Tmp.new(operand.codeOrigin, :gpr)
 381 newList << Instruction.new(operand.codeOrigin, "move", [operand, tmp])
 382 newOperands << tmp
 383 else
 384 newOperands << operand
 385 end
 386 }
 387 newList << Instruction.new(node.codeOrigin, node.opcode, newOperands)
 388 else
 389 newList << node
 390 end
 391 else
 392 newList << node
 393 end
 394 }
 395 newList
 396end
 397
 398#
 399# Lowering of malformed immediates except when used in a "move" instruction.
 400# For example:
 401#
 402# addp 642641, foo
 403#
 404# will become:
 405#
 406# move 642641, tmp
 407# addp tmp, foo
 408#
 409
 410class Node
 411 def armV7LowerMalformedImmediatesRecurse(list)
 412 mapChildren {
 413 | node |
 414 node.armV7LowerMalformedImmediatesRecurse(list)
 415 }
 416 end
 417end
 418
 419class Address
 420 def armV7LowerMalformedImmediatesRecurse(list)
 421 self
 422 end
 423end
 424
 425class BaseIndex
 426 def armV7LowerMalformedImmediatesRecurse(list)
 427 self
 428 end
 429end
 430
 431class AbsoluteAddress
 432 def armV7LowerMalformedImmediatesRecurse(list)
 433 self
 434 end
 435end
 436
 437class Immediate
 438 def armV7LowerMalformedImmediatesRecurse(list)
 439 if value < 0 or value > 255
 440 tmp = Tmp.new(codeOrigin, :gpr)
 441 list << Instruction.new(codeOrigin, "move", [self, tmp])
 442 tmp
 443 else
 444 self
 445 end
 446 end
 447end
 448
 449def armV7LowerMalformedImmediates(list)
 450 newList = []
 451 list.each {
 452 | node |
 453 if node.is_a? Instruction
 454 case node.opcode
 455 when "move"
 456 newList << node
 457 when "addi", "addp", "addis", "subi", "subp", "subis"
 458 if node.operands[0].is_a? Immediate and
 459 node.operands[0].value < 0 and
 460 node.operands[0].value >= 255 and
 461 node.operands.size == 2
 462 if node.opcode =~ /add/
 463 newOpcode = "sub" + node.opcode[-1..-1]
 464 else
 465 newOpcode = "add" + node.opcode[-1..-1]
 466 end
 467 newList << Instruction.new(node.codeOrigin, newOpcode,
 468 [Immediate.new(-node.operands[0].value)] + node.operands[1..-1])
 469 else
 470 newList << node.armV7LowerMalformedImmediatesRecurse(newList)
 471 end
 472 when "muli"
 473 if node.operands[0].is_a? Immediate
 474 tmp = Tmp.new(codeOrigin, :gpr)
 475 newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp])
 476 newList << Instruction.new(node.codeOrigin, "muli", [tmp] + node.operands[1..-1])
 477 else
 478 newList << node.armV7LowerMalformedImmediatesRecurse(newList)
 479 end
 480 else
 481 newList << node.armV7LowerMalformedImmediatesRecurse(newList)
 482 end
 483 else
 484 newList << node
 485 end
 486 }
 487 newList
 488end
 489
 490#
 491# Lowering of misplaced addresses. For example:
 492#
 493# addi foo, [bar]
 494#
 495# will become:
 496#
 497# loadi [bar], tmp
 498# addi foo, tmp
 499# storei tmp, [bar]
 500#
 501# Another example:
 502#
 503# addi [foo], bar
 504#
 505# will become:
 506#
 507# loadi [foo], tmp
 508# addi tmp, bar
 509#
 510
 511def armV7AsRegister(preList, postList, operand, suffix, needStore)
 512 return operand unless operand.address?
 513
 514 tmp = Tmp.new(operand.codeOrigin, if suffix == "d" then :fpr else :gpr end)
 515 preList << Instruction.new(operand.codeOrigin, "load" + suffix, [operand, tmp])
 516 if needStore
 517 postList << Instruction.new(operand.codeOrigin, "store" + suffix, [tmp, operand])
 518 end
 519 tmp
 520end
 521
 522def armV7AsRegisters(preList, postList, operands, suffix)
 523 newOperands = []
 524 operands.each_with_index {
 525 | operand, index |
 526 newOperands << armV7AsRegister(preList, postList, operand, suffix, index == operands.size - 1)
 527 }
 528 newOperands
 529end
 530
 531def armV7LowerMisplacedAddresses(list)
 532 newList = []
 533 list.each {
 534 | node |
 535 if node.is_a? Instruction
 536 postInstructions = []
 537 case node.opcode
 538 when "addi", "addp", "addis", "andi", "andp", "lshifti", "muli", "negi", "noti", "ori", "oris",
 539 "orp", "rshifti", "urshifti", "subi", "subp", "subis", "xori", "xorp", /^bi/, /^bp/, /^bti/,
 540 /^btp/, /^ci/, /^cp/, /^ti/
 541 newList << Instruction.new(node.codeOrigin,
 542 node.opcode,
 543 armV7AsRegisters(newList, postInstructions, node.operands, "i"))
 544 when "bbeq", "bbneq", "bba", "bbaeq", "bbb", "bbbeq", "btbo", "btbz", "btbnz", "tbz", "tbnz",
 545 "tbo"
 546 newList << Instruction.new(node.codeOrigin,
 547 node.opcode,
 548 armV7AsRegisters(newList, postInstructions, node.operands, "b"))
 549 when "bbgt", "bbgteq", "bblt", "bblteq", "btbs", "tbs"
 550 newList << Instruction.new(node.codeOrigin,
 551 node.opcode,
 552 armV7AsRegisters(newList, postInstructions, node.operands, "bs"))
 553 when "addd", "divd", "subd", "muld", "sqrtd", /^bd/
 554 newList << Instruction.new(node.codeOrigin,
 555 node.opcode,
 556 armV7AsRegisters(newList, postInstructions, node.operands, "d"))
 557 when "jmp", "call"
 558 newList << Instruction.new(node.codeOrigin,
 559 node.opcode,
 560 [armV7AsRegister(newList, postInstructions, node.operands[0], "p", false)])
 561 else
 562 newList << node
 563 end
 564 newList += postInstructions
 565 else
 566 newList << node
 567 end
 568 }
 569 newList
 570end
 571
 572#
 573# Lowering of register reuse in compare instructions. For example:
 574#
 575# cieq t0, t1, t0
 576#
 577# will become:
 578#
 579# mov tmp, t0
 580# cieq tmp, t1, t0
 581#
 582
 583def armV7LowerRegisterReuse(list)
 584 newList = []
 585 list.each {
 586 | node |
 587 if node.is_a? Instruction
 588 case node.opcode
 589 when "cieq", "cineq", "cia", "ciaeq", "cib", "cibeq", "cigt", "cigteq", "cilt", "cilteq",
 590 "cpeq", "cpneq", "cpa", "cpaeq", "cpb", "cpbeq", "cpgt", "cpgteq", "cplt", "cplteq",
 591 "tio", "tis", "tiz", "tinz", "tbo", "tbs", "tbz", "tbnz"
 592 if node.operands.size == 2
 593 if node.operands[0] == node.operands[1]
 594 tmp = Tmp.new(node.codeOrigin, :gpr)
 595 newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp])
 596 newList << Instruction.new(node.codeOrigin, node.opcode, [tmp, node.operands[1]])
 597 else
 598 newList << node
 599 end
 600 else
 601 raise "Wrong number of arguments at #{node.codeOriginString}" unless node.operands.size == 3
 602 if node.operands[0] == node.operands[2]
 603 tmp = Tmp.new(node.codeOrigin, :gpr)
 604 newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp])
 605 newList << Instruction.new(node.codeOrigin, node.opcode, [tmp, node.operands[1], node.operands[2]])
 606 elsif node.operands[1] == node.operands[2]
 607 tmp = Tmp.new(node.codeOrigin, :gpr)
 608 newList << Instruction.new(node.codeOrigin, "move", [node.operands[1], tmp])
 609 newList << Instruction.new(node.codeOrigin, node.opcode, [node.operands[0], tmp, node.operands[2]])
 610 else
 611 newList << node
 612 end
 613 end
 614 else
 615 newList << node
 616 end
 617 else
 618 newList << node
 619 end
 620 }
 621 newList
 622end
 623
 624#
 625# Lea support.
 626#
 627
 628class Address
 629 def armV7EmitLea(destination)
 630 if destination == base
 631 $asm.puts "adds #{destination.armV7Operand}, \##{offset.value}"
 632 else
 633 $asm.puts "adds #{destination.armV7Operand}, #{base.armV7Operand}, \##{offset.value}"
 634 end
 635 end
 636end
 637
 638class BaseIndex
 639 def armV7EmitLea(destination)
 640 raise "Malformed BaseIndex, offset should be zero at #{codeOriginString}" unless offset.value == 0
 641 $asm.puts "add.w #{destination.armV7Operand}, #{base.armV7Operand}, #{index.armV7Operand}, lsl \##{scaleShift}"
 642 end
 643end
 644
 645# FIXME: we could support AbsoluteAddress for lea, but we don't.
 646
 647#
 648# Actual lowering code follows.
 649#
 650
 651class Sequence
 652 def lowerARMv7
 653 myList = @list
 654
 655 # Verify that we will only see instructions and labels.
 656 myList.each {
 657 | node |
 658 unless node.is_a? Instruction or
 659 node.is_a? Label or
 660 node.is_a? LocalLabel or
 661 node.is_a? Skip
 662 raise "Unexpected #{node.inspect} at #{node.codeOrigin}"
 663 end
 664 }
 665
 666 myList = armV7LowerBranchOps(myList)
 667 myList = armV7LowerShiftOps(myList)
 668 myList = armV7LowerMalformedAddresses(myList)
 669 myList = armV7LowerMalformedAddressesDouble(myList)
 670 myList = armV7LowerMisplacedImmediates(myList)
 671 myList = armV7LowerMalformedImmediates(myList)
 672 myList = armV7LowerMisplacedAddresses(myList)
 673 myList = armV7LowerRegisterReuse(myList)
 674 myList = assignRegistersToTemporaries(myList, :gpr, ARMv7_EXTRA_GPRS)
 675 myList = assignRegistersToTemporaries(myList, :fpr, ARMv7_EXTRA_FPRS)
 676 myList.each {
 677 | node |
 678 node.lower("ARMv7")
 679 }
 680 end
 681end
 682
 683def armV7Operands(operands)
 684 operands.map{|v| v.armV7Operand}.join(", ")
 685end
 686
 687def armV7FlippedOperands(operands)
 688 armV7Operands([operands[-1]] + operands[0..-2])
 689end
 690
 691def emitArmV7Compact(opcode2, opcode3, operands)
 692 if operands.size == 3
 693 $asm.puts "#{opcode3} #{armV7FlippedOperands(operands)}"
 694 else
 695 raise unless operands.size == 2
 696 raise unless operands[1].is_a? RegisterID
 697 if operands[0].is_a? Immediate
 698 $asm.puts "#{opcode3} #{operands[1].armV7Operand}, #{operands[1].armV7Operand}, #{operands[0].armV7Operand}"
 699 else
 700 $asm.puts "#{opcode2} #{armV7FlippedOperands(operands)}"
 701 end
 702 end
 703end
 704
 705def emitArmV7(opcode, operands)
 706 if operands.size == 3
 707 $asm.puts "#{opcode} #{armV7FlippedOperands(operands)}"
 708 else
 709 raise unless operands.size == 2
 710 $asm.puts "#{opcode} #{operands[1].armV7Operand}, #{operands[1].armV7Operand}, #{operands[0].armV7Operand}"
 711 end
 712end
 713
 714def emitArmV7DoubleBranch(branchOpcode, operands)
 715 $asm.puts "vcmpe.f64 #{armV7Operands(operands[0..1])}"
 716 $asm.puts "vmrs apsr_nzcv, fpscr"
 717 $asm.puts "#{branchOpcode} #{operands[2].asmLabel}"
 718end
 719
 720def emitArmV7Test(operands)
 721 value = operands[0]
 722 case operands.size
 723 when 2
 724 mask = Immediate.new(codeOrigin, -1)
 725 when 3
 726 mask = operands[1]
 727 else
 728 raise "Expected 2 or 3 operands but got #{operands.size} at #{codeOriginString}"
 729 end
 730
 731 if mask.is_a? Immediate and mask.value == -1
 732 $asm.puts "tst #{value.armV7Operand}, #{value.armV7Operand}"
 733 elsif mask.is_a? Immediate
 734 $asm.puts "tst.w #{value.armV7Operand}, #{mask.armV7Operand}"
 735 else
 736 $asm.puts "tst #{value.armV7Operand}, #{mask.armV7Operand}"
 737 end
 738end
 739
 740def emitArmV7Compare(operands, code)
 741 $asm.puts "movs #{operands[2].armV7Operand}, \#0"
 742 $asm.puts "cmp #{operands[0].armV7Operand}, #{operands[1].armV7Operand}"
 743 $asm.puts "it #{code}"
 744 $asm.puts "mov#{code} #{operands[2].armV7Operand}, \#1"
 745end
 746
 747def emitArmV7TestSet(operands, code)
 748 $asm.puts "movs #{operands[-1].armV7Operand}, \#0"
 749 emitArmV7Test(operands)
 750 $asm.puts "it #{code}"
 751 $asm.puts "mov#{code} #{operands[-1].armV7Operand}, \#1"
 752end
 753
 754class Instruction
 755 def lowerARMv7
 756 $asm.comment codeOriginString
 757 case opcode
 758 when "addi", "addp", "addis"
 759 if opcode == "addis"
 760 suffix = "s"
 761 else
 762 suffix = ""
 763 end
 764 if operands.size == 3 and operands[0].is_a? Immediate
 765 raise unless operands[1].is_a? RegisterID
 766 raise unless operands[2].is_a? RegisterID
 767 if operands[0].value == 0 and suffix.empty?
 768 unless operands[1] == operands[2]
 769 $asm.puts "mov #{operands[2].armV7Operand}, #{operands[1].armV7Operand}"
 770 end
 771 else
 772 $asm.puts "adds #{operands[2].armV7Operand}, #{operands[1].armV7Operand}, #{operands[0].armV7Operand}"
 773 end
 774 elsif operands.size == 3 and operands[0].is_a? RegisterID
 775 raise unless operands[1].is_a? RegisterID
 776 raise unless operands[2].is_a? RegisterID
 777 $asm.puts "adds #{armV7FlippedOperands(operands)}"
 778 else
 779 if operands[0].is_a? Immediate
 780 unless Immediate.new(nil, 0) == operands[0]
 781 $asm.puts "adds #{armV7FlippedOperands(operands)}"
 782 end
 783 else
 784 $asm.puts "add#{suffix} #{armV7FlippedOperands(operands)}"
 785 end
 786 end
 787 when "andi", "andp"
 788 emitArmV7Compact("ands", "and", operands)
 789 when "ori", "orp"
 790 emitArmV7Compact("orrs", "orr", operands)
 791 when "oris"
 792 emitArmV7Compact("orrs", "orrs", operands)
 793 when "xori", "xorp"
 794 emitArmV7Compact("eors", "eor", operands)
 795 when "lshifti"
 796 emitArmV7Compact("lsls", "lsls", operands)
 797 when "rshifti"
 798 emitArmV7Compact("asrs", "asrs", operands)
 799 when "urshifti"
 800 emitArmV7Compact("lsrs", "lsrs", operands)
 801 when "muli"
 802 if operands.size == 2 or operands[0] == operands[2] or operands[1] == operands[2]
 803 emitArmV7("muls", operands)
 804 else
 805 $asm.puts "mov #{operands[2].armV7Operand}, #{operands[0].armV7Operand}"
 806 $asm.puts "muls #{operands[2].armV7Operand}, #{operands[2].armV7Operand}, #{operands[1].armV7Operand}"
 807 end
 808 when "subi", "subp", "subis"
 809 emitArmV7Compact("subs", "subs", operands)
 810 when "negi"
 811 $asm.puts "rsbs #{operands[0].armV7Operand}, #{operands[0].armV7Operand}, \#0"
 812 when "noti"
 813 $asm.puts "mvns #{operands[0].armV7Operand}, #{operands[0].armV7Operand}"
 814 when "loadi", "loadp"
 815 $asm.puts "ldr #{armV7FlippedOperands(operands)}"
 816 when "storei", "storep"
 817 $asm.puts "str #{armV7Operands(operands)}"
 818 when "loadb"
 819 $asm.puts "ldrb #{armV7FlippedOperands(operands)}"
 820 when "loadbs"
 821 $asm.puts "ldrsb.w #{armV7FlippedOperands(operands)}"
 822 when "storeb"
 823 $asm.puts "strb #{armV7Operands(operands)}"
 824 when "loadh"
 825 $asm.puts "ldrh #{armV7FlippedOperands(operands)}"
 826 when "loadhs"
 827 $asm.puts "ldrsh.w #{armV7FlippedOperands(operands)}"
 828 when "storeh"
 829 $asm.puts "strh #{armV7Operands(operands)}"
 830 when "loadd"
 831 $asm.puts "vldr.64 #{armV7FlippedOperands(operands)}"
 832 when "stored"
 833 $asm.puts "vstr.64 #{armV7Operands(operands)}"
 834 when "addd"
 835 emitArmV7("vadd.f64", operands)
 836 when "divd"
 837 emitArmV7("vdiv.f64", operands)
 838 when "subd"
 839 emitArmV7("vsub.f64", operands)
 840 when "muld"
 841 emitArmV7("vmul.f64", operands)
 842 when "sqrtd"
 843 $asm.puts "vsqrt.f64 #{armV7FlippedOperands(operands)}"
 844 when "ci2d"
 845 $asm.puts "vmov #{operands[1].armV7Single}, #{operands[0].armV7Operand}"
 846 $asm.puts "vcvt.f64.s32 #{operands[1].armV7Operand}, #{operands[1].armV7Single}"
 847 when "bdeq"
 848 emitArmV7DoubleBranch("beq", operands)
 849 when "bdneq"
 850 $asm.puts "vcmpe.f64 #{armV7Operands(operands[0..1])}"
 851 $asm.puts "vmrs apsr_nzcv, fpscr"
 852 isUnordered = LocalLabel.unique("bdneq")
 853 $asm.puts "bvs #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
 854 $asm.puts "bne #{operands[2].asmLabel}"
 855 isUnordered.lower("ARMv7")
 856 when "bdgt"
 857 emitArmV7DoubleBranch("bgt", operands)
 858 when "bdgteq"
 859 emitArmV7DoubleBranch("bge", operands)
 860 when "bdlt"
 861 emitArmV7DoubleBranch("bmi", operands)
 862 when "bdlteq"
 863 emitArmV7DoubleBranch("bls", operands)
 864 when "bdequn"
 865 $asm.puts "vcmpe.f64 #{armV7Operands(operands[0..1])}"
 866 $asm.puts "vmrs apsr_nzcv, fpscr"
 867 $asm.puts "bvs #{operands[2].asmLabel}"
 868 $asm.puts "beq #{operands[2].asmLabel}"
 869 when "bdnequn"
 870 emitArmV7DoubleBranch("bne", operands)
 871 when "bdgtun"
 872 emitArmV7DoubleBranch("bhi", operands)
 873 when "bdgtequn"
 874 emitArmV7DoubleBranch("bpl", operands)
 875 when "bdltun"
 876 emitArmV7DoubleBranch("blt", operands)
 877 when "bdltequn"
 878 emitArmV7DoubleBranch("ble", operands)
 879 when "btd2i"
 880 # FIXME: may be a good idea to just get rid of this instruction, since the interpreter
 881 # currently does not use it.
 882 raise "ARMv7 does not support this opcode yet, #{codeOrigin}"
 883 when "td2i"
 884 $asm.puts "vcvt.s32.f64 #{ARMv7_SCRATCH_FPR.armV7Single}, #{operands[0].armV7Operand}"
 885 $asm.puts "vmov #{operands[1].armV7Operand}, #{ARMv7_SCRATCH_FPR.armV7Single}"
 886 when "bcd2i"
 887 $asm.puts "vcvt.s32.f64 #{ARMv7_SCRATCH_FPR.armV7Single}, #{operands[0].armV7Operand}"
 888 $asm.puts "vmov #{operands[1].armV7Operand}, #{ARMv7_SCRATCH_FPR.armV7Single}"
 889 $asm.puts "vcvt.f64.s32 #{ARMv7_SCRATCH_FPR.armV7Operand}, #{ARMv7_SCRATCH_FPR.armV7Single}"
 890 emitArmV7DoubleBranch("bne", [ARMv7_SCRATCH_FPR, operands[0], operands[2]])
 891 $asm.puts "tst #{operands[1].armV7Operand}, #{operands[1].armV7Operand}"
 892 $asm.puts "beq #{operands[2].asmLabel}"
 893 when "movdz"
 894 # FIXME: either support this or remove it.
 895 raise "ARMv7 does not support this opcode yet, #{codeOrigin}"
 896 when "pop"
 897 $asm.puts "pop #{operands[0].armV7Operand}"
 898 when "push"
 899 $asm.puts "push #{operands[0].armV7Operand}"
 900 when "move", "sxi2p", "zxi2p"
 901 if operands[0].is_a? Immediate
 902 armV7MoveImmediate(operands[0].value, operands[1])
 903 else
 904 $asm.puts "mov #{armV7FlippedOperands(operands)}"
 905 end
 906 when "nop"
 907 $asm.puts "nop"
 908 when "bieq", "bpeq", "bbeq"
 909 if Immediate.new(nil, 0) == operands[0]
 910 $asm.puts "tst #{operands[1].armV7Operand}, #{operands[1].armV7Operand}"
 911 elsif Immediate.new(nil, 0) == operands[1]
 912 $asm.puts "tst #{operands[0].armV7Operand}, #{operands[0].armV7Operand}"
 913 else
 914 $asm.puts "cmp #{armV7Operands(operands[0..1])}"
 915 end
 916 $asm.puts "beq #{operands[2].asmLabel}"
 917 when "bineq", "bpneq", "bbneq"
 918 if Immediate.new(nil, 0) == operands[0]
 919 $asm.puts "tst #{operands[1].armV7Operand}, #{operands[1].armV7Operand}"
 920 elsif Immediate.new(nil, 0) == operands[1]
 921 $asm.puts "tst #{operands[0].armV7Operand}, #{operands[0].armV7Operand}"
 922 else
 923 $asm.puts "cmp #{armV7Operands(operands[0..1])}"
 924 end
 925 $asm.puts "bne #{operands[2].asmLabel}"
 926 when "bia", "bpa", "bba"
 927 $asm.puts "cmp #{armV7Operands(operands[0..1])}"
 928 $asm.puts "bhi #{operands[2].asmLabel}"
 929 when "biaeq", "bpaeq", "bbaeq"
 930 $asm.puts "cmp #{armV7Operands(operands[0..1])}"
 931 $asm.puts "bhs #{operands[2].asmLabel}"
 932 when "bib", "bpb", "bbb"
 933 $asm.puts "cmp #{armV7Operands(operands[0..1])}"
 934 $asm.puts "blo #{operands[2].asmLabel}"
 935 when "bibeq", "bpbeq", "bbbeq"
 936 $asm.puts "cmp #{armV7Operands(operands[0..1])}"
 937 $asm.puts "bls #{operands[2].asmLabel}"
 938 when "bigt", "bpgt", "bbgt"
 939 $asm.puts "cmp #{armV7Operands(operands[0..1])}"
 940 $asm.puts "bgt #{operands[2].asmLabel}"
 941 when "bigteq", "bpgteq", "bbgteq"
 942 $asm.puts "cmp #{armV7Operands(operands[0..1])}"
 943 $asm.puts "bge #{operands[2].asmLabel}"
 944 when "bilt", "bplt", "bblt"
 945 $asm.puts "cmp #{armV7Operands(operands[0..1])}"
 946 $asm.puts "blt #{operands[2].asmLabel}"
 947 when "bilteq", "bplteq", "bblteq"
 948 $asm.puts "cmp #{armV7Operands(operands[0..1])}"
 949 $asm.puts "ble #{operands[2].asmLabel}"
 950 when "btiz", "btpz", "btbz"
 951 emitArmV7Test(operands)
 952 $asm.puts "beq #{operands[-1].asmLabel}"
 953 when "btinz", "btpnz", "btbnz"
 954 emitArmV7Test(operands)
 955 $asm.puts "bne #{operands[-1].asmLabel}"
 956 when "btio", "btpo", "btbo"
 957 emitArmV7Test(operands)
 958 $asm.puts "bvs #{operands[-1].asmLabel}"
 959 when "btis", "btps", "btbs"
 960 emitArmV7Test(operands)
 961 $asm.puts "bmi #{operands[-1].asmLabel}"
 962 when "jmp"
 963 if operands[0].label?
 964 $asm.puts "b #{operands[0].asmLabel}"
 965 else
 966 $asm.puts "mov pc, #{operands[0].armV7Operand}"
 967 end
 968 when "call"
 969 if operands[0].label?
 970 $asm.puts "blx #{operands[0].asmLabel}"
 971 else
 972 $asm.puts "blx #{operands[0].armV7Operand}"
 973 end
 974 when "break"
 975 $asm.puts "bkpt"
 976 when "ret"
 977 $asm.puts "bx lr"
 978 when "cieq", "cpeq"
 979 emitArmV7Compare(operands, "eq")
 980 when "cineq", "cpneq"
 981 emitArmV7Compare(operands, "ne")
 982 when "cia", "cpa"
 983 emitArmV7Compare(operands, "hi")
 984 when "ciaeq", "cpaeq"
 985 emitArmV7Compare(operands, "hs")
 986 when "cib", "cpb"
 987 emitArmV7Compare(operands, "lo")
 988 when "cibeq", "cpbeq"
 989 emitArmV7Compare(operands, "ls")
 990 when "cigt", "cpgt"
 991 emitArmV7Compare(operands, "gt")
 992 when "cigteq", "cpgteq"
 993 emitArmV7Compare(operands, "ge")
 994 when "cilt", "cplt"
 995 emitArmV7Compare(operands, "lt")
 996 when "cilteq", "cplteq"
 997 emitArmV7Compare(operands, "le")
 998 when "tio", "tbo"
 999 emitArmV7TestSet(operands, "vs")
 1000 when "tis", "tbs"
 1001 emitArmV7TestSet(operands, "mi")
 1002 when "tiz", "tbz"
 1003 emitArmV7TestSet(operands, "eq")
 1004 when "tinz", "tbnz"
 1005 emitArmV7TestSet(operands, "ne")
 1006 when "peek"
 1007 $asm.puts "ldr #{operands[1].armV7Operand}, [sp, \##{operands[0].value * 4}]"
 1008 when "poke"
 1009 $asm.puts "str #{operands[1].armV7Operand}, [sp, \##{operands[0].value * 4}]"
 1010 when "fii2d"
 1011 $asm.puts "vmov #{operands[2].armV7Operand}, #{operands[0].armV7Operand}, #{operands[1].armV7Operand}"
 1012 when "fd2ii"
 1013 $asm.puts "vmov #{operands[1].armV7Operand}, #{operands[2].armV7Operand}, #{operands[0].armV7Operand}"
 1014 when "bo"
 1015 $asm.puts "bvs #{operands[0].asmLabel}"
 1016 when "bs"
 1017 $asm.puts "bmi #{operands[0].asmLabel}"
 1018 when "bz"
 1019 $asm.puts "beq #{operands[0].asmLabel}"
 1020 when "bnz"
 1021 $asm.puts "bne #{operands[0].asmLabel}"
 1022 when "leai", "leap"
 1023 operands[0].armV7EmitLea(operands[1])
 1024 when "smulli"
 1025 raise "Wrong number of arguments to smull in #{self.inspect} at #{codeOriginString}" unless operands.length == 4
 1026 $asm.puts "smull #{operands[2].armV7Operand}, #{operands[3].armV7Operand}, #{operands[0].armV7Operand}, #{operands[1].armV7Operand}"
 1027 else
 1028 raise "Unhandled opcode #{opcode} at #{codeOriginString}"
 1029 end
 1030 end
 1031end
 1032
0

Source/JavaScriptCore/offlineasm/asm.rb

 1#!/usr/bin/env ruby
 2
 3# Copyright (C) 2011 Apple Inc. All rights reserved.
 4#
 5# Redistribution and use in source and binary forms, with or without
 6# modification, are permitted provided that the following conditions
 7# are met:
 8# 1. Redistributions of source code must retain the above copyright
 9# notice, this list of conditions and the following disclaimer.
 10# 2. Redistributions in binary form must reproduce the above copyright
 11# notice, this list of conditions and the following disclaimer in the
 12# documentation and/or other materials provided with the distribution.
 13#
 14# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 15# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 16# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 17# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 18# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 19# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 20# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 21# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 22# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 23# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 24# THE POSSIBILITY OF SUCH DAMAGE.
 25
 26$: << File.dirname(__FILE__)
 27
 28require "backends"
 29require "digest/sha1"
 30require "offsets"
 31require "parser"
 32require "self_hash"
 33require "settings"
 34require "transform"
 35
 36class Assembler
 37 def initialize(outp)
 38 @outp = outp
 39 @state = :cpp
 40 @commentState = :none
 41 @comment = nil
 42 end
 43
 44 def enterAsm
 45 @outp.puts "asm ("
 46 @state = :asm
 47 end
 48
 49 def leaveAsm
 50 putsLastComment
 51 @outp.puts ");"
 52 @state = :cpp
 53 end
 54
 55 def inAsm
 56 enterAsm
 57 yield
 58 leaveAsm
 59 end
 60
 61 def lastComment
 62 if @comment
 63 result = "// #{@comment}"
 64 else
 65 result = ""
 66 end
 67 @commentState = :none
 68 @comment = nil
 69 result
 70 end
 71
 72 def putsLastComment
 73 comment = lastComment
 74 unless comment.empty?
 75 @outp.puts comment
 76 end
 77 end
 78
 79 def puts(*line)
 80 raise unless @state == :asm
 81 @outp.puts("\"\\t" + line.join('') + "\\n\" #{lastComment}")
 82 end
 83
 84 def print(line)
 85 raise unless @state == :asm
 86 @outp.print("\"" + line + "\"")
 87 end
 88
 89 def putsLabel(labelName)
 90 raise unless @state == :asm
 91 @outp.puts("OFFLINE_ASM_GLOBAL_LABEL(#{labelName}) #{lastComment}")
 92 end
 93
 94 def putsLocalLabel(labelName)
 95 raise unless @state == :asm
 96 @outp.puts("LOCAL_LABEL_STRING(#{labelName}) \":\\n\" #{lastComment}")
 97 end
 98
 99 def self.labelReference(labelName)
 100 "\" SYMBOL_STRING(#{labelName}) \""
 101 end
 102
 103 def self.localLabelReference(labelName)
 104 "\" LOCAL_LABEL_STRING(#{labelName}) \""
 105 end
 106
 107 def comment(text)
 108 case @commentState
 109 when :none
 110 @comment = text
 111 @commentState = :one
 112 when :one
 113 @outp.puts "// #{@comment}"
 114 @outp.puts "// #{text}"
 115 @comment = nil
 116 @commentState = :many
 117 when :many
 118 @outp.puts "// #{text}"
 119 else
 120 raise
 121 end
 122 end
 123end
 124
 125asmFile = ARGV.shift
 126offsetsFile = ARGV.shift
 127outputFlnm = ARGV.shift
 128
 129$stderr.puts "offlineasm: Parsing #{asmFile} and #{offsetsFile} and creating assembly file #{outputFlnm}."
 130
 131offsetsList, configIndex = offsetsAndConfigurationIndex(offsetsFile)
 132inputData = IO::read(asmFile)
 133
 134inputHash =
 135 "// offlineasm input hash: " + Digest::SHA1.hexdigest(inputData) +
 136 " " + Digest::SHA1.hexdigest((offsetsList + [configIndex]).join(' ')) +
 137 " " + selfHash
 138
 139if FileTest.exist? outputFlnm
 140 File.open(outputFlnm, "r") {
 141 | inp |
 142 firstLine = inp.gets
 143 if firstLine and firstLine.chomp == inputHash
 144 $stderr.puts "offlineasm: Nothing changed."
 145 exit 0
 146 end
 147 }
 148end
 149
 150File.open(outputFlnm, "w") {
 151 | outp |
 152 $output = outp
 153 $output.puts inputHash
 154
 155 $asm = Assembler.new($output)
 156
 157 ast = parse(lex(inputData))
 158
 159 forSettings(computeSettingsCombinations(ast)[configIndex], ast) {
 160 | concreteSettings, lowLevelAST, backend |
 161 assertConfiguration(concreteSettings)
 162 lowLevelAST = lowLevelAST.resolve(*buildOffsetsMap(lowLevelAST, offsetsList))
 163 emitCodeInConfiguration(concreteSettings, lowLevelAST, backend) {
 164 $asm.inAsm {
 165 lowLevelAST.lower(backend)
 166 }
 167 }
 168 }
 169}
 170
 171$stderr.puts "offlineasm: Assembly file #{outputFlnm} successfully generated."
 172
0

Source/JavaScriptCore/offlineasm/ast.rb

 1# Copyright (C) 2011 Apple Inc. All rights reserved.
 2#
 3# Redistribution and use in source and binary forms, with or without
 4# modification, are permitted provided that the following conditions
 5# are met:
 6# 1. Redistributions of source code must retain the above copyright
 7# notice, this list of conditions and the following disclaimer.
 8# 2. Redistributions in binary form must reproduce the above copyright
 9# notice, this list of conditions and the following disclaimer in the
 10# documentation and/or other materials provided with the distribution.
 11#
 12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 22# THE POSSIBILITY OF SUCH DAMAGE.
 23
 24#
 25# Base utility types for the AST.
 26#
 27
 28# Valid methods for Node:
 29#
 30# node.children -> Returns an array of immediate children.
 31#
 32# node.descendents -> Returns an array of all strict descendants (children
 33# and children of children, transitively).
 34#
 35# node.flatten -> Returns an array containing the strict descendants and
 36# the node itself.
 37#
 38# node.filter(type) -> Returns an array containing those elements in
 39# node.flatten that are of the given type (is_a? type returns true).
 40#
 41# node.mapChildren{|v| ...} -> Returns a new node with all children
 42# replaced according to the given block.
 43#
 44# Examples:
 45#
 46# node.filter(Setting).uniq -> Returns all of the settings that the AST's
 47# IfThenElse blocks depend on.
 48#
 49# node.filter(StructOffset).uniq -> Returns all of the structure offsets
 50# that the AST depends on.
 51
 52class Node
 53 attr_reader :codeOrigin
 54
 55 def initialize(codeOrigin)
 56 @codeOrigin = codeOrigin
 57 end
 58
 59 def codeOriginString
 60 "line number #{@codeOrigin}"
 61 end
 62
 63 def descendants
 64 children.collect{|v| v.flatten}.flatten
 65 end
 66
 67 def flatten
 68 [self] + descendants
 69 end
 70
 71 def filter(type)
 72 flatten.select{|v| v.is_a? type}
 73 end
 74end
 75
 76class NoChildren < Node
 77 def initialize(codeOrigin)
 78 super(codeOrigin)
 79 end
 80
 81 def children
 82 []
 83 end
 84
 85 def mapChildren
 86 self
 87 end
 88end
 89
 90class StructOffsetKey
 91 attr_reader :struct, :field
 92
 93 def initialize(struct, field)
 94 @struct = struct
 95 @field = field
 96 end
 97
 98 def hash
 99 @struct.hash + @field.hash * 3
 100 end
 101
 102 def eql?(other)
 103 @struct == other.struct and @field == other.field
 104 end
 105end
 106
 107#
 108# AST nodes.
 109#
 110
 111class StructOffset < NoChildren
 112 attr_reader :struct, :field
 113
 114 def initialize(codeOrigin, struct, field)
 115 super(codeOrigin)
 116 @struct = struct
 117 @field = field
 118 end
 119
 120 @@mapping = {}
 121
 122 def self.forField(codeOrigin, struct, field)
 123 key = StructOffsetKey.new(struct, field)
 124
 125 unless @@mapping[key]
 126 @@mapping[key] = StructOffset.new(codeOrigin, struct, field)
 127 end
 128 @@mapping[key]
 129 end
 130
 131 def dump
 132 "#{struct}::#{field}"
 133 end
 134
 135 def <=>(other)
 136 if @struct != other.struct
 137 return @struct <=> other.struct
 138 end
 139 @field <=> other.field
 140 end
 141
 142 def address?
 143 false
 144 end
 145
 146 def label?
 147 false
 148 end
 149
 150 def immediate?
 151 true
 152 end
 153
 154 def register?
 155 false
 156 end
 157end
 158
 159class Sizeof < NoChildren
 160 attr_reader :struct
 161
 162 def initialize(codeOrigin, struct)
 163 super(codeOrigin)
 164 @struct = struct
 165 end
 166
 167 @@mapping = {}
 168
 169 def self.forName(codeOrigin, struct)
 170 unless @@mapping[struct]
 171 @@mapping[struct] = Sizeof.new(codeOrigin, struct)
 172 end
 173 @@mapping[struct]
 174 end
 175
 176 def dump
 177 "sizeof #{@struct}"
 178 end
 179
 180 def <=>(other)
 181 @struct <=> other.struct
 182 end
 183
 184 def address?
 185 false
 186 end
 187
 188 def label?
 189 false
 190 end
 191
 192 def immediate?
 193 true
 194 end
 195
 196 def register?
 197 false
 198 end
 199end
 200
 201class Immediate < NoChildren
 202 attr_reader :value
 203
 204 def initialize(codeOrigin, value)
 205 super(codeOrigin)
 206 @value = value
 207 raise "Bad immediate value #{value.inspect} at #{codeOriginString}" unless value.is_a? Integer
 208 end
 209
 210 def dump
 211 "#{value}"
 212 end
 213
 214 def ==(other)
 215 other.is_a? Immediate and other.value == @value
 216 end
 217
 218 def address?
 219 false
 220 end
 221
 222 def label?
 223 false
 224 end
 225
 226 def immediate?
 227 true
 228 end
 229
 230 def register?
 231 false
 232 end
 233end
 234
 235class AddImmediates < Node
 236 attr_reader :left, :right
 237
 238 def initialize(codeOrigin, left, right)
 239 super(codeOrigin)
 240 @left = left
 241 @right = right
 242 end
 243
 244 def children
 245 [@left, @right]
 246 end
 247
 248 def mapChildren
 249 AddImmediates.new(codeOrigin, (yield @left), (yield @right))
 250 end
 251
 252 def dump
 253 "(#{left.dump} + #{right.dump})"
 254 end
 255
 256 def address?
 257 false
 258 end
 259
 260 def label?
 261 false
 262 end
 263
 264 def immediate?
 265 true
 266 end
 267
 268 def register?
 269 false
 270 end
 271end
 272
 273class SubImmediates < Node
 274 attr_reader :left, :right
 275
 276 def initialize(codeOrigin, left, right)
 277 super(codeOrigin)
 278 @left = left
 279 @right = right
 280 end
 281
 282 def children
 283 [@left, @right]
 284 end
 285
 286 def mapChildren
 287 SubImmediates.new(codeOrigin, (yield @left), (yield @right))
 288 end
 289
 290 def dump
 291 "(#{left.dump} - #{right.dump})"
 292 end
 293
 294 def address?
 295 false
 296 end
 297
 298 def label?
 299 false
 300 end
 301
 302 def immediate?
 303 true
 304 end
 305
 306 def register?
 307 false
 308 end
 309end
 310
 311class MulImmediates < Node
 312 attr_reader :left, :right
 313
 314 def initialize(codeOrigin, left, right)
 315 super(codeOrigin)
 316 @left = left
 317 @right = right
 318 end
 319
 320 def children
 321 [@left, @right]
 322 end
 323
 324 def mapChildren
 325 MulImmediates.new(codeOrigin, (yield @left), (yield @right))
 326 end
 327
 328 def dump
 329 "(#{left.dump} * #{right.dump})"
 330 end
 331
 332 def address?
 333 false
 334 end
 335
 336 def label?
 337 false
 338 end
 339
 340 def immediate?
 341 true
 342 end
 343
 344 def register?
 345 false
 346 end
 347end
 348
 349class NegImmediate < Node
 350 attr_reader :child
 351
 352 def initialize(codeOrigin, child)
 353 super(codeOrigin)
 354 @child = child
 355 end
 356
 357 def children
 358 [@child]
 359 end
 360
 361 def mapChildren
 362 NegImmediate.new(codeOrigin, (yield @child))
 363 end
 364
 365 def dump
 366 "(-#{@child.dump})"
 367 end
 368
 369 def address?
 370 false
 371 end
 372
 373 def label?
 374 false
 375 end
 376
 377 def immediate?
 378 true
 379 end
 380
 381 def register?
 382 false
 383 end
 384end
 385
 386class RegisterID < NoChildren
 387 attr_reader :name
 388
 389 def initialize(codeOrigin, name)
 390 super(codeOrigin)
 391 @name = name
 392 end
 393
 394 @@mapping = {}
 395
 396 def self.forName(codeOrigin, name)
 397 unless @@mapping[name]
 398 @@mapping[name] = RegisterID.new(codeOrigin, name)
 399 end
 400 @@mapping[name]
 401 end
 402
 403 def dump
 404 name
 405 end
 406
 407 def address?
 408 false
 409 end
 410
 411 def label?
 412 false
 413 end
 414
 415 def immediate?
 416 false
 417 end
 418
 419 def register?
 420 true
 421 end
 422end
 423
 424class FPRegisterID < NoChildren
 425 attr_reader :name
 426
 427 def initialize(codeOrigin, name)
 428 super(codeOrigin)
 429 @name = name
 430 end
 431
 432 @@mapping = {}
 433
 434 def self.forName(codeOrigin, name)
 435 unless @@mapping[name]
 436 @@mapping[name] = FPRegisterID.new(codeOrigin, name)
 437 end
 438 @@mapping[name]
 439 end
 440
 441 def dump
 442 name
 443 end
 444
 445 def address?
 446 false
 447 end
 448
 449 def label?
 450 false
 451 end
 452
 453 def immediate?
 454 false
 455 end
 456
 457 def register?
 458 true
 459 end
 460end
 461
 462class Variable < NoChildren
 463 attr_reader :name
 464
 465 def initialize(codeOrigin, name)
 466 super(codeOrigin)
 467 @name = name
 468 end
 469
 470 @@mapping = {}
 471
 472 def self.forName(codeOrigin, name)
 473 unless @@mapping[name]
 474 @@mapping[name] = Variable.new(codeOrigin, name)
 475 end
 476 @@mapping[name]
 477 end
 478
 479 def dump
 480 name
 481 end
 482end
 483
 484class Address < Node
 485 attr_reader :base, :offset
 486
 487 def initialize(codeOrigin, base, offset)
 488 super(codeOrigin)
 489 @base = base
 490 @offset = offset
 491 raise "Bad base for address #{base.inspect} at #{codeOriginString}" unless base.is_a? Variable or base.register?
 492 raise "Bad offset for address #{offset.inspect} at #{codeOriginString}" unless offset.is_a? Variable or offset.immediate?
 493 end
 494
 495 def children
 496 [@base, @offset]
 497 end
 498
 499 def mapChildren
 500 Address.new(codeOrigin, (yield @base), (yield @offset))
 501 end
 502
 503 def dump
 504 "#{offset.dump}[#{base.dump}]"
 505 end
 506
 507 def address?
 508 true
 509 end
 510
 511 def label?
 512 false
 513 end
 514
 515 def immediate?
 516 false
 517 end
 518
 519 def register?
 520 false
 521 end
 522end
 523
 524class BaseIndex < Node
 525 attr_reader :base, :index, :scale, :offset
 526
 527 def initialize(codeOrigin, base, index, scale, offset)
 528 super(codeOrigin)
 529 @base = base
 530 @index = index
 531 @scale = scale
 532 raise unless [1, 2, 4, 8].member? @scale
 533 @offset = offset
 534 end
 535
 536 def scaleShift
 537 case scale
 538 when 1
 539 0
 540 when 2
 541 1
 542 when 4
 543 2
 544 when 8
 545 3
 546 else
 547 raise "Bad scale at #{codeOriginString}"
 548 end
 549 end
 550
 551 def children
 552 [@base, @index, @offset]
 553 end
 554
 555 def mapChildren
 556 BaseIndex.new(codeOrigin, (yield @base), (yield @index), @scale, (yield @offset))
 557 end
 558
 559 def dump
 560 "#{offset.dump}[#{base.dump}, #{index.dump}, #{scale}]"
 561 end
 562
 563 def address?
 564 true
 565 end
 566
 567 def label?
 568 false
 569 end
 570
 571 def immediate?
 572 false
 573 end
 574
 575 def register?
 576 false
 577 end
 578end
 579
 580class AbsoluteAddress < NoChildren
 581 attr_reader :address
 582
 583 def initialize(codeOrigin, address)
 584 super(codeOrigin)
 585 @address = address
 586 end
 587
 588 def dump
 589 "#{address.dump}[]"
 590 end
 591
 592 def address?
 593 true
 594 end
 595
 596 def label?
 597 false
 598 end
 599
 600 def immediate?
 601 false
 602 end
 603
 604 def register?
 605 false
 606 end
 607end
 608
 609class Instruction < Node
 610 attr_reader :opcode, :operands
 611
 612 def initialize(codeOrigin, opcode, operands)
 613 super(codeOrigin)
 614 @opcode = opcode
 615 @operands = operands
 616 end
 617
 618 def children
 619 operands
 620 end
 621
 622 def mapChildren(&proc)
 623 Instruction.new(codeOrigin, @opcode, @operands.map(&proc))
 624 end
 625
 626 def dump
 627 "\t" + opcode.to_s + " " + operands.collect{|v| v.dump}.join(", ")
 628 end
 629end
 630
 631class Error < NoChildren
 632 def initialize(codeOrigin)
 633 super(codeOrigin)
 634 end
 635
 636 def dump
 637 "\terror"
 638 end
 639end
 640
 641class ConstDecl < Node
 642 attr_reader :variable, :value
 643
 644 def initialize(codeOrigin, variable, value)
 645 super(codeOrigin)
 646 @variable = variable
 647 @value = value
 648 end
 649
 650 def children
 651 [@variable, @value]
 652 end
 653
 654 def mapChildren
 655 ConstDecl.new(codeOrigin, (yield @variable), (yield @value))
 656 end
 657
 658 def dump
 659 "const #{@variable.dump} = #{@value.dump}"
 660 end
 661end
 662
 663$labelMapping = {}
 664
 665class Label < NoChildren
 666 attr_reader :name
 667
 668 def initialize(codeOrigin, name)
 669 super(codeOrigin)
 670 @name = name
 671 end
 672
 673 def self.forName(codeOrigin, name)
 674 if $labelMapping[name]
 675 raise "Label name collision: #{name}" unless $labelMapping[name].is_a? Label
 676 else
 677 $labelMapping[name] = Label.new(codeOrigin, name)
 678 end
 679 $labelMapping[name]
 680 end
 681
 682 def dump
 683 "#{name}:"
 684 end
 685end
 686
 687class LocalLabel < NoChildren
 688 attr_reader :name
 689
 690 def initialize(codeOrigin, name)
 691 super(codeOrigin)
 692 @name = name
 693 end
 694
 695 @@uniqueNameCounter = 0
 696
 697 def self.forName(codeOrigin, name)
 698 if $labelMapping[name]
 699 raise "Label name collision: #{name}" unless $labelMapping[name].is_a? LocalLabel
 700 else
 701 $labelMapping[name] = LocalLabel.new(codeOrigin, name)
 702 end
 703 $labelMapping[name]
 704 end
 705
 706 def self.unique(comment)
 707 newName = "_#{comment}"
 708 if $labelMapping[newName]
 709 while $labelMapping[newName = "_#{@@uniqueNameCounter}_#{comment}"]
 710 @@uniqueNameCounter += 1
 711 end
 712 end
 713 forName(nil, newName)
 714 end
 715
 716 def cleanName
 717 if name =~ /^\./
 718 "_" + name[1..-1]
 719 else
 720 name
 721 end
 722 end
 723
 724 def dump
 725 "#{name}:"
 726 end
 727end
 728
 729class LabelReference < Node
 730 attr_reader :label
 731
 732 def initialize(codeOrigin, label)
 733 super(codeOrigin)
 734 @label = label
 735 end
 736
 737 def children
 738 [@label]
 739 end
 740
 741 def mapChildren
 742 LabelReference.new(codeOrigin, (yield @label))
 743 end
 744
 745 def name
 746 label.name
 747 end
 748
 749 def dump
 750 label.name
 751 end
 752
 753 def address?
 754 false
 755 end
 756
 757 def label?
 758 true
 759 end
 760end
 761
 762class LocalLabelReference < NoChildren
 763 attr_reader :label
 764
 765 def initialize(codeOrigin, label)
 766 super(codeOrigin)
 767 @label = label
 768 end
 769
 770 def children
 771 [@label]
 772 end
 773
 774 def mapChildren
 775 LocalLabelReference.new(codeOrigin, (yield @label))
 776 end
 777
 778 def name
 779 label.name
 780 end
 781
 782 def dump
 783 label.name
 784 end
 785
 786 def address?
 787 false
 788 end
 789
 790 def label?
 791 true
 792 end
 793end
 794
 795class Sequence < Node
 796 attr_reader :list
 797
 798 def initialize(codeOrigin, list)
 799 super(codeOrigin)
 800 @list = list
 801 end
 802
 803 def children
 804 list
 805 end
 806
 807 def mapChildren(&proc)
 808 Sequence.new(codeOrigin, @list.map(&proc))
 809 end
 810
 811 def dump
 812 list.collect{|v| v.dump}.join("\n")
 813 end
 814end
 815
 816class True < NoChildren
 817 def initialize
 818 super(nil)
 819 end
 820
 821 @@instance = True.new
 822
 823 def self.instance
 824 @@instance
 825 end
 826
 827 def value
 828 true
 829 end
 830
 831 def dump
 832 "true"
 833 end
 834end
 835
 836class False < NoChildren
 837 def initialize
 838 super(nil)
 839 end
 840
 841 @@instance = False.new
 842
 843 def self.instance
 844 @@instance
 845 end
 846
 847 def value
 848 false
 849 end
 850
 851 def dump
 852 "false"
 853 end
 854end
 855
 856class TrueClass
 857 def asNode
 858 True.instance
 859 end
 860end
 861
 862class FalseClass
 863 def asNode
 864 False.instance
 865 end
 866end
 867
 868class Setting < NoChildren
 869 attr_reader :name
 870
 871 def initialize(codeOrigin, name)
 872 super(codeOrigin)
 873 @name = name
 874 end
 875
 876 @@mapping = {}
 877
 878 def self.forName(codeOrigin, name)
 879 unless @@mapping[name]
 880 @@mapping[name] = Setting.new(codeOrigin, name)
 881 end
 882 @@mapping[name]
 883 end
 884
 885 def dump
 886 name
 887 end
 888end
 889
 890class And < Node
 891 attr_reader :left, :right
 892
 893 def initialize(codeOrigin, left, right)
 894 super(codeOrigin)
 895 @left = left
 896 @right = right
 897 end
 898
 899 def children
 900 [@left, @right]
 901 end
 902
 903 def mapChildren
 904 And.new(codeOrigin, (yield @left), (yield @right))
 905 end
 906
 907 def dump
 908 "(#{left.dump} and #{right.dump})"
 909 end
 910end
 911
 912class Or < Node
 913 attr_reader :left, :right
 914
 915 def initialize(codeOrigin, left, right)
 916 super(codeOrigin)
 917 @left = left
 918 @right = right
 919 end
 920
 921 def children
 922 [@left, @right]
 923 end
 924
 925 def mapChildren
 926 Or.new(codeOrigin, (yield @left), (yield @right))
 927 end
 928
 929 def dump
 930 "(#{left.dump} or #{right.dump})"
 931 end
 932end
 933
 934class Not < Node
 935 attr_reader :child
 936
 937 def initialize(codeOrigin, child)
 938 super(codeOrigin)
 939 @child = child
 940 end
 941
 942 def children
 943 [@left, @right]
 944 end
 945
 946 def mapChildren
 947 Not.new(codeOrigin, (yield @child))
 948 end
 949
 950 def dump
 951 "(not #{child.dump})"
 952 end
 953end
 954
 955class Skip < NoChildren
 956 def initialize(codeOrigin)
 957 super(codeOrigin)
 958 end
 959
 960 def dump
 961 "\tskip"
 962 end
 963end
 964
 965class IfThenElse < Node
 966 attr_reader :predicate, :thenCase
 967 attr_accessor :elseCase
 968
 969 def initialize(codeOrigin, predicate, thenCase)
 970 super(codeOrigin)
 971 @predicate = predicate
 972 @thenCase = thenCase
 973 @elseCase = Skip.new(codeOrigin)
 974 end
 975
 976 def children
 977 if @elseCase
 978 [@predicate, @thenCase, @elseCase]
 979 else
 980 [@predicate, @thenCase]
 981 end
 982 end
 983
 984 def mapChildren
 985 IfThenElse.new(codeOrigin, (yield @predicate), (yield @thenCase), (yield @elseCase))
 986 end
 987
 988 def dump
 989 "if #{predicate.dump}\n" + thenCase.dump + "\nelse\n" + elseCase.dump + "\nend"
 990 end
 991end
 992
 993class Macro < Node
 994 attr_reader :name, :variables, :body
 995
 996 def initialize(codeOrigin, name, variables, body)
 997 super(codeOrigin)
 998 @name = name
 999 @variables = variables
 1000 @body = body
 1001 end
 1002
 1003 def children
 1004 @variables + [@body]
 1005 end
 1006
 1007 def mapChildren
 1008 Macro.new(codeOrigin, @name, @variables.map{|v| yield v}, (yield @body))
 1009 end
 1010
 1011 def dump
 1012 "macro #{name}(" + variables.collect{|v| v.dump}.join(", ") + ")\n" + body.dump + "\nend"
 1013 end
 1014end
 1015
 1016class MacroCall < Node
 1017 attr_reader :name, :operands
 1018
 1019 def initialize(codeOrigin, name, operands)
 1020 super(codeOrigin)
 1021 @name = name
 1022 @operands = operands
 1023 raise unless @operands
 1024 @operands.each{|v| raise unless v}
 1025 end
 1026
 1027 def children
 1028 @operands
 1029 end
 1030
 1031 def mapChildren(&proc)
 1032 MacroCall.new(codeOrigin, @name, @operands.map(&proc))
 1033 end
 1034
 1035 def dump
 1036 "\t#{name}(" + operands.collect{|v| v.dump}.join(", ") + ")"
 1037 end
 1038end
 1039
0

Source/JavaScriptCore/offlineasm/backends.rb

 1# Copyright (C) 2011 Apple Inc. All rights reserved.
 2#
 3# Redistribution and use in source and binary forms, with or without
 4# modification, are permitted provided that the following conditions
 5# are met:
 6# 1. Redistributions of source code must retain the above copyright
 7# notice, this list of conditions and the following disclaimer.
 8# 2. Redistributions in binary form must reproduce the above copyright
 9# notice, this list of conditions and the following disclaimer in the
 10# documentation and/or other materials provided with the distribution.
 11#
 12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 22# THE POSSIBILITY OF SUCH DAMAGE.
 23
 24require "armv7"
 25require "ast"
 26require "x86"
 27
 28BACKENDS =
 29 [
 30 "X86",
 31 "ARMv7"
 32 ]
 33
 34# Keep the set of working backends separate from the set of backends that might be
 35# supported. This is great because the BACKENDS list is almost like a reserved
 36# words list, in that it causes settings resolution to treat those words specially.
 37# Hence this lets us set aside the name of a backend we might want to support in
 38# the future while not actually supporting the backend yet.
 39WORKING_BACKENDS =
 40 [
 41 "X86",
 42 "ARMv7"
 43 ]
 44
 45BACKEND_PATTERN = Regexp.new('\\A(' + BACKENDS.join(')|(') + ')\\Z')
 46
 47class Node
 48 def lower(name)
 49 send("lower" + name)
 50 end
 51end
 52
 53# Overrides for lower() for those nodes that are backend-agnostic
 54
 55class Label
 56 def lower(name)
 57 $asm.putsLabel(self.name[1..-1])
 58 end
 59end
 60
 61class LocalLabel
 62 def lower(name)
 63 $asm.putsLocalLabel "_offlineasm_#{self.name[1..-1]}"
 64 end
 65end
 66
 67class LabelReference
 68 def asmLabel
 69 Assembler.labelReference(name[1..-1])
 70 end
 71end
 72
 73class LocalLabelReference
 74 def asmLabel
 75 Assembler.localLabelReference("_offlineasm_"+name[1..-1])
 76 end
 77end
 78
 79class Skip
 80 def lower(name)
 81 end
 82end
 83
 84class Sequence
 85 def lower(name)
 86 if respond_to? "lower#{name}"
 87 send("lower#{name}")
 88 else
 89 @list.each {
 90 | node |
 91 node.lower(name)
 92 }
 93 end
 94 end
 95end
 96
0

Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb

 1#!/usr/bin/env ruby
 2
 3# Copyright (C) 2011 Apple Inc. All rights reserved.
 4#
 5# Redistribution and use in source and binary forms, with or without
 6# modification, are permitted provided that the following conditions
 7# are met:
 8# 1. Redistributions of source code must retain the above copyright
 9# notice, this list of conditions and the following disclaimer.
 10# 2. Redistributions in binary form must reproduce the above copyright
 11# notice, this list of conditions and the following disclaimer in the
 12# documentation and/or other materials provided with the distribution.
 13#
 14# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 15# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 16# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 17# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 18# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 19# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 20# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 21# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 22# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 23# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 24# THE POSSIBILITY OF SUCH DAMAGE.
 25
 26$: << File.dirname(__FILE__)
 27
 28require "backends"
 29require "digest/sha1"
 30require "offsets"
 31require "parser"
 32require "self_hash"
 33require "settings"
 34require "transform"
 35
 36inputFlnm = ARGV.shift
 37outputFlnm = ARGV.shift
 38
 39$stderr.puts "offlineasm: Parsing #{inputFlnm} and creating offset extractor #{outputFlnm}."
 40
 41def emitMagicNumber
 42 OFFSET_MAGIC_NUMBERS.each {
 43 | number |
 44 $output.puts "#{number},"
 45 }
 46end
 47
 48inputData = IO::read(inputFlnm)
 49inputHash = "// offlineasm input hash: #{Digest::SHA1.hexdigest(inputData)} #{selfHash}"
 50
 51if FileTest.exist? outputFlnm
 52 File.open(outputFlnm, "r") {
 53 | inp |
 54 firstLine = inp.gets
 55 if firstLine and firstLine.chomp == inputHash
 56 $stderr.puts "offlineasm: Nothing changed."
 57 exit 0
 58 end
 59 }
 60end
 61
 62originalAST = parse(lex(inputData))
 63
 64#
 65# Optimize the AST to make configuration extraction faster. This reduces the AST to a form
 66# that only contains the things that matter for our purposes: offsets, sizes, and if
 67# statements.
 68#
 69
 70class Node
 71 def offsetsPruneTo(sequence)
 72 children.each {
 73 | child |
 74 child.offsetsPruneTo(sequence)
 75 }
 76 end
 77
 78 def offsetsPrune
 79 result = Sequence.new(codeOrigin, [])
 80 offsetsPruneTo(result)
 81 result
 82 end
 83end
 84
 85class IfThenElse
 86 def offsetsPruneTo(sequence)
 87 ifThenElse = IfThenElse.new(codeOrigin, predicate, thenCase.offsetsPrune)
 88 ifThenElse.elseCase = elseCase.offsetsPrune
 89 sequence.list << ifThenElse
 90 end
 91end
 92
 93class StructOffset
 94 def offsetsPruneTo(sequence)
 95 sequence.list << self
 96 end
 97end
 98
 99class Sizeof
 100 def offsetsPruneTo(sequence)
 101 sequence.list << self
 102 end
 103end
 104
 105prunedAST = originalAST.offsetsPrune
 106
 107File.open(outputFlnm, "w") {
 108 | outp |
 109 $output = outp
 110 outp.puts inputHash
 111 emitCodeInAllConfigurations(prunedAST) {
 112 | settings, ast, backend, index |
 113 offsetsList = ast.filter(StructOffset).uniq.sort
 114 sizesList = ast.filter(Sizeof).uniq.sort
 115
 116 length = (OFFSET_MAGIC_NUMBERS.size + 1) * (1 + offsetsList.size + sizesList.size)
 117
 118 outp.puts "static const unsigned extractorTable[#{length}] = {"
 119 emitMagicNumber
 120 outp.puts "#{index},"
 121 offsetsList.each {
 122 | offset |
 123 emitMagicNumber
 124 outp.puts "OFFLINE_ASM_OFFSETOF(#{offset.struct}, #{offset.field}),"
 125 }
 126 sizesList.each {
 127 | offset |
 128 emitMagicNumber
 129 outp.puts "sizeof(#{offset.struct}),"
 130 }
 131 outp.puts "};"
 132 }
 133}
 134
 135$stderr.puts "offlineasm: offset extractor #{outputFlnm} successfully generated."
 136
0

Source/JavaScriptCore/offlineasm/instructions.rb

 1# Copyright (C) 2011 Apple Inc. All rights reserved.
 2#
 3# Redistribution and use in source and binary forms, with or without
 4# modification, are permitted provided that the following conditions
 5# are met:
 6# 1. Redistributions of source code must retain the above copyright
 7# notice, this list of conditions and the following disclaimer.
 8# 2. Redistributions in binary form must reproduce the above copyright
 9# notice, this list of conditions and the following disclaimer in the
 10# documentation and/or other materials provided with the distribution.
 11#
 12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 22# THE POSSIBILITY OF SUCH DAMAGE.
 23
 24# Interesting invariant, which we take advantage of: branching instructions
 25# always begin with "b", and no non-branching instructions begin with "b".
 26# Terminal instructions are "jmp" and "ret".
 27
 28MACRO_INSTRUCTIONS =
 29 [
 30 "addi",
 31 "andi",
 32 "lshifti",
 33 "muli",
 34 "negi",
 35 "noti",
 36 "ori",
 37 "rshifti",
 38 "urshifti",
 39 "subi",
 40 "xori",
 41 "loadi",
 42 "loadb",
 43 "loadbs",
 44 "loadh",
 45 "loadhs",
 46 "storei",
 47 "storeb",
 48 "loadd",
 49 "moved",
 50 "stored",
 51 "addd",
 52 "divd",
 53 "subd",
 54 "muld",
 55 "sqrtd",
 56 "ci2d",
 57 "fii2d", # usage: fii2d <gpr with least significant bits>, <gpr with most significant bits>, <fpr>
 58 "fd2ii", # usage: fd2ii <fpr>, <gpr with least significant bits>, <gpr with most significant bits>
 59 "bdeq",
 60 "bdneq",
 61 "bdgt",
 62 "bdgteq",
 63 "bdlt",
 64 "bdlteq",
 65 "bdequn",
 66 "bdnequn",
 67 "bdgtun",
 68 "bdgtequn",
 69 "bdltun",
 70 "bdltequn",
 71 "btd2i",
 72 "td2i",
 73 "bcd2i",
 74 "movdz",
 75 "pop",
 76 "push",
 77 "move",
 78 "sxi2p",
 79 "zxi2p",
 80 "nop",
 81 "bieq",
 82 "bineq",
 83 "bia",
 84 "biaeq",
 85 "bib",
 86 "bibeq",
 87 "bigt",
 88 "bigteq",
 89 "bilt",
 90 "bilteq",
 91 "bbeq",
 92 "bbneq",
 93 "bba",
 94 "bbaeq",
 95 "bbb",
 96 "bbbeq",
 97 "bbgt",
 98 "bbgteq",
 99 "bblt",
 100 "bblteq",
 101 "btio",
 102 "btis",
 103 "btiz",
 104 "btinz",
 105 "btbo",
 106 "btbs",
 107 "btbz",
 108 "btbnz",
 109 "jmp",
 110 "baddio",
 111 "baddis",
 112 "baddiz",
 113 "baddinz",
 114 "bsubio",
 115 "bsubis",
 116 "bsubiz",
 117 "bsubinz",
 118 "bmulio",
 119 "bmulis",
 120 "bmuliz",
 121 "bmulinz",
 122 "borio",
 123 "boris",
 124 "boriz",
 125 "borinz",
 126 "break",
 127 "call",
 128 "ret",
 129 "cieq",
 130 "cineq",
 131 "cia",
 132 "ciaeq",
 133 "cib",
 134 "cibeq",
 135 "cigt",
 136 "cigteq",
 137 "cilt",
 138 "cilteq",
 139 "tio",
 140 "tis",
 141 "tiz",
 142 "tinz",
 143 "tbo",
 144 "tbs",
 145 "tbz",
 146 "tbnz",
 147 "peek",
 148 "poke",
 149 "bpeq",
 150 "bpneq",
 151 "bpa",
 152 "bpaeq",
 153 "bpb",
 154 "bpbeq",
 155 "bpgt",
 156 "bpgteq",
 157 "bplt",
 158 "bplteq",
 159 "addp",
 160 "andp",
 161 "orp",
 162 "subp",
 163 "xorp",
 164 "loadp",
 165 "cpeq",
 166 "cpneq",
 167 "cpa",
 168 "cpaeq",
 169 "cpb",
 170 "cpbeq",
 171 "cpgt",
 172 "cpgteq",
 173 "cplt",
 174 "cplteq",
 175 "storep",
 176 "btpo",
 177 "btps",
 178 "btpz",
 179 "btpnz",
 180 "baddpo",
 181 "baddps",
 182 "baddpz",
 183 "baddpnz",
 184 "bo",
 185 "bs",
 186 "bz",
 187 "bnz",
 188 "leai",
 189 "leap",
 190 ]
 191
 192X86_INSTRUCTIONS =
 193 [
 194 "cdqi",
 195 "idivi"
 196 ]
 197
 198ARMv7_INSTRUCTIONS =
 199 [
 200 "smulli",
 201 "addis",
 202 "subis",
 203 "oris"
 204 ]
 205
 206INSTRUCTIONS = MACRO_INSTRUCTIONS + X86_INSTRUCTIONS + ARMv7_INSTRUCTIONS
 207
 208INSTRUCTION_PATTERN = Regexp.new('\\A((' + INSTRUCTIONS.join(')|(') + '))\\Z')
 209
 210def isBranch(instruction)
 211 instruction =~ /^b/
 212end
 213
 214def hasFallThrough(instruction)
 215 instruction != "ret" and instruction != "jmp"
 216end
 217
0

Source/JavaScriptCore/offlineasm/offset_extractor_constants.rb

 1# Copyright (C) 2011 Apple Inc. All rights reserved.
 2#
 3# Redistribution and use in source and binary forms, with or without
 4# modification, are permitted provided that the following conditions
 5# are met:
 6# 1. Redistributions of source code must retain the above copyright
 7# notice, this list of conditions and the following disclaimer.
 8# 2. Redistributions in binary form must reproduce the above copyright
 9# notice, this list of conditions and the following disclaimer in the
 10# documentation and/or other materials provided with the distribution.
 11#
 12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 22# THE POSSIBILITY OF SUCH DAMAGE.
 23
 24MAGIC_NUMBERS = [ 0xec577ac7, 0x0ff5e755 ]
 25
 26
0

Source/JavaScriptCore/offlineasm/offsets.rb

 1# Copyright (C) 2011 Apple Inc. All rights reserved.
 2#
 3# Redistribution and use in source and binary forms, with or without
 4# modification, are permitted provided that the following conditions
 5# are met:
 6# 1. Redistributions of source code must retain the above copyright
 7# notice, this list of conditions and the following disclaimer.
 8# 2. Redistributions in binary form must reproduce the above copyright
 9# notice, this list of conditions and the following disclaimer in the
 10# documentation and/or other materials provided with the distribution.
 11#
 12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 22# THE POSSIBILITY OF SUCH DAMAGE.
 23
 24require "ast"
 25require "offset_extractor_constants"
 26
 27OFFSET_MAGIC_NUMBERS = [ 0xec577ac7, 0x0ff5e755 ]
 28
 29#
 30# offsetsList(ast)
 31# sizesList(ast)
 32#
 33# Returns a list of offsets and sizes used by the AST.
 34#
 35
 36def offsetsList(ast)
 37 ast.filter(StructOffset).uniq.sort
 38end
 39
 40def sizesList(ast)
 41 ast.filter(Sizeof).uniq.sort
 42end
 43
 44#
 45# offsetsAndConfigurationIndex(ast, file) ->
 46# [offsets, index]
 47#
 48# Parses the offsets from a file and returns a list of offsets and the
 49# index of the configuration that is valid in this build target.
 50#
 51
 52def offsetsAndConfigurationIndex(file)
 53 index = nil
 54 offsets = []
 55 endiannessMarkerBytes = nil
 56
 57 def readInt(endianness, inp)
 58 bytes = []
 59 4.times {
 60 bytes << inp.getbyte
 61 }
 62
 63 if endianness == :little
 64 # Little endian
 65 (bytes[0] << 0 |
 66 bytes[1] << 8 |
 67 bytes[2] << 16 |
 68 bytes[3] << 24)
 69 else
 70 # Big endian
 71 (bytes[0] << 24 |
 72 bytes[1] << 16 |
 73 bytes[2] << 8 |
 74 bytes[3] << 0)
 75 end
 76 end
 77
 78 [:little, :big].each {
 79 | endianness |
 80 magicBytes = []
 81 MAGIC_NUMBERS.each {
 82 | number |
 83 currentBytes = []
 84 4.times {
 85 currentBytes << (number & 0xff)
 86 number >>= 8
 87 }
 88 if endianness == :big
 89 currentBytes.reverse!
 90 end
 91 magicBytes += currentBytes
 92 }
 93
 94 File.open(file, "r") {
 95 | inp |
 96 whereInMarker = 0
 97 loop {
 98 byte = inp.getbyte
 99 break unless byte
 100 if byte == magicBytes[whereInMarker]
 101 whereInMarker += 1
 102 if whereInMarker == magicBytes.size
 103 # We have a match! If we have not yet read the endianness marker and index,
 104 # then read those now; otherwise read an offset.
 105
 106 if not index
 107 index = readInt(endianness, inp)
 108 else
 109 offsets << readInt(endianness, inp)
 110 end
 111
 112 whereInMarker = 0
 113 end
 114 else
 115 whereInMarker = 0
 116 end
 117 }
 118 }
 119
 120 break if index
 121 }
 122
 123 raise unless index
 124
 125 [offsets, index]
 126end
 127
 128#
 129# buildOffsetsMap(ast, offsetsList) -> [offsets, sizes]
 130#
 131# Builds a mapping between StructOffset nodes and their values.
 132#
 133
 134def buildOffsetsMap(ast, offsetsList)
 135 offsetsMap = {}
 136 sizesMap = {}
 137 astOffsetsList = offsetsList(ast)
 138 astSizesList = sizesList(ast)
 139 raise unless astOffsetsList.size + astSizesList.size == offsetsList.size
 140 offsetsList(ast).each_with_index {
 141 | structOffset, index |
 142 offsetsMap[structOffset] = offsetsList.shift
 143 }
 144 sizesList(ast).each_with_index {
 145 | sizeof, index |
 146 sizesMap[sizeof] = offsetsList.shift
 147 }
 148 [offsetsMap, sizesMap]
 149end
 150
0

Source/JavaScriptCore/offlineasm/opt.rb

 1# Copyright (C) 2011 Apple Inc. All rights reserved.
 2#
 3# Redistribution and use in source and binary forms, with or without
 4# modification, are permitted provided that the following conditions
 5# are met:
 6# 1. Redistributions of source code must retain the above copyright
 7# notice, this list of conditions and the following disclaimer.
 8# 2. Redistributions in binary form must reproduce the above copyright
 9# notice, this list of conditions and the following disclaimer in the
 10# documentation and/or other materials provided with the distribution.
 11#
 12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 22# THE POSSIBILITY OF SUCH DAMAGE.
 23
 24require "ast"
 25
 26#
 27# "Optimization" passes. These are used to lower the representation for
 28# backends that cannot handle some of our higher-level instructions.
 29#
 30
 31#
 32# A temporary - a variable that will be allocated to a register after we're
 33# done.
 34#
 35
 36class Node
 37 def replaceTemporariesWithRegisters(kind)
 38 mapChildren {
 39 | node |
 40 node.replaceTemporariesWithRegisters(kind)
 41 }
 42 end
 43end
 44
 45class Tmp < NoChildren
 46 attr_reader :firstMention, :lastMention
 47 attr_reader :kind
 48 attr_accessor :register
 49
 50 def initialize(codeOrigin, kind)
 51 super(codeOrigin)
 52 @kind = kind
 53 end
 54
 55 def dump
 56 "$tmp#{object_id}"
 57 end
 58
 59 def mention!(position)
 60 if not @firstMention or position < @firstMention
 61 @firstMention = position
 62 end
 63 if not @lastMention or position > @lastMention
 64 @lastMention = position
 65 end
 66 end
 67
 68 def replaceTemporariesWithRegisters(kind)
 69 if @kind == kind
 70 raise "Did not allocate register to temporary at #{codeOriginString}" unless @register
 71 @register
 72 else
 73 self
 74 end
 75 end
 76
 77 def address?
 78 false
 79 end
 80
 81 def label?
 82 false
 83 end
 84
 85 def immediate?
 86 false
 87 end
 88
 89 def register?
 90 true
 91 end
 92end
 93
 94# Assign registers to temporaries, by finding which temporaries interfere
 95# with each other. Note that this relies on temporary live ranges not crossing
 96# basic block boundaries.
 97
 98def assignRegistersToTemporaries(list, kind, registers)
 99 list.each_with_index {
 100 | node, index |
 101 node.filter(Tmp).uniq.each {
 102 | tmp |
 103 if tmp.kind == kind
 104 tmp.mention! index
 105 end
 106 }
 107 }
 108
 109 freeRegisters = registers.dup
 110 list.each_with_index {
 111 | node, index |
 112 tmpList = node.filter(Tmp).uniq
 113 tmpList.each {
 114 | tmp |
 115 if tmp.kind == kind and tmp.firstMention == index
 116 raise "Could not allocate register to temporary at #{node.codeOriginString}" if freeRegisters.empty?
 117 tmp.register = freeRegisters.pop
 118 end
 119 }
 120 tmpList.each {
 121 | tmp |
 122 if tmp.kind == kind and tmp.lastMention == index
 123 freeRegisters.push tmp.register
 124 raise "Register allocation inconsistency at #{node.codeOriginString}" if freeRegisters.size > registers.size
 125 end
 126 }
 127 }
 128
 129 list.map {
 130 | node |
 131 node.replaceTemporariesWithRegisters(kind)
 132 }
 133end
 134
0

Source/JavaScriptCore/offlineasm/parser.rb

 1# Copyright (C) 2011 Apple Inc. All rights reserved.
 2#
 3# Redistribution and use in source and binary forms, with or without
 4# modification, are permitted provided that the following conditions
 5# are met:
 6# 1. Redistributions of source code must retain the above copyright
 7# notice, this list of conditions and the following disclaimer.
 8# 2. Redistributions in binary form must reproduce the above copyright
 9# notice, this list of conditions and the following disclaimer in the
 10# documentation and/or other materials provided with the distribution.
 11#
 12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 22# THE POSSIBILITY OF SUCH DAMAGE.
 23
 24require "ast"
 25require "instructions"
 26require "registers"
 27
 28class Token
 29 attr_reader :codeOrigin, :string
 30
 31 def initialize(codeOrigin, string)
 32 @codeOrigin = codeOrigin
 33 @string = string
 34 end
 35
 36 def ==(other)
 37 if other.is_a? Token
 38 @string == other.string
 39 else
 40 @string == other
 41 end
 42 end
 43
 44 def =~(other)
 45 @string =~ other
 46 end
 47
 48 def to_s
 49 "#{@string.inspect} at line #{codeOrigin}"
 50 end
 51
 52 def parseError(*comment)
 53 if comment.empty?
 54 raise "Parse error: #{to_s}"
 55 else
 56 raise "Parse error: #{to_s}: #{comment[0]}"
 57 end
 58 end
 59end
 60
 61#
 62# The lexer. Takes a string and returns an array of tokens.
 63#
 64
 65def lex(str)
 66 result = []
 67 lineNumber = 1
 68 while not str.empty?
 69 case str
 70 when /\A\#([^\n]*)/
 71 # comment, ignore
 72 when /\A\n/
 73 result << Token.new(lineNumber, $&)
 74 lineNumber += 1
 75 when /\A[a-zA-Z]([a-zA-Z0-9_]*)/
 76 result << Token.new(lineNumber, $&)
 77 when /\A\.([a-zA-Z0-9_]*)/
 78 result << Token.new(lineNumber, $&)
 79 when /\A_([a-zA-Z0-9_]*)/
 80 result << Token.new(lineNumber, $&)
 81 when /\A([ \t]+)/
 82 # whitespace, ignore
 83 when /\A0x([0-9a-fA-F]+)/
 84 result << Token.new(lineNumber, $&.hex.to_s)
 85 when /\A0([0-7]+)/
 86 result << Token.new(lineNumber, $&.oct.to_s)
 87 when /\A([0-9]+)/
 88 result << Token.new(lineNumber, $&)
 89 when /\A::/
 90 result << Token.new(lineNumber, $&)
 91 when /\A[:,\(\)\[\]=\+\-*]/
 92 result << Token.new(lineNumber, $&)
 93 else
 94 raise "Lexer error at line number #{lineNumber}, unexpected sequence #{str[0..20].inspect}"
 95 end
 96 str = $~.post_match
 97 end
 98 result
 99end
 100
 101#
 102# Token identification.
 103#
 104
 105def isRegister(token)
 106 token =~ REGISTER_PATTERN
 107end
 108
 109def isInstruction(token)
 110 token =~ INSTRUCTION_PATTERN
 111end
 112
 113def isKeyword(token)
 114 token =~ /\A((true)|(false)|(if)|(then)|(else)|(elsif)|(end)|(and)|(or)|(not)|(macro)|(const)|(sizeof)|(error))\Z/ or
 115 token =~ REGISTER_PATTERN or
 116 token =~ INSTRUCTION_PATTERN
 117end
 118
 119def isIdentifier(token)
 120 token =~ /\A[a-zA-Z]([a-zA-Z0-9_]*)\Z/ and not isKeyword(token)
 121end
 122
 123def isLabel(token)
 124 token =~ /\A_([a-zA-Z0-9_]*)\Z/
 125end
 126
 127def isLocalLabel(token)
 128 token =~ /\A\.([a-zA-Z0-9_]*)\Z/
 129end
 130
 131def isVariable(token)
 132 isIdentifier(token) or isRegister(token)
 133end
 134
 135def isInteger(token)
 136 token =~ /\A[0-9]/
 137end
 138
 139#
 140# The parser. Takes an array of tokens and returns an AST. Methods
 141# other than parse(tokens) are not for public consumption.
 142#
 143
 144class Parser
 145 def initialize(tokens)
 146 @tokens = tokens
 147 @idx = 0
 148 end
 149
 150 def parseError(*comment)
 151 if @tokens[@idx]
 152 @tokens[@idx].parseError(*comment)
 153 else
 154 if comment.empty?
 155 raise "Parse error at end of file"
 156 else
 157 raise "Parse error at end of file: #{comment[0]}"
 158 end
 159 end
 160 end
 161
 162 def consume(regexp)
 163 if regexp
 164 parseError unless @tokens[@idx] =~ regexp
 165 else
 166 parseError unless @idx == @tokens.length
 167 end
 168 @idx += 1
 169 end
 170
 171 def skipNewLine
 172 while @tokens[@idx] == "\n"
 173 @idx += 1
 174 end
 175 end
 176
 177 def parsePredicateAtom
 178 if @tokens[@idx] == "not"
 179 @idx += 1
 180 parsePredicateAtom
 181 elsif @tokens[@idx] == "("
 182 @idx += 1
 183 skipNewLine
 184 result = parsePredicate
 185 parseError unless @tokens[@idx] == ")"
 186 @idx += 1
 187 result
 188 elsif @tokens[@idx] == "true"
 189 result = True.instance
 190 @idx += 1
 191 result
 192 elsif @tokens[@idx] == "false"
 193 result = False.instance
 194 @idx += 1
 195 result
 196 elsif isIdentifier @tokens[@idx]
 197 result = Setting.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
 198 @idx += 1
 199 result
 200 else
 201 parseError
 202 end
 203 end
 204
 205 def parsePredicateAnd
 206 result = parsePredicateAtom
 207 while @tokens[@idx] == "and"
 208 codeOrigin = @tokens[@idx].codeOrigin
 209 @idx += 1
 210 skipNewLine
 211 right = parsePredicateAtom
 212 result = And.new(codeOrigin, result, right)
 213 end
 214 result
 215 end
 216
 217 def parsePredicate
 218 # some examples of precedence:
 219 # not a and b -> (not a) and b
 220 # a and b or c -> (a and b) or c
 221 # a or b and c -> a or (b and c)
 222
 223 result = parsePredicateAnd
 224 while @tokens[@idx] == "or"
 225 codeOrigin = @tokens[@idx].codeOrigin
 226 @idx += 1
 227 skipNewLine
 228 right = parsePredicateAnd
 229 result = Or.new(codeOrigin, result, right)
 230 end
 231 result
 232 end
 233
 234 def parseVariable
 235 if isRegister(@tokens[@idx])
 236 if @tokens[@idx] =~ FPR_PATTERN
 237 result = FPRegisterID.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
 238 else
 239 result = RegisterID.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
 240 end
 241 elsif isIdentifier(@tokens[@idx])
 242 result = Variable.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
 243 else
 244 parseError
 245 end
 246 @idx += 1
 247 result
 248 end
 249
 250 def parseAddress(offset)
 251 parseError unless @tokens[@idx] == "["
 252 codeOrigin = @tokens[@idx].codeOrigin
 253
 254 # Three possibilities:
 255 # [] -> AbsoluteAddress
 256 # [a] -> Address
 257 # [a,b] -> BaseIndex with scale = 1
 258 # [a,b,c] -> BaseIndex
 259
 260 @idx += 1
 261 if @tokens[@idx] == "]"
 262 @idx += 1
 263 return AbsoluteAddress.new(codeOrigin, offset)
 264 end
 265 a = parseVariable
 266 if @tokens[@idx] == "]"
 267 result = Address.new(codeOrigin, a, offset)
 268 else
 269 parseError unless @tokens[@idx] == ","
 270 @idx += 1
 271 b = parseVariable
 272 if @tokens[@idx] == "]"
 273 result = BaseIndex.new(codeOrigin, a, b, 1, offset)
 274 else
 275 parseError unless @tokens[@idx] == ","
 276 @idx += 1
 277 parseError unless ["1", "2", "4", "8"].member? @tokens[@idx].string
 278 c = @tokens[@idx].string.to_i
 279 @idx += 1
 280 parseError unless @tokens[@idx] == "]"
 281 result = BaseIndex.new(codeOrigin, a, b, c, offset)
 282 end
 283 end
 284 @idx += 1
 285 result
 286 end
 287
 288 def parseColonColon
 289 skipNewLine
 290 codeOrigin = @tokens[@idx].codeOrigin
 291 parseError unless isIdentifier @tokens[@idx]
 292 names = [@tokens[@idx].string]
 293 @idx += 1
 294 while @tokens[@idx] == "::"
 295 @idx += 1
 296 parseError unless isIdentifier @tokens[@idx]
 297 names << @tokens[@idx].string
 298 @idx += 1
 299 end
 300 raise if names.empty?
 301 [codeOrigin, names]
 302 end
 303
 304 def parseExpressionAtom
 305 skipNewLine
 306 if @tokens[@idx] == "-"
 307 @idx += 1
 308 NegImmediate.new(@tokens[@idx - 1].codeOrigin, parseExpressionAtom)
 309 elsif @tokens[@idx] == "("
 310 @idx += 1
 311 result = parseExpression
 312 parseError unless @tokens[@idx] == ")"
 313 @idx += 1
 314 result
 315 elsif isInteger @tokens[@idx]
 316 result = Immediate.new(@tokens[@idx].codeOrigin, @tokens[@idx].string.to_i)
 317 @idx += 1
 318 result
 319 elsif isIdentifier @tokens[@idx]
 320 codeOrigin, names = parseColonColon
 321 if names.size > 1
 322 StructOffset.forField(codeOrigin, names[0..-2].join('::'), names[-1])
 323 else
 324 Variable.forName(codeOrigin, names[0])
 325 end
 326 elsif isRegister @tokens[@idx]
 327 parseVariable
 328 elsif @tokens[@idx] == "sizeof"
 329 @idx += 1
 330 codeOrigin, names = parseColonColon
 331 Sizeof.forName(codeOrigin, names.join('::'))
 332 else
 333 parseError
 334 end
 335 end
 336
 337 def parseExpressionMul
 338 skipNewLine
 339 result = parseExpressionAtom
 340 while @tokens[@idx] == "*"
 341 if @tokens[@idx] == "*"
 342 @idx += 1
 343 result = MulImmediates.new(@tokens[@idx - 1].codeOrigin, result, parseExpressionAtom)
 344 else
 345 raise
 346 end
 347 end
 348 result
 349 end
 350
 351 def couldBeExpression
 352 @tokens[@idx] == "-" or @tokens[@idx] == "sizeof" or isInteger(@tokens[@idx]) or isVariable(@tokens[@idx]) or @tokens[@idx] == "("
 353 end
 354
 355 def parseExpression
 356 skipNewLine
 357 result = parseExpressionMul
 358 while @tokens[@idx] == "+" or @tokens[@idx] == "-"
 359 if @tokens[@idx] == "+"
 360 @idx += 1
 361 result = AddImmediates.new(@tokens[@idx - 1].codeOrigin, result, parseExpressionMul)
 362 elsif @tokens[@idx] == "-"
 363 @idx += 1
 364 result = SubImmediates.new(@tokens[@idx - 1].codeOrigin, result, parseExpressionMul)
 365 else
 366 raise
 367 end
 368 end
 369 result
 370 end
 371
 372 def parseOperand(comment)
 373 skipNewLine
 374 if couldBeExpression
 375 expr = parseExpression
 376 if @tokens[@idx] == "["
 377 parseAddress(expr)
 378 else
 379 expr
 380 end
 381 elsif @tokens[@idx] == "["
 382 parseAddress(Immediate.new(@tokens[@idx].codeOrigin, 0))
 383 elsif isLabel @tokens[@idx]
 384 result = LabelReference.new(@tokens[@idx].codeOrigin, Label.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string))
 385 @idx += 1
 386 result
 387 elsif isLocalLabel @tokens[@idx]
 388 result = LocalLabelReference.new(@tokens[@idx].codeOrigin, LocalLabel.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string))
 389 @idx += 1
 390 result
 391 else
 392 parseError(comment)
 393 end
 394 end
 395
 396 def parseMacroVariables
 397 skipNewLine
 398 consume(/\A\(\Z/)
 399 variables = []
 400 loop {
 401 skipNewLine
 402 if @tokens[@idx] == ")"
 403 @idx += 1
 404 break
 405 elsif isIdentifier(@tokens[@idx])
 406 variables << Variable.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
 407 @idx += 1
 408 skipNewLine
 409 if @tokens[@idx] == ")"
 410 @idx += 1
 411 break
 412 elsif @tokens[@idx] == ","
 413 @idx += 1
 414 else
 415 parseError
 416 end
 417 else
 418 parseError
 419 end
 420 }
 421 variables
 422 end
 423
 424 def parseSequence(final, comment)
 425 firstCodeOrigin = @tokens[@idx].codeOrigin
 426 list = []
 427 loop {
 428 if (@idx == @tokens.length and not final) or (final and @tokens[@idx] =~ final)
 429 break
 430 elsif @tokens[@idx] == "\n"
 431 # ignore
 432 @idx += 1
 433 elsif @tokens[@idx] == "const"
 434 @idx += 1
 435 parseError unless isVariable @tokens[@idx]
 436 variable = Variable.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
 437 @idx += 1
 438 parseError unless @tokens[@idx] == "="
 439 @idx += 1
 440 value = parseOperand("while inside of const #{variable.name}")
 441 list << ConstDecl.new(@tokens[@idx].codeOrigin, variable, value)
 442 elsif @tokens[@idx] == "error"
 443 list << Error.new(@tokens[@idx].codeOrigin)
 444 @idx += 1
 445 elsif @tokens[@idx] == "if"
 446 codeOrigin = @tokens[@idx].codeOrigin
 447 @idx += 1
 448 skipNewLine
 449 predicate = parsePredicate
 450 consume(/\A((then)|(\n))\Z/)
 451 skipNewLine
 452 ifThenElse = IfThenElse.new(codeOrigin, predicate, parseSequence(/\A((else)|(end)|(elsif))\Z/, "while inside of \"if #{predicate.dump}\""))
 453 list << ifThenElse
 454 while @tokens[@idx] == "elsif"
 455 codeOrigin = @tokens[@idx].codeOrigin
 456 @idx += 1
 457 skipNewLine
 458 predicate = parsePredicate
 459 consume(/\A((then)|(\n))\Z/)
 460 skipNewLine
 461 elseCase = IfThenElse.new(codeOrigin, predicate, parseSequence(/\A((else)|(end)|(elsif))\Z/, "while inside of \"if #{predicate.dump}\""))
 462 ifThenElse.elseCase = elseCase
 463 ifThenElse = elseCase
 464 end
 465 if @tokens[@idx] == "else"
 466 @idx += 1
 467 ifThenElse.elseCase = parseSequence(/\Aend\Z/, "while inside of else case for \"if #{predicate.dump}\"")
 468 @idx += 1
 469 else
 470 parseError unless @tokens[@idx] == "end"
 471 @idx += 1
 472 end
 473 elsif @tokens[@idx] == "macro"
 474 codeOrigin = @tokens[@idx].codeOrigin
 475 @idx += 1
 476 skipNewLine
 477 parseError unless isIdentifier(@tokens[@idx])
 478 name = @tokens[@idx].string
 479 @idx += 1
 480 variables = parseMacroVariables
 481 body = parseSequence(/\Aend\Z/, "while inside of macro #{name}")
 482 @idx += 1
 483 list << Macro.new(codeOrigin, name, variables, body)
 484 elsif isInstruction @tokens[@idx]
 485 codeOrigin = @tokens[@idx].codeOrigin
 486 name = @tokens[@idx].string
 487 @idx += 1
 488 if (not final and @idx == @tokens.size) or (final and @tokens[@idx] =~ final)
 489 # Zero operand instruction, and it's the last one.
 490 list << Instruction.new(codeOrigin, name, [])
 491 break
 492 elsif @tokens[@idx] == "\n"
 493 # Zero operand instruction.
 494 list << Instruction.new(codeOrigin, name, [])
 495 @idx += 1
 496 else
 497 # It's definitely an instruction, and it has at least one operand.
 498 operands = []
 499 endOfSequence = false
 500 loop {
 501 operands << parseOperand("while inside of instruction #{name}")
 502 if (not final and @idx == @tokens.size) or (final and @tokens[@idx] =~ final)
 503 # The end of the instruction and of the sequence.
 504 endOfSequence = true
 505 break
 506 elsif @tokens[@idx] == ","
 507 # Has another operand.
 508 @idx += 1
 509 elsif @tokens[@idx] == "\n"
 510 # The end of the instruction.
 511 @idx += 1
 512 break
 513 else
 514 parseError("Expected a comma, newline, or #{final} after #{operands.last.dump}")
 515 end
 516 }
 517 list << Instruction.new(codeOrigin, name, operands)
 518 if endOfSequence
 519 break
 520 end
 521 end
 522 elsif isIdentifier @tokens[@idx]
 523 codeOrigin = @tokens[@idx].codeOrigin
 524 name = @tokens[@idx].string
 525 @idx += 1
 526 if @tokens[@idx] == "("
 527 # Macro invocation.
 528 @idx += 1
 529 operands = []
 530 skipNewLine
 531 if @tokens[@idx] == ")"
 532 @idx += 1
 533 else
 534 loop {
 535 skipNewLine
 536 if @tokens[@idx] == "macro"
 537 # It's a macro lambda!
 538 codeOriginInner = @tokens[@idx].codeOrigin
 539 @idx += 1
 540 variables = parseMacroVariables
 541 body = parseSequence(/\Aend\Z/, "while inside of anonymous macro passed as argument to #{name}")
 542 @idx += 1
 543 operands << Macro.new(codeOriginInner, nil, variables, body)
 544 else
 545 operands << parseOperand("while inside of macro call to #{name}")
 546 end
 547 skipNewLine
 548 if @tokens[@idx] == ")"
 549 @idx += 1
 550 break
 551 elsif @tokens[@idx] == ","
 552 @idx += 1
 553 else
 554 parseError "Unexpected #{@tokens[@idx].string.inspect} while parsing invocation of macro #{name}"
 555 end
 556 }
 557 end
 558 list << MacroCall.new(codeOrigin, name, operands)
 559 else
 560 parseError "Expected \"(\" after #{name}"
 561 end
 562 elsif isLabel @tokens[@idx] or isLocalLabel @tokens[@idx]
 563 codeOrigin = @tokens[@idx].codeOrigin
 564 name = @tokens[@idx].string
 565 @idx += 1
 566 parseError unless @tokens[@idx] == ":"
 567 # It's a label.
 568 if isLabel name
 569 list << Label.forName(codeOrigin, name)
 570 else
 571 list << LocalLabel.forName(codeOrigin, name)
 572 end
 573 @idx += 1
 574 else
 575 parseError "Expecting terminal #{final} #{comment}"
 576 end
 577 }
 578 Sequence.new(firstCodeOrigin, list)
 579 end
 580end
 581
 582def parse(tokens)
 583 parser = Parser.new(tokens)
 584 parser.parseSequence(nil, "")
 585end
 586
0

Source/JavaScriptCore/offlineasm/registers.rb

 1# Copyright (C) 2011 Apple Inc. All rights reserved.
 2#
 3# Redistribution and use in source and binary forms, with or without
 4# modification, are permitted provided that the following conditions
 5# are met:
 6# 1. Redistributions of source code must retain the above copyright
 7# notice, this list of conditions and the following disclaimer.
 8# 2. Redistributions in binary form must reproduce the above copyright
 9# notice, this list of conditions and the following disclaimer in the
 10# documentation and/or other materials provided with the distribution.
 11#
 12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 22# THE POSSIBILITY OF SUCH DAMAGE.
 23
 24GPRS =
 25 [
 26 "t0",
 27 "t1",
 28 "t2",
 29 "t3",
 30 "t4",
 31 "cfr",
 32 "a0",
 33 "a1",
 34 "r0",
 35 "r1",
 36 "sp",
 37 "lr"
 38 ]
 39
 40FPRS =
 41 [
 42 "ft0",
 43 "ft1",
 44 "ft2",
 45 "ft3",
 46 "ft4",
 47 "ft5",
 48 "fa0",
 49 "fa1",
 50 "fa2",
 51 "fa3",
 52 "fr"
 53 ]
 54
 55REGISTERS = GPRS + FPRS
 56
 57GPR_PATTERN = Regexp.new('\\A((' + GPRS.join(')|(') + '))\\Z')
 58FPR_PATTERN = Regexp.new('\\A((' + FPRS.join(')|(') + '))\\Z')
 59
 60REGISTER_PATTERN = Regexp.new('\\A((' + REGISTERS.join(')|(') + '))\\Z')
0

Source/JavaScriptCore/offlineasm/self_hash.rb

 1# Copyright (C) 2011 Apple Inc. All rights reserved.
 2#
 3# Redistribution and use in source and binary forms, with or without
 4# modification, are permitted provided that the following conditions
 5# are met:
 6# 1. Redistributions of source code must retain the above copyright
 7# notice, this list of conditions and the following disclaimer.
 8# 2. Redistributions in binary form must reproduce the above copyright
 9# notice, this list of conditions and the following disclaimer in the
 10# documentation and/or other materials provided with the distribution.
 11#
 12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 22# THE POSSIBILITY OF SUCH DAMAGE.
 23
 24require "digest/sha1"
 25require "pathname"
 26
 27#
 28# selfHash -> SHA1 hexdigest
 29#
 30# Returns a hash of the offlineasm source code. This allows dependency
 31# tracking for not just changes in input, but also changes in the assembler
 32# itself.
 33#
 34
 35def selfHash
 36 contents = ""
 37 myPath = Pathname.new(__FILE__).dirname
 38 Dir.foreach(myPath) {
 39 | entry |
 40 if entry =~ /\.rb$/
 41 contents += IO::read(myPath + entry)
 42 end
 43 }
 44 return Digest::SHA1.hexdigest(contents)
 45end
 46
0

Source/JavaScriptCore/offlineasm/settings.rb

 1# Copyright (C) 2011 Apple Inc. All rights reserved.
 2#
 3# Redistribution and use in source and binary forms, with or without
 4# modification, are permitted provided that the following conditions
 5# are met:
 6# 1. Redistributions of source code must retain the above copyright
 7# notice, this list of conditions and the following disclaimer.
 8# 2. Redistributions in binary form must reproduce the above copyright
 9# notice, this list of conditions and the following disclaimer in the
 10# documentation and/or other materials provided with the distribution.
 11#
 12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 22# THE POSSIBILITY OF SUCH DAMAGE.
 23
 24require "ast"
 25require "backends"
 26require "parser"
 27require "transform"
 28
 29#
 30# computeSettingsCombinations(ast) -> settingsCombiations
 31#
 32# Computes an array of settings maps, where a settings map constitutes
 33# a configuration for the assembly code being generated. The map
 34# contains key value pairs where keys are settings names (strings) and
 35# the values are booleans (true for enabled, false for disabled).
 36#
 37
 38def computeSettingsCombinations(ast)
 39 settingsCombinations = []
 40
 41 def settingsCombinator(settingsCombinations, mapSoFar, remaining)
 42 if remaining.empty?
 43 settingsCombinations << mapSoFar
 44 return
 45 end
 46
 47 newMap = mapSoFar.dup
 48 newMap[remaining[0]] = true
 49 settingsCombinator(settingsCombinations, newMap, remaining[1..-1])
 50
 51 newMap = mapSoFar.dup
 52 newMap[remaining[0]] = false
 53 settingsCombinator(settingsCombinations, newMap, remaining[1..-1])
 54 end
 55
 56 settingsCombinator(settingsCombinations, {}, (ast.filter(Setting).uniq.collect{|v| v.name} + ["X86", "ARMv7"]).uniq)
 57
 58 settingsCombinations
 59end
 60
 61#
 62# forSettings(concreteSettings, ast) {
 63# | concreteSettings, lowLevelAST, backend | ... }
 64#
 65# Determines if the settings combination is valid, and if so, calls
 66# the block with the information you need to generate code.
 67#
 68
 69def forSettings(concreteSettings, ast)
 70 # Check which architectures this combinator claims to support.
 71 numClaimedBackends = 0
 72 selectedBackend = nil
 73 BACKENDS.each {
 74 | backend |
 75 isSupported = concreteSettings[backend]
 76 raise unless isSupported != nil
 77 numClaimedBackends += if isSupported then 1 else 0 end
 78 if isSupported
 79 selectedBackend = backend
 80 end
 81 }
 82
 83 return if numClaimedBackends > 1
 84
 85 # Resolve the AST down to a low-level form (no macros or conditionals).
 86 lowLevelAST = ast.resolveSettings(concreteSettings)
 87
 88 yield concreteSettings, lowLevelAST, selectedBackend
 89end
 90
 91#
 92# forEachValidSettingsCombination(ast) {
 93# | concreteSettings, ast, backend, index | ... }
 94#
 95# forEachValidSettingsCombination(ast, settingsCombinations) {
 96# | concreteSettings, ast, backend, index | ... }
 97#
 98# Executes the given block for each valid settings combination in the
 99# settings map. The ast passed into the block is resolved
 100# (ast.resolve) against the settings.
 101#
 102# The first form will call computeSettingsCombinations(ast) for you.
 103#
 104
 105def forEachValidSettingsCombination(ast, *optionalSettingsCombinations)
 106 raise if optionalSettingsCombinations.size > 1
 107
 108 if optionalSettingsCombinations.empty?
 109 settingsCombinations = computeSettingsCombinations(ast)
 110 else
 111 settingsCombinations = optionalSettingsCombiations[0]
 112 end
 113
 114 settingsCombinations.each_with_index {
 115 | concreteSettings, index |
 116 forSettings(concreteSettings, ast) {
 117 | concreteSettings_, lowLevelAST, backend |
 118 yield concreteSettings, lowLevelAST, backend, index
 119 }
 120 }
 121end
 122
 123#
 124# cppSettingsTest(concreteSettings)
 125#
 126# Returns the C++ code used to test if we are in a configuration that
 127# corresponds to the given concrete settings.
 128#
 129
 130def cppSettingsTest(concreteSettings)
 131 "#if " + concreteSettings.to_a.collect{
 132 | pair |
 133 (if pair[1]
 134 ""
 135 else
 136 "!"
 137 end) + "OFFLINE_ASM_" + pair[0]
 138 }.join(" && ")
 139end
 140
 141#
 142# isASTErroneous(ast)
 143#
 144# Tests to see if the AST claims that there is an error - i.e. if the
 145# user's code, after settings resolution, has Error nodes.
 146#
 147
 148def isASTErroneous(ast)
 149 not ast.filter(Error).empty?
 150end
 151
 152#
 153# assertConfiguration(concreteSettings)
 154#
 155# Emits a check that asserts that we're using the given configuration.
 156#
 157
 158def assertConfiguration(concreteSettings)
 159 $output.puts cppSettingsTest(concreteSettings)
 160 $output.puts "#else"
 161 $output.puts "#error \"Configuration mismatch.\""
 162 $output.puts "#endif"
 163end
 164
 165#
 166# emitCodeInConfiguration(concreteSettings, ast, backend) {
 167# | concreteSettings, ast, backend | ... }
 168#
 169# Emits all relevant guards to see if the configuration holds and
 170# calls the block if the configuration is not erroneous.
 171#
 172
 173def emitCodeInConfiguration(concreteSettings, ast, backend)
 174 $output.puts cppSettingsTest(concreteSettings)
 175
 176 if isASTErroneous(ast)
 177 $output.puts "#error \"Invalid configuration.\""
 178 elsif not WORKING_BACKENDS.include? backend
 179 $output.puts "#error \"This backend is not supported yet.\""
 180 else
 181 yield concreteSettings, ast, backend
 182 end
 183
 184 $output.puts "#endif"
 185end
 186
 187#
 188# emitCodeInAllConfigurations(ast) {
 189# | concreteSettings, ast, backend, index | ... }
 190#
 191# Emits guard codes for all valid configurations, and calls the block
 192# for those configurations that are valid and not erroneous.
 193#
 194
 195def emitCodeInAllConfigurations(ast)
 196 forEachValidSettingsCombination(ast) {
 197 | concreteSettings, lowLevelAST, backend, index |
 198 $output.puts cppSettingsTest(concreteSettings)
 199 yield concreteSettings, lowLevelAST, backend, index
 200 $output.puts "#endif"
 201 }
 202end
 203
 204
 205
0

Source/JavaScriptCore/offlineasm/transform.rb

 1# Copyright (C) 2011 Apple Inc. All rights reserved.
 2#
 3# Redistribution and use in source and binary forms, with or without
 4# modification, are permitted provided that the following conditions
 5# are met:
 6# 1. Redistributions of source code must retain the above copyright
 7# notice, this list of conditions and the following disclaimer.
 8# 2. Redistributions in binary form must reproduce the above copyright
 9# notice, this list of conditions and the following disclaimer in the
 10# documentation and/or other materials provided with the distribution.
 11#
 12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 22# THE POSSIBILITY OF SUCH DAMAGE.
 23
 24require "ast"
 25
 26#
 27# node.resolveSettings(settings)
 28#
 29# Construct a new AST that does not have any IfThenElse nodes by
 30# substituting concrete boolean values for each Setting.
 31#
 32
 33class Node
 34 def resolveSettings(settings)
 35 mapChildren {
 36 | child |
 37 child.resolveSettings(settings)
 38 }
 39 end
 40end
 41
 42class True
 43 def resolveSettings(settings)
 44 self
 45 end
 46end
 47
 48class False
 49 def resolveSettings(settings)
 50 self
 51 end
 52end
 53
 54class Setting
 55 def resolveSettings(settings)
 56 settings[@name].asNode
 57 end
 58end
 59
 60class And
 61 def resolveSettings(settings)
 62 (@left.resolveSettings(settings).value and @right.resolveSettings(settings).value).asNode
 63 end
 64end
 65
 66class Or
 67 def resolveSettings(settings)
 68 (@left.resolveSettings(settings).value or @right.resolveSettings(settings).value).asNode
 69 end
 70end
 71
 72class Not
 73 def resolveSettings(settings)
 74 (not @child.resolveSettings(settings).value).asNode
 75 end
 76end
 77
 78class IfThenElse
 79 def resolveSettings(settings)
 80 if @predicate.resolveSettings(settings).value
 81 @thenCase.resolveSettings(settings)
 82 else
 83 @elseCase.resolveSettings(settings)
 84 end
 85 end
 86end
 87
 88class Sequence
 89 def resolveSettings(settings)
 90 newList = []
 91 @list.each {
 92 | item |
 93 item = item.resolveSettings(settings)
 94 if item.is_a? Sequence
 95 newList += item.list
 96 else
 97 newList << item
 98 end
 99 }
 100 Sequence.new(codeOrigin, newList)
 101 end
 102end
 103
 104#
 105# node.demacroify(macros)
 106# node.substitute(mapping)
 107#
 108# demacroify() constructs a new AST that does not have any Macro
 109# nodes, while substitute() replaces Variable nodes with the given
 110# nodes in the mapping.
 111#
 112
 113class Node
 114 def demacroify(macros)
 115 mapChildren {
 116 | child |
 117 child.demacroify(macros)
 118 }
 119 end
 120
 121 def substitute(mapping)
 122 mapChildren {
 123 | child |
 124 child.substitute(mapping)
 125 }
 126 end
 127
 128 def substituteLabels(mapping)
 129 mapChildren {
 130 | child |
 131 child.substituteLabels(mapping)
 132 }
 133 end
 134end
 135
 136class Macro
 137 def substitute(mapping)
 138 myMapping = {}
 139 mapping.each_pair {
 140 | key, value |
 141 unless @variables.include? key
 142 myMapping[key] = value
 143 end
 144 }
 145 mapChildren {
 146 | child |
 147 child.substitute(myMapping)
 148 }
 149 end
 150end
 151
 152class Variable
 153 def substitute(mapping)
 154 if mapping[self]
 155 mapping[self]
 156 else
 157 self
 158 end
 159 end
 160end
 161
 162class LocalLabel
 163 def substituteLabels(mapping)
 164 if mapping[self]
 165 mapping[self]
 166 else
 167 self
 168 end
 169 end
 170end
 171
 172class Sequence
 173 def substitute(constants)
 174 newList = []
 175 myConstants = constants.dup
 176 @list.each {
 177 | item |
 178 if item.is_a? ConstDecl
 179 myConstants[item.variable] = item.value.substitute(myConstants)
 180 else
 181 newList << item.substitute(myConstants)
 182 end
 183 }
 184 Sequence.new(codeOrigin, newList)
 185 end
 186
 187 def renameLabels(comment)
 188 mapping = {}
 189
 190 @list.each {
 191 | item |
 192 if item.is_a? LocalLabel
 193 mapping[item] = LocalLabel.unique(if comment then comment + "_" else "" end + item.cleanName)
 194 end
 195 }
 196
 197 substituteLabels(mapping)
 198 end
 199
 200 def demacroify(macros)
 201 myMacros = macros.dup
 202 @list.each {
 203 | item |
 204 if item.is_a? Macro
 205 myMacros[item.name] = item
 206 end
 207 }
 208 newList = []
 209 @list.each {
 210 | item |
 211 if item.is_a? Macro
 212 # Ignore.
 213 elsif item.is_a? MacroCall
 214 mapping = {}
 215 myMyMacros = myMacros.dup
 216 raise "Could not find macro #{item.name} at #{item.codeOriginString}" unless myMacros[item.name]
 217 raise "Argument count mismatch for call to #{item.name} at #{item.codeOriginString}" unless item.operands.size == myMacros[item.name].variables.size
 218 item.operands.size.times {
 219 | idx |
 220 if item.operands[idx].is_a? Variable and myMacros[item.operands[idx].name]
 221 myMyMacros[myMacros[item.name].variables[idx].name] = myMacros[item.operands[idx].name]
 222 mapping[myMacros[item.name].variables[idx].name] = nil
 223 elsif item.operands[idx].is_a? Macro
 224 myMyMacros[myMacros[item.name].variables[idx].name] = item.operands[idx]
 225 mapping[myMacros[item.name].variables[idx].name] = nil
 226 else
 227 myMyMacros[myMacros[item.name].variables[idx]] = nil
 228 mapping[myMacros[item.name].variables[idx]] = item.operands[idx]
 229 end
 230 }
 231 newList += myMacros[item.name].body.substitute(mapping).demacroify(myMyMacros).renameLabels(item.name).list
 232 else
 233 newList << item.demacroify(myMacros)
 234 end
 235 }
 236 Sequence.new(codeOrigin, newList).substitute({})
 237 end
 238end
 239
 240#
 241# node.resolveOffsets(offsets, sizes)
 242#
 243# Construct a new AST that has offset values instead of symbolic
 244# offsets.
 245#
 246
 247class Node
 248 def resolveOffsets(offsets, sizes)
 249 mapChildren {
 250 | child |
 251 child.resolveOffsets(offsets, sizes)
 252 }
 253 end
 254end
 255
 256class StructOffset
 257 def resolveOffsets(offsets, sizes)
 258 if offsets[self]
 259 Immediate.new(codeOrigin, offsets[self])
 260 else
 261 self
 262 end
 263 end
 264end
 265
 266class Sizeof
 267 def resolveOffsets(offsets, sizes)
 268 if sizes[self]
 269 Immediate.new(codeOrigin, sizes[self])
 270 else
 271 puts "Could not find #{self.inspect} in #{sizes.keys.inspect}"
 272 puts "sizes = #{sizes.inspect}"
 273 self
 274 end
 275 end
 276end
 277
 278#
 279# node.fold
 280#
 281# Resolve constant references and compute arithmetic expressions.
 282#
 283
 284class Node
 285 def fold
 286 mapChildren {
 287 | child |
 288 child.fold
 289 }
 290 end
 291end
 292
 293class AddImmediates
 294 def fold
 295 @left = @left.fold
 296 @right = @right.fold
 297 return self unless @left.is_a? Immediate
 298 return self unless @right.is_a? Immediate
 299 Immediate.new(codeOrigin, @left.value + @right.value)
 300 end
 301end
 302
 303class SubImmediates
 304 def fold
 305 @left = @left.fold
 306 @right = @right.fold
 307 return self unless @left.is_a? Immediate
 308 return self unless @right.is_a? Immediate
 309 Immediate.new(codeOrigin, @left.value - @right.value)
 310 end
 311end
 312
 313class MulImmediates
 314 def fold
 315 @left = @left.fold
 316 @right = @right.fold
 317 return self unless @left.is_a? Immediate
 318 return self unless @right.is_a? Immediate
 319 Immediate.new(codeOrigin, @left.value * @right.value)
 320 end
 321end
 322
 323class NegImmediate
 324 def fold
 325 @child = @child.fold
 326 return self unless @child.is_a? Immediate
 327 Immediate.new(codeOrigin, -@child.value)
 328 end
 329end
 330
 331#
 332# node.resolveAfterSettings(offsets, sizes)
 333#
 334# Compile assembly against a set of offsets.
 335#
 336
 337class Node
 338 def resolve(offsets, sizes)
 339 demacroify({}).resolveOffsets(offsets, sizes).fold
 340 end
 341end
 342
0

Source/JavaScriptCore/offlineasm/x86.rb

 1# Copyright (C) 2011 Apple Inc. All rights reserved.
 2#
 3# Redistribution and use in source and binary forms, with or without
 4# modification, are permitted provided that the following conditions
 5# are met:
 6# 1. Redistributions of source code must retain the above copyright
 7# notice, this list of conditions and the following disclaimer.
 8# 2. Redistributions in binary form must reproduce the above copyright
 9# notice, this list of conditions and the following disclaimer in the
 10# documentation and/or other materials provided with the distribution.
 11#
 12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 22# THE POSSIBILITY OF SUCH DAMAGE.
 23
 24class RegisterID
 25 def supports8BitOnX86
 26 case name
 27 when "t0", "a0", "r0", "t1", "a1", "r1", "t2", "t3"
 28 true
 29 when "t4", "cfr"
 30 false
 31 else
 32 raise
 33 end
 34 end
 35
 36 def x86Operand(kind)
 37 case name
 38 when "t0", "a0", "r0"
 39 case kind
 40 when :byte
 41 "%al"
 42 when :half
 43 "%ax"
 44 when :int
 45 "%eax"
 46 else
 47 raise
 48 end
 49 when "t1", "a1", "r1"
 50 case kind
 51 when :byte
 52 "%dl"
 53 when :half
 54 "%dx"
 55 when :int
 56 "%edx"
 57 else
 58 raise
 59 end
 60 when "t2"
 61 case kind
 62 when :byte
 63 "%cl"
 64 when :half
 65 "%cx"
 66 when :int
 67 "%ecx"
 68 else
 69 raise
 70 end
 71 when "t3"
 72 case kind
 73 when :byte
 74 "%bl"
 75 when :half
 76 "%bx"
 77 when :int
 78 "%ebx"
 79 else
 80 raise
 81 end
 82 when "t4"
 83 case kind
 84 when :byte
 85 "%sil"
 86 when :half
 87 "%si"
 88 when :int
 89 "%esi"
 90 else
 91 raise
 92 end
 93 when "cfr"
 94 case kind
 95 when :byte
 96 "%dil"
 97 when :half
 98 "%di"
 99 when :int
 100 "%edi"
 101 else
 102 raise
 103 end
 104 when "sp"
 105 case kind
 106 when :byte
 107 "%spl"
 108 when :half
 109 "%sp"
 110 when :int
 111 "%esp"
 112 else
 113 raise
 114 end
 115 else
 116 raise "Bad register #{name} for X86 at #{codeOriginString}"
 117 end
 118 end
 119 def x86CallOperand(kind)
 120 "*#{x86Operand(kind)}"
 121 end
 122end
 123
 124class FPRegisterID
 125 def x86Operand(kind)
 126 raise unless kind == :double
 127 case name
 128 when "ft0", "fa0", "fr"
 129 "%xmm0"
 130 when "ft1", "fa1"
 131 "%xmm1"
 132 when "ft2", "fa2"
 133 "%xmm2"
 134 when "ft3", "fa3"
 135 "%xmm3"
 136 when "ft4"
 137 "%xmm4"
 138 when "ft5"
 139 "%xmm5"
 140 else
 141 raise "Bad register #{name} for X86 at #{codeOriginString}"
 142 end
 143 end
 144 def x86CallOperand(kind)
 145 "*#{x86Operand(kind)}"
 146 end
 147end
 148
 149class Immediate
 150 def x86Operand(kind)
 151 "$#{value}"
 152 end
 153 def x86CallOperand(kind)
 154 "#{value}"
 155 end
 156end
 157
 158class Address
 159 def supports8BitOnX86
 160 true
 161 end
 162
 163 def x86Operand(kind)
 164 "#{offset.value}(#{base.x86Operand(:int)})"
 165 end
 166 def x86CallOperand(kind)
 167 "*#{x86Operand(kind)}"
 168 end
 169end
 170
 171class BaseIndex
 172 def supports8BitOnX86
 173 true
 174 end
 175
 176 def x86Operand(kind)
 177 "#{offset.value}(#{base.x86Operand(:int)}, #{index.x86Operand(:int)}, #{scale})"
 178 end
 179
 180 def x86CallOperand(kind)
 181 "*#{x86operand(kind)}"
 182 end
 183end
 184
 185class AbsoluteAddress
 186 def supports8BitOnX86
 187 true
 188 end
 189
 190 def x86Operand(kind)
 191 "#{address.value}"
 192 end
 193
 194 def x86CallOperand(kind)
 195 "*#{address.value}"
 196 end
 197end
 198
 199class LabelReference
 200 def x86CallOperand(kind)
 201 asmLabel
 202 end
 203end
 204
 205class LocalLabelReference
 206 def x86CallOperand(kind)
 207 asmLabel
 208 end
 209end
 210
 211class Instruction
 212 def x86Operands(*kinds)
 213 raise unless kinds.size == operands.size
 214 result = []
 215 kinds.size.times {
 216 | idx |
 217 result << operands[idx].x86Operand(kinds[idx])
 218 }
 219 result.join(", ")
 220 end
 221
 222 def x86Suffix(kind)
 223 case kind
 224 when :byte
 225 "b"
 226 when :half
 227 "w"
 228 when :int
 229 "l"
 230 when :double
 231 "sd"
 232 else
 233 raise
 234 end
 235 end
 236
 237 def handleX86OpWithNumOperands(opcode, kind, numOperands)
 238 if numOperands == 3
 239 if operands[0] == operands[2]
 240 $asm.puts "#{opcode} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
 241 elsif operands[1] == operands[2]
 242 $asm.puts "#{opcode} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
 243 else
 244 $asm.puts "mov#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
 245 $asm.puts "#{opcode} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
 246 end
 247 else
 248 $asm.puts "#{opcode} #{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}"
 249 end
 250 end
 251
 252 def handleX86Op(opcode, kind)
 253 handleX86OpWithNumOperands(opcode, kind, operands.size)
 254 end
 255
 256 def handleX86Shift(opcode, kind)
 257 if operands[0].is_a? Immediate or operands[0] == RegisterID.forName(nil, "t2")
 258 $asm.puts "#{opcode} #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(kind)}"
 259 else
 260 $asm.puts "xchgl #{operands[0].x86Operand(:int)}, %ecx"
 261 $asm.puts "#{opcode} %cl, #{operands[1].x86Operand(kind)}"
 262 $asm.puts "xchgl #{operands[0].x86Operand(:int)}, %ecx"
 263 end
 264 end
 265
 266 def handleX86DoubleBranch(branchOpcode, mode)
 267 case mode
 268 when :normal
 269 $asm.puts "ucomisd #{operands[1].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
 270 when :reverse
 271 $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
 272 else
 273 raise mode.inspect
 274 end
 275 $asm.puts "#{branchOpcode} #{operands[2].asmLabel}"
 276 end
 277
 278 def handleX86IntCompare(opcodeSuffix, kind)
 279 if operands[0].is_a? Immediate and operands[0].value == 0 and operands[1].is_a? RegisterID and (opcodeSuffix == "e" or opcodeSuffix == "ne")
 280 $asm.puts "test#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}"
 281 elsif operands[1].is_a? Immediate and operands[1].value == 0 and operands[0].is_a? RegisterID and (opcodeSuffix == "e" or opcodeSuffix == "ne")
 282 $asm.puts "test#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}"
 283 else
 284 $asm.puts "cmp#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[0].x86Operand(kind)}"
 285 end
 286 end
 287
 288 def handleX86IntBranch(branchOpcode, kind)
 289 handleX86IntCompare(branchOpcode[1..-1], kind)
 290 $asm.puts "#{branchOpcode} #{operands[2].asmLabel}"
 291 end
 292
 293 def handleX86Set(setOpcode, operand)
 294 if operand.supports8BitOnX86
 295 $asm.puts "#{setOpcode} #{operand.x86Operand(:byte)}"
 296 $asm.puts "movzbl #{operand.x86Operand(:byte)}, #{operand.x86Operand(:int)}"
 297 else
 298 $asm.puts "xchgl #{operand.x86Operand(:int)}, %eax"
 299 $asm.puts "#{setOpcode} %al"
 300 $asm.puts "movzbl %al, %eax"
 301 $asm.puts "xchgl #{operand.x86Operand(:int)}, %eax"
 302 end
 303 end
 304
 305 def handleX86IntCompareSet(setOpcode, kind)
 306 handleX86IntCompare(setOpcode[3..-1], kind)
 307 handleX86Set(setOpcode, operands[2])
 308 end
 309
 310 def handleX86Test(kind)
 311 value = operands[0]
 312 case operands.size
 313 when 2
 314 mask = Immediate.new(codeOrigin, -1)
 315 when 3
 316 mask = operands[1]
 317 else
 318 raise "Expected 2 or 3 operands, but got #{operands.size} at #{codeOriginString}"
 319 end
 320
 321 if mask.is_a? Immediate and mask.value == -1
 322 if value.is_a? RegisterID
 323 $asm.puts "test#{x86Suffix(kind)} #{value.x86Operand(kind)}, #{value.x86Operand(kind)}"
 324 else
 325 $asm.puts "cmp#{x86Suffix(kind)} $0, #{value.x86Operand(kind)}"
 326 end
 327 else
 328 $asm.puts "test#{x86Suffix(kind)} #{mask.x86Operand(kind)}, #{value.x86Operand(kind)}"
 329 end
 330 end
 331
 332 def handleX86BranchTest(branchOpcode, kind)
 333 handleX86Test(kind)
 334 $asm.puts "#{branchOpcode} #{operands.last.asmLabel}"
 335 end
 336
 337 def handleX86SetTest(setOpcode, kind)
 338 handleX86Test(kind)
 339 handleX86Set(setOpcode, operands.last)
 340 end
 341
 342 def handleX86OpBranch(opcode, branchOpcode, kind)
 343 handleX86OpWithNumOperands(opcode, kind, operands.size - 1)
 344 case operands.size
 345 when 4
 346 jumpTarget = operands[3]
 347 when 3
 348 jumpTarget = operands[2]
 349 else
 350 raise self.inspect
 351 end
 352 $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}"
 353 end
 354
 355 def handleX86SubBranch(branchOpcode, kind)
 356 if operands.size == 4 and operands[1] == operands[2]
 357 $asm.puts "negl #{operands[2].x86Operand(:int)}"
 358 $asm.puts "addl #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:int)}"
 359 else
 360 handleX86OpWithNumOperands("sub#{x86Suffix(kind)}", kind, operands.size - 1)
 361 end
 362 case operands.size
 363 when 4
 364 jumpTarget = operands[3]
 365 when 3
 366 jumpTarget = operands[2]
 367 else
 368 raise self.inspect
 369 end
 370 $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}"
 371 end
 372
 373 def lowerX86
 374 $asm.comment codeOriginString
 375 case opcode
 376 when "addi", "addp"
 377 if operands.size == 3 and operands[0].is_a? Immediate
 378 raise unless operands[1].is_a? RegisterID
 379 raise unless operands[2].is_a? RegisterID
 380 if operands[0].value == 0
 381 unless operands[1] == operands[2]
 382 $asm.puts "movl #{operands[1].x86Operand(:int)}, #{operands[2].x86Operand(:int)}"
 383 end
 384 else
 385 $asm.puts "leal #{operands[0].value}(#{operands[1].x86Operand(:int)}), #{operands[2].x86Operand(:int)}"
 386 end
 387 elsif operands.size == 3 and operands[0].is_a? RegisterID
 388 raise unless operands[1].is_a? RegisterID
 389 raise unless operands[2].is_a? RegisterID
 390 $asm.puts "leal (#{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}), #{operands[2].x86Operand(:int)}"
 391 else
 392 unless Immediate.new(nil, 0) == operands[0]
 393 $asm.puts "addl #{x86Operands(:int, :int)}"
 394 end
 395 end
 396 when "andi", "andp"
 397 handleX86Op("andl", :int)
 398 when "lshifti"
 399 handleX86Shift("sall", :int)
 400 when "muli"
 401 if operands.size == 3 and operands[0].is_a? Immediate
 402 $asm.puts "imull #{x86Operands(:int, :int, :int)}"
 403 else
 404 # FIXME: could do some peephole in case the left operand is immediate and it's
 405 # a power of two.
 406 handleX86Op("imull", :int)
 407 end
 408 when "negi"
 409 $asm.puts "negl #{x86Operands(:int)}"
 410 when "noti"
 411 $asm.puts "notl #{x86Operands(:int)}"
 412 when "ori", "orp"
 413 handleX86Op("orl", :int)
 414 when "rshifti"
 415 handleX86Shift("sarl", :int)
 416 when "urshifti"
 417 handleX86Shift("shrl", :int)
 418 when "subi", "subp"
 419 if operands.size == 3 and operands[1] == operands[2]
 420 $asm.puts "negl #{operands[2].x86Operand(:int)}"
 421 $asm.puts "addl #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:int)}"
 422 else
 423 handleX86Op("subl", :int)
 424 end
 425 when "xori", "xorp"
 426 handleX86Op("xorl", :int)
 427 when "loadi", "storei", "loadp", "storep"
 428 $asm.puts "movl #{x86Operands(:int, :int)}"
 429 when "loadb"
 430 $asm.puts "movzbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}"
 431 when "loadbs"
 432 $asm.puts "movsbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}"
 433 when "loadh"
 434 $asm.puts "movzwl #{operands[0].x86Operand(:half)}, #{operands[1].x86Operand(:int)}"
 435 when "loadhs"
 436 $asm.puts "movswl #{operands[0].x86Operand(:half)}, #{operands[1].x86Operand(:int)}"
 437 when "storeb"
 438 $asm.puts "movb #{x86Operands(:byte, :byte)}"
 439 when "loadd", "moved", "stored"
 440 $asm.puts "movsd #{x86Operands(:double, :double)}"
 441 when "addd"
 442 $asm.puts "addsd #{x86Operands(:double, :double)}"
 443 when "divd"
 444 $asm.puts "divsd #{x86Operands(:double, :double)}"
 445 when "subd"
 446 $asm.puts "subsd #{x86Operands(:double, :double)}"
 447 when "muld"
 448 $asm.puts "mulsd #{x86Operands(:double, :double)}"
 449 when "sqrtd"
 450 $asm.puts "sqrtsd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
 451 when "ci2d"
 452 $asm.puts "cvtsi2sd #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:double)}"
 453 when "bdeq"
 454 isUnordered = LocalLabel.unique("bdeq")
 455 $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
 456 $asm.puts "jp #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
 457 $asm.puts "je #{LabelReference.new(codeOrigin, operands[2]).asmLabel}"
 458 isUnordered.lower("X86")
 459 when "bdneq"
 460 handleX86DoubleBranch("jne", :normal)
 461 when "bdgt"
 462 handleX86DoubleBranch("ja", :normal)
 463 when "bdgteq"
 464 handleX86DoubleBranch("jae", :normal)
 465 when "bdlt"
 466 handleX86DoubleBranch("ja", :reverse)
 467 when "bdlteq"
 468 handleX86DoubleBranch("jae", :reverse)
 469 when "bdequn"
 470 handleX86DoubleBranch("je", :normal)
 471 when "bdnequn"
 472 isUnordered = LocalLabel.unique("bdnequn")
 473 isEqual = LocalLabel.unique("bdnequn")
 474 $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
 475 $asm.puts "jp #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
 476 $asm.puts "je #{LabelReference.new(codeOrigin, isEqual).asmLabel}"
 477 isUnordered.lower("X86")
 478 $asm.puts "jmp #{operands[2].asmLabel}"
 479 isEqual.lower("X86")
 480 when "bdgtun"
 481 handleX86DoubleBranch("jb", :reverse)
 482 when "bdgtequn"
 483 handleX86DoubleBranch("jbe", :reverse)
 484 when "bdltun"
 485 handleX86DoubleBranch("jb", :normal)
 486 when "bdltequn"
 487 handleX86DoubleBranch("jbe", :normal)
 488 when "btd2i"
 489 $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
 490 $asm.puts "cmpl $0x80000000 #{operands[1].x86Operand(:int)}"
 491 $asm.puts "je #{operands[2].asmLabel}"
 492 when "td2i"
 493 $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
 494 when "bcd2i"
 495 $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
 496 $asm.puts "testl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
 497 $asm.puts "je #{operands[2].asmLabel}"
 498 $asm.puts "cvtsi2sd #{operands[1].x86Operand(:int)}, %xmm7"
 499 $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, %xmm7"
 500 $asm.puts "jp #{operands[2].asmLabel}"
 501 $asm.puts "jne #{operands[2].asmLabel}"
 502 when "movdz"
 503 $asm.puts "xorpd #{operands[0].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
 504 when "pop"
 505 $asm.puts "pop #{operands[0].x86Operand(:int)}"
 506 when "push"
 507 $asm.puts "push #{operands[0].x86Operand(:int)}"
 508 when "move", "sxi2p", "zxi2p"
 509 if Immediate.new(nil, 0) == operands[0] and operands[1].is_a? RegisterID
 510 $asm.puts "xorl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
 511 elsif operands[0] != operands[1]
 512 $asm.puts "movl #{x86Operands(:int, :int)}"
 513 end
 514 when "nop"
 515 $asm.puts "nop"
 516 when "bieq", "bpeq"
 517 handleX86IntBranch("je", :int)
 518 when "bineq", "bpneq"
 519 handleX86IntBranch("jne", :int)
 520 when "bia", "bpa"
 521 handleX86IntBranch("ja", :int)
 522 when "biaeq", "bpaeq"
 523 handleX86IntBranch("jae", :int)
 524 when "bib", "bpb"
 525 handleX86IntBranch("jb", :int)
 526 when "bibeq", "bpbeq"
 527 handleX86IntBranch("jbe", :int)
 528 when "bigt", "bpgt"
 529 handleX86IntBranch("jg", :int)
 530 when "bigteq", "bpgteq"
 531 handleX86IntBranch("jge", :int)
 532 when "bilt", "bplt"
 533 handleX86IntBranch("jl", :int)
 534 when "bilteq", "bplteq"
 535 handleX86IntBranch("jle", :int)
 536 when "bbeq"
 537 handleX86IntBranch("je", :byte)
 538 when "bbneq"
 539 handleX86IntBranch("jne", :byte)
 540 when "bba"
 541 handleX86IntBranch("ja", :byte)
 542 when "bbaeq"
 543 handleX86IntBranch("jae", :byte)
 544 when "bbb"
 545 handleX86IntBranch("jb", :byte)
 546 when "bbbeq"
 547 handleX86IntBranch("jbe", :byte)
 548 when "bbgt"
 549 handleX86IntBranch("jg", :byte)
 550 when "bbgteq"
 551 handleX86IntBranch("jge", :byte)
 552 when "bblt"
 553 handleX86IntBranch("jl", :byte)
 554 when "bblteq"
 555 handleX86IntBranch("jlteq", :byte)
 556 when "btio", "btpo"
 557 handleX86BranchTest("jo", :int)
 558 when "btis", "btps"
 559 handleX86BranchTest("js", :int)
 560 when "btiz", "btpz"
 561 handleX86BranchTest("jz", :int)
 562 when "btinz", "btpnz"
 563 handleX86BranchTest("jnz", :int)
 564 when "btbo"
 565 handleX86BranchTest("jo", :byte)
 566 when "btbs"
 567 handleX86BranchTest("js", :byte)
 568 when "btbz"
 569 handleX86BranchTest("jz", :byte)
 570 when "btbnz"
 571 handleX86BranchTest("jnz", :byte)
 572 when "jmp"
 573 $asm.puts "jmp #{operands[0].x86CallOperand(:int)}"
 574 when "baddio", "baddpo"
 575 handleX86OpBranch("addl", "jo", :int)
 576 when "baddis", "baddps"
 577 handleX86OpBranch("addl", "js", :int)
 578 when "baddiz", "baddpz"
 579 handleX86OpBranch("addl", "jz", :int)
 580 when "baddinz", "baddpnz"
 581 handleX86OpBranch("addl", "jnz", :int)
 582 when "bsubio"
 583 handleX86SubBranch("jo", :int)
 584 when "bsubis"
 585 handleX86SubBranch("js", :int)
 586 when "bsubiz"
 587 handleX86SubBranch("jz", :int)
 588 when "bsubinz"
 589 handleX86SubBranch("jnz", :int)
 590 when "bmulio"
 591 handleX86OpBranch("imull", "jo", :int)
 592 when "bmulis"
 593 handleX86OpBranch("imull", "js", :int)
 594 when "bmuliz"
 595 handleX86OpBranch("imull", "jz", :int)
 596 when "bmulinz"
 597 handleX86OpBranch("imull", "jnz", :int)
 598 when "borio"
 599 handleX86OpBranch("orl", "jo", :int)
 600 when "boris"
 601 handleX86OpBranch("orl", "js", :int)
 602 when "boriz"
 603 handleX86OpBranch("orl", "jz", :int)
 604 when "borinz"
 605 handleX86OpBranch("orl", "jnz", :int)
 606 when "break"
 607 $asm.puts "int $3"
 608 when "call"
 609 $asm.puts "call #{operands[0].x86CallOperand(:int)}"
 610 when "ret"
 611 $asm.puts "ret"
 612 when "cieq", "cpeq"
 613 handleX86IntCompareSet("sete", :int)
 614 when "cineq", "cpneq"
 615 handleX86IntCompareSet("setne", :int)
 616 when "cia", "cpa"
 617 handleX86IntCompareSet("seta", :int)
 618 when "ciaeq", "cpaeq"
 619 handleX86IntCompareSet("setae", :int)
 620 when "cib", "cpb"
 621 handleX86IntCompareSet("setb", :int)
 622 when "cibeq", "cpbeq"
 623 handleX86IntCompareSet("setbe", :int)
 624 when "cigt", "cpgt"
 625 handleX86IntCompareSet("setg", :int)
 626 when "cigteq", "cpgteq"
 627 handleX86IntCompareSet("setge", :int)
 628 when "cilt", "cplt"
 629 handleX86IntCompareSet("setl", :int)
 630 when "cilteq", "cplteq"
 631 handleX86IntCompareSet("setle", :int)
 632 when "tio"
 633 handleX86SetTest("seto", :int)
 634 when "tis"
 635 handleX86SetTest("sets", :int)
 636 when "tiz"
 637 handleX86SetTest("setz", :int)
 638 when "tinz"
 639 handleX86SetTest("setnz", :int)
 640 when "tbo"
 641 handleX86SetTest("seto", :byte)
 642 when "tbs"
 643 handleX86SetTest("sets", :byte)
 644 when "tbz"
 645 handleX86SetTest("setz", :byte)
 646 when "tbnz"
 647 handleX86SetTest("setnz", :byte)
 648 when "peek"
 649 $asm.puts "movl #{operands[0].value * 4}(%esp), #{operands[1].x86Operand(:int)}"
 650 when "poke"
 651 $asm.puts "movl #{operands[0].x86Operand(:int)}, #{operands[1].value * 4}(%esp)"
 652 when "cdqi"
 653 $asm.puts "cdq"
 654 when "idivi"
 655 $asm.puts "idivl #{operands[0].x86Operand(:int)}"
 656 when "fii2d"
 657 $asm.puts "movd #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:double)}"
 658 $asm.puts "movd #{operands[1].x86Operand(:int)}, %xmm7"
 659 $asm.puts "psllq $32, %xmm7"
 660 $asm.puts "por %xmm7, #{operands[2].x86Operand(:double)}"
 661 when "fd2ii"
 662 $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
 663 $asm.puts "movsd #{operands[0].x86Operand(:double)}, %xmm7"
 664 $asm.puts "psrlq $32, %xmm7"
 665 $asm.puts "movsd %xmm7, #{operands[2].x86Operand(:int)}"
 666 when "bo"
 667 $asm.puts "jo #{operands[0].asmLabel}"
 668 when "bs"
 669 $asm.puts "js #{operands[0].asmLabel}"
 670 when "bz"
 671 $asm.puts "jz #{operands[0].asmLabel}"
 672 when "bnz"
 673 $asm.puts "jnz #{operands[0].asmLabel}"
 674 when "leai", "leap"
 675 $asm.puts "leal #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
 676 else
 677 raise "Bad opcode: #{opcode}"
 678 end
 679 end
 680end
 681
0

Source/JavaScriptCore/runtime/CodeSpecializationKind.h

 1/*
 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef CodeSpecializationKind_h
 27#define CodeSpecializationKind_h
 28
 29namespace JSC {
 30
 31enum CodeSpecializationKind { CodeForCall, CodeForConstruct };
 32
 33} // namespace JSC
 34
 35#endif // CodeSpecializationKind_h
 36
0

Source/JavaScriptCore/runtime/CommonSlowPaths.h

2727#define CommonSlowPaths_h
2828
2929#include "CodeBlock.h"
 30#include "CodeSpecializationKind.h"
3031#include "ExceptionHelpers.h"
3132#include "JSArray.h"
3233

@@namespace JSC {
4142
4243namespace CommonSlowPaths {
4344
 45ALWAYS_INLINE ExecState* arityCheckFor(ExecState* exec, RegisterFile* registerFile, CodeSpecializationKind kind)
 46{
 47 JSFunction* callee = asFunction(exec->callee());
 48 ASSERT(!callee->isHostFunction());
 49 CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecodeFor(kind);
 50 int argumentCountIncludingThis = exec->argumentCountIncludingThis();
 51
 52 // This ensures enough space for the worst case scenario of zero arguments passed by the caller.
 53 if (!registerFile->grow(exec->registers() + newCodeBlock->numParameters() + newCodeBlock->m_numCalleeRegisters))
 54 return 0;
 55
 56 ASSERT(argumentCountIncludingThis < newCodeBlock->numParameters());
 57
 58 // Too few arguments -- copy call frame and arguments, then fill in missing arguments with undefined.
 59 size_t delta = newCodeBlock->numParameters() - argumentCountIncludingThis;
 60 Register* src = exec->registers();
 61 Register* dst = exec->registers() + delta;
 62
 63 int i;
 64 int end = -ExecState::offsetFor(argumentCountIncludingThis);
 65 for (i = -1; i >= end; --i)
 66 dst[i] = src[i];
 67
 68 end -= delta;
 69 for ( ; i >= end; --i)
 70 dst[i] = jsUndefined();
 71
 72 ExecState* newExec = ExecState::create(dst);
 73 ASSERT((void*)newExec <= registerFile->end());
 74 return newExec;
 75}
 76
4477ALWAYS_INLINE bool opInstanceOfSlow(ExecState* exec, JSValue value, JSValue baseVal, JSValue proto)
4578{
4679 ASSERT(!value.isCell() || !baseVal.isCell() || !proto.isCell()
107713

Source/JavaScriptCore/runtime/Executable.cpp

2929#include "BytecodeGenerator.h"
3030#include "CodeBlock.h"
3131#include "DFGDriver.h"
 32#include "ExecutionHarness.h"
3233#include "JIT.h"
3334#include "JITDriver.h"
3435#include "Parser.h"

@@Intrinsic NativeExecutable::intrinsic()
8485template<typename T>
8586static void jettisonCodeBlock(JSGlobalData& globalData, OwnPtr<T>& codeBlock)
8687{
87  ASSERT(codeBlock->getJITType() != JITCode::BaselineJIT);
 88 ASSERT(JITCode::isOptimizingJIT(codeBlock->getJITType()));
8889 ASSERT(codeBlock->alternative());
8990 OwnPtr<T> codeBlockToJettison = codeBlock.release();
9091 codeBlock = static_pointer_cast<T>(codeBlockToJettison->releaseAlternative());

@@JSObject* EvalExecutable::compileOptimiz
169170 return error;
170171}
171172
 173void EvalExecutable::jitCompile(JSGlobalData& globalData)
 174{
 175 bool result = jitCompileIfAppropriate(globalData, m_evalCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT());
 176 ASSERT_UNUSED(result, result);
 177}
 178
 179inline const char* samplingDescription(JITCode::JITType jitType)
 180{
 181 switch (jitType) {
 182 case JITCode::InterpreterThunk:
 183 return "Interpreter Compilation (TOTAL)";
 184 case JITCode::BaselineJIT:
 185 return "Baseline Compilation (TOTAL)";
 186 case JITCode::DFGJIT:
 187 return "DFG Compilation (TOTAL)";
 188 default:
 189 ASSERT_NOT_REACHED();
 190 return 0;
 191 }
 192}
 193
172194JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
173195{
174  SamplingRegion samplingRegion(jitType == JITCode::BaselineJIT ? "Baseline Compilation (TOTAL)" : "DFG Compilation (TOTAL)");
 196 SamplingRegion samplingRegion(samplingDescription(jitType));
175197
176198#if !ENABLE(JIT)
177199 UNUSED_PARAM(jitType);

@@JSObject* EvalExecutable::compileInterna
212234 }
213235
214236#if ENABLE(JIT)
215  if (!jitCompileIfAppropriate(*globalData, m_evalCodeBlock, m_jitCodeForCall, jitType))
 237 if (!prepareForExecution(*globalData, m_evalCodeBlock, m_jitCodeForCall, jitType))
216238 return 0;
217239#endif
218240

@@JSObject* ProgramExecutable::compileOpti
297319 return error;
298320}
299321
 322void ProgramExecutable::jitCompile(JSGlobalData& globalData)
 323{
 324 bool result = jitCompileIfAppropriate(globalData, m_programCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT());
 325 ASSERT_UNUSED(result, result);
 326}
 327
300328JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
301329{
302  SamplingRegion samplingRegion(jitType == JITCode::BaselineJIT ? "Baseline Compilation (TOTAL)" : "DFG Compilation (TOTAL)");
 330 SamplingRegion samplingRegion(samplingDescription(jitType));
303331
304332#if !ENABLE(JIT)
305333 UNUSED_PARAM(jitType);

@@JSObject* ProgramExecutable::compileInte
338366 }
339367
340368#if ENABLE(JIT)
341  if (!jitCompileIfAppropriate(*globalData, m_programCodeBlock, m_jitCodeForCall, jitType))
 369 if (!prepareForExecution(*globalData, m_programCodeBlock, m_jitCodeForCall, jitType))
342370 return 0;
343371#endif
344372

@@FunctionCodeBlock* FunctionExecutable::b
414442 while (result->alternative())
415443 result = static_cast<FunctionCodeBlock*>(result->alternative());
416444 ASSERT(result);
417  ASSERT(result->getJITType() == JITCode::BaselineJIT);
 445 ASSERT(JITCode::isBaselineCode(result->getJITType()));
418446 return result;
419447}
420448

@@JSObject* FunctionExecutable::compileOpt
440468 return error;
441469}
442470
 471void FunctionExecutable::jitCompileForCall(JSGlobalData& globalData)
 472{
 473 bool result = jitCompileFunctionIfAppropriate(globalData, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, JITCode::bottomTierJIT());
 474 ASSERT_UNUSED(result, result);
 475}
 476
 477void FunctionExecutable::jitCompileForConstruct(JSGlobalData& globalData)
 478{
 479 bool result = jitCompileFunctionIfAppropriate(globalData, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, JITCode::bottomTierJIT());
 480 ASSERT_UNUSED(result, result);
 481}
 482
443483FunctionCodeBlock* FunctionExecutable::codeBlockWithBytecodeFor(CodeSpecializationKind kind)
444484{
445485 FunctionCodeBlock* codeBlock = baselineCodeBlockFor(kind);

@@PassOwnPtr<FunctionCodeBlock> FunctionEx
484524
485525JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
486526{
487  SamplingRegion samplingRegion(jitType == JITCode::BaselineJIT ? "Baseline Compilation (TOTAL)" : "DFG Compilation (TOTAL)");
 527 SamplingRegion samplingRegion(samplingDescription(jitType));
488528
489529#if !ENABLE(JIT)
490530 UNUSED_PARAM(exec);

@@JSObject* FunctionExecutable::compileFor
506546 m_symbolTable = m_codeBlockForCall->sharedSymbolTable();
507547
508548#if ENABLE(JIT)
509  if (!jitCompileFunctionIfAppropriate(exec->globalData(), m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, jitType))
 549 if (!prepareFunctionForExecution(exec->globalData(), m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, jitType, CodeForCall))
510550 return 0;
511551#endif
512552

@@JSObject* FunctionExecutable::compileFor
526566
527567JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
528568{
529  SamplingRegion samplingRegion(jitType == JITCode::BaselineJIT ? "Baseline Compilation (TOTAL)" : "DFG Compilation (TOTAL)");
 569 SamplingRegion samplingRegion(samplingDescription(jitType));
530570
531571#if !ENABLE(JIT)
532572 UNUSED_PARAM(jitType);

@@JSObject* FunctionExecutable::compileFor
548588 m_symbolTable = m_codeBlockForConstruct->sharedSymbolTable();
549589
550590#if ENABLE(JIT)
551  if (!jitCompileFunctionIfAppropriate(exec->globalData(), m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, jitType))
 591 if (!prepareFunctionForExecution(exec->globalData(), m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, jitType, CodeForConstruct))
552592 return 0;
553593#endif
554594
107713

Source/JavaScriptCore/runtime/Executable.h

2727#define Executable_h
2828
2929#include "CallData.h"
 30#include "CodeSpecializationKind.h"
3031#include "JSFunction.h"
3132#include "Interpreter.h"
3233#include "Nodes.h"

@@namespace JSC {
3940 class Debugger;
4041 class EvalCodeBlock;
4142 class FunctionCodeBlock;
 43 class LLIntOffsetsExtractor;
4244 class ProgramCodeBlock;
4345 class ScopeChainNode;
4446
4547 struct ExceptionInfo;
4648
47  enum CodeSpecializationKind { CodeForCall, CodeForConstruct };
4849 enum CompilationKind { FirstCompilation, OptimizingCompilation };
4950
5051 inline bool isCall(CodeSpecializationKind kind)

@@namespace JSC {
319320 };
320321
321322 class EvalExecutable : public ScriptExecutable {
 323 friend class LLIntOffsetsExtractor;
322324 public:
323325 typedef ScriptExecutable Base;
324326

@@namespace JSC {
338340
339341#if ENABLE(JIT)
340342 void jettisonOptimizedCode(JSGlobalData&);
 343 void jitCompile(JSGlobalData&);
341344#endif
342345
343346 EvalCodeBlock& generatedBytecode()

@@namespace JSC {
384387 };
385388
386389 class ProgramExecutable : public ScriptExecutable {
 390 friend class LLIntOffsetsExtractor;
387391 public:
388392 typedef ScriptExecutable Base;
389393

@@namespace JSC {
411415
412416#if ENABLE(JIT)
413417 void jettisonOptimizedCode(JSGlobalData&);
 418 void jitCompile(JSGlobalData&);
414419#endif
415420
416421 ProgramCodeBlock& generatedBytecode()

@@namespace JSC {
453458
454459 class FunctionExecutable : public ScriptExecutable {
455460 friend class JIT;
 461 friend class LLIntOffsetsExtractor;
456462 public:
457463 typedef ScriptExecutable Base;
458464

@@namespace JSC {
508514
509515#if ENABLE(JIT)
510516 void jettisonOptimizedCodeForCall(JSGlobalData&);
 517 void jitCompileForCall(JSGlobalData&);
511518#endif
512519
513520 bool isGeneratedForCall() const

@@namespace JSC {
535542
536543#if ENABLE(JIT)
537544 void jettisonOptimizedCodeForConstruct(JSGlobalData&);
 545 void jitCompileForConstruct(JSGlobalData&);
538546#endif
539547
540548 bool isGeneratedForConstruct() const

@@namespace JSC {
582590 jettisonOptimizedCodeForConstruct(globalData);
583591 }
584592 }
 593
 594 void jitCompileFor(JSGlobalData& globalData, CodeSpecializationKind kind)
 595 {
 596 if (kind == CodeForCall) {
 597 jitCompileForCall(globalData);
 598 return;
 599 }
 600 ASSERT(kind == CodeForConstruct);
 601 jitCompileForConstruct(globalData);
 602 }
585603#endif
586604
587605 bool isGeneratedFor(CodeSpecializationKind kind)
107713

Source/JavaScriptCore/runtime/ExecutionHarness.h

 1/*
 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef ExecutionHarness_h
 27#define ExecutionHarness_h
 28
 29#include <wtf/Platform.h>
 30
 31#if ENABLE(JIT)
 32
 33#include "JITDriver.h"
 34#include "LLIntEntrypoints.h"
 35
 36namespace JSC {
 37
 38template<typename CodeBlockType>
 39inline bool prepareForExecution(JSGlobalData& globalData, OwnPtr<CodeBlockType>& codeBlock, JITCode& jitCode, JITCode::JITType jitType)
 40{
 41#if ENABLE(LLINT)
 42 if (JITCode::isBaselineCode(jitType)) {
 43 // Start off in the low level interpreter.
 44 LLInt::getEntrypoint(globalData, codeBlock.get(), jitCode);
 45 codeBlock->setJITCode(jitCode, MacroAssemblerCodePtr());
 46 return true;
 47 }
 48#endif // ENABLE(LLINT)
 49 return jitCompileIfAppropriate(globalData, codeBlock, jitCode, jitType);
 50}
 51
 52inline bool prepareFunctionForExecution(JSGlobalData& globalData, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType, CodeSpecializationKind kind)
 53{
 54#if ENABLE(LLINT)
 55 if (JITCode::isBaselineCode(jitType)) {
 56 // Start off in the low level interpreter.
 57 LLInt::getFunctionEntrypoint(globalData, kind, jitCode, jitCodeWithArityCheck);
 58 codeBlock->setJITCode(jitCode, jitCodeWithArityCheck);
 59 return true;
 60 }
 61#else
 62 UNUSED_PARAM(kind);
 63#endif // ENABLE(LLINT)
 64 return jitCompileFunctionIfAppropriate(globalData, codeBlock, jitCode, jitCodeWithArityCheck, symbolTable, jitType);
 65}
 66
 67} // namespace JSC
 68
 69#endif // ENABLE(JIT)
 70
 71#endif // ExecutionHarness_h
 72
0

Source/JavaScriptCore/runtime/JSActivation.h

@@namespace JSC {
126126
127127 OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[registerArraySize]);
128128 WriteBarrier<Unknown>* registers = registerArray.get() + registerOffset;
129 
 129
130130 // Copy all arguments that can be captured by name or by the arguments object.
131131 for (int i = 0; i < m_numCapturedArgs; ++i) {
132132 int index = CallFrame::argumentOffset(i);
107713

Source/JavaScriptCore/runtime/JSArray.h

2828namespace JSC {
2929
3030 class JSArray;
 31 class LLIntOffsetsExtractor;
3132
3233 struct SparseArrayEntry : public WriteBarrier<Unknown> {
3334 typedef WriteBarrier<Unknown> Base;

@@namespace JSC {
122123 };
123124
124125 class JSArray : public JSNonFinalObject {
 126 friend class LLIntOffsetsExtractor;
125127 friend class Walker;
126128
127129 protected:
107713

Source/JavaScriptCore/runtime/JSCell.h

3636namespace JSC {
3737
3838 class JSGlobalObject;
39  class Structure;
 39 class LLIntOffsetsExtractor;
4040 class PropertyDescriptor;
4141 class PropertyNameArray;
 42 class Structure;
4243
4344 enum EnumerationMode {
4445 ExcludeDontEnumProperties,

@@namespace JSC {
163164 static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
164165
165166 private:
 167 friend class LLIntOffsetsExtractor;
 168
166169 const ClassInfo* m_classInfo;
167170 WriteBarrier<Structure> m_structure;
168171 };
107713

Source/JavaScriptCore/runtime/JSFunction.h

@@namespace JSC {
3333 class FunctionPrototype;
3434 class JSActivation;
3535 class JSGlobalObject;
 36 class LLIntOffsetsExtractor;
3637 class NativeExecutable;
3738 class SourceCode;
3839 namespace DFG {

@@namespace JSC {
140141 static void visitChildren(JSCell*, SlotVisitor&);
141142
142143 private:
 144 friend class LLIntOffsetsExtractor;
 145
143146 JS_EXPORT_PRIVATE bool isHostFunctionNonInline() const;
144147
145148 static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&);
107713

Source/JavaScriptCore/runtime/JSGlobalData.cpp

3535#include "DebuggerActivation.h"
3636#include "FunctionConstructor.h"
3737#include "GetterSetter.h"
 38#include "HostCallReturnValue.h"
3839#include "Interpreter.h"
3940#include "JSActivation.h"
4041#include "JSAPIValueWrapper.h"

@@JSGlobalData::JSGlobalData(GlobalDataTyp
141142 , keywords(adoptPtr(new Keywords(this)))
142143 , interpreter(0)
143144 , heap(this, heapSize)
 145 , jsArrayClassInfo(&JSArray::s_info)
 146 , jsFinalObjectClassInfo(&JSFinalObject::s_info)
144147#if ENABLE(DFG_JIT)
145148 , sizeOfLastScratchBuffer(0)
146149#endif

@@JSGlobalData::JSGlobalData(GlobalDataTyp
216219 jitStubs = adoptPtr(new JITThunks(this));
217220#endif
218221
219  interpreter->initialize(this->canUseJIT());
 222 interpreter->initialize(&llintData, this->canUseJIT());
 223
 224 initializeHostCallReturnValue(); // This is needed to convince the linker not to drop host call return support.
220225
221226 heap.notifyIsSafeToCollect();
222227}
107713

Source/JavaScriptCore/runtime/JSGlobalData.h

3030#define JSGlobalData_h
3131
3232#include "CachedTranscendentalFunction.h"
33 #include "Intrinsic.h"
3433#include "DateInstanceCache.h"
3534#include "ExecutableAllocator.h"
3635#include "Heap.h"
37 #include "Strong.h"
 36#include "Intrinsic.h"
3837#include "JITStubs.h"
3938#include "JSValue.h"
 39#include "LLIntData.h"
4040#include "NumericStrings.h"
4141#include "SmallStrings.h"
 42#include "Strong.h"
4243#include "Terminator.h"
4344#include "TimeoutChecker.h"
4445#include "WeakRandom.h"

@@namespace JSC {
6566 class JSGlobalObject;
6667 class JSObject;
6768 class Keywords;
 69 class LLIntOffsetsExtractor;
6870 class NativeExecutable;
6971 class ParserArena;
7072 class RegExpCache;

@@namespace JSC {
241243 Heap heap;
242244
243245 JSValue exception;
 246
 247 const ClassInfo* const jsArrayClassInfo;
 248 const ClassInfo* const jsFinalObjectClassInfo;
 249
 250 LLInt::Data llintData;
 251
244252#if ENABLE(JIT)
245253 ReturnAddressPtr exceptionLocation;
246254 JSValue hostCallReturnValue;

@@namespace JSC {
346354#undef registerTypedArrayFunction
347355
348356 private:
 357 friend class LLIntOffsetsExtractor;
 358
349359 JSGlobalData(GlobalDataType, ThreadStackType, HeapSize);
350360 static JSGlobalData*& sharedInstanceInternal();
351361 void createNativeThunk();
107713

Source/JavaScriptCore/runtime/JSGlobalObject.h

@@namespace JSC {
4444 class FunctionPrototype;
4545 class GetterSetter;
4646 class GlobalCodeBlock;
 47 class LLIntOffsetsExtractor;
4748 class NativeErrorConstructor;
4849 class ProgramCodeBlock;
4950 class RegExpConstructor;

@@namespace JSC {
336337 JS_EXPORT_PRIVATE void addStaticGlobals(GlobalPropertyInfo*, int count);
337338
338339 private:
 340 friend class LLIntOffsetsExtractor;
 341
339342 // FIXME: Fold reset into init.
340343 JS_EXPORT_PRIVATE void init(JSObject* thisValue);
341344 void reset(JSValue prototype);
107713

Source/JavaScriptCore/runtime/JSObject.h

@@namespace JSC {
4949 class GetterSetter;
5050 class HashEntry;
5151 class InternalFunction;
 52 class LLIntOffsetsExtractor;
5253 class MarkedBlock;
5354 class PropertyDescriptor;
5455 class PropertyNameArray;

@@namespace JSC {
262263 JSObject(JSGlobalData&, Structure*, PropertyStorage inlineStorage);
263264
264265 private:
 266 friend class LLIntOffsetsExtractor;
 267
265268 // Nobody should ever ask any of these questions on something already known to be a JSObject.
266269 using JSCell::isAPIValueWrapper;
267270 using JSCell::isGetterSetter;

@@COMPILE_ASSERT((JSFinalObject_inlineStor
367370 }
368371
369372 private:
 373 friend class LLIntOffsetsExtractor;
 374
370375 explicit JSFinalObject(JSGlobalData& globalData, Structure* structure)
371376 : JSObject(globalData, structure, m_inlineStorage)
372377 {
107713

Source/JavaScriptCore/runtime/JSPropertyNameIterator.h

@@namespace JSC {
3838
3939 class Identifier;
4040 class JSObject;
 41 class LLIntOffsetsExtractor;
4142
4243 class JSPropertyNameIterator : public JSCell {
4344 friend class JIT;

@@namespace JSC {
9697 }
9798
9899 private:
 100 friend class LLIntOffsetsExtractor;
 101
99102 JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlot);
100103
101104 WriteBarrier<Structure> m_cachedStructure;
107713

Source/JavaScriptCore/runtime/JSString.h

3232namespace JSC {
3333
3434 class JSString;
 35 class LLIntOffsetsExtractor;
3536
3637 JSString* jsEmptyString(JSGlobalData*);
3738 JSString* jsEmptyString(ExecState*);

@@namespace JSC {
240241 static void visitChildren(JSCell*, SlotVisitor&);
241242
242243 private:
 244 friend class LLIntOffsetsExtractor;
 245
243246 JS_EXPORT_PRIVATE void resolveRope(ExecState*) const;
244247 void resolveRopeSlowCase8(LChar*) const;
245248 void resolveRopeSlowCase(UChar*) const;
107713

Source/JavaScriptCore/runtime/JSTypeInfo.h

3434
3535namespace JSC {
3636
 37 class LLIntOffsetsExtractor;
 38
3739 static const unsigned MasqueradesAsUndefined = 1; // WebCore uses MasqueradesAsUndefined to make document.all undetectable.
3840 static const unsigned ImplementsHasInstance = 1 << 1;
3941 static const unsigned OverridesHasInstance = 1 << 2;

@@namespace JSC {
8789 }
8890
8991 private:
 92 friend class LLIntOffsetsExtractor;
 93
9094 bool isSetOnFlags1(unsigned flag) const { ASSERT(flag <= (1 << 7)); return m_flags & flag; }
9195 bool isSetOnFlags2(unsigned flag) const { ASSERT(flag >= (1 << 8)); return m_flags2 & (flag >> 8); }
9296
107713

Source/JavaScriptCore/runtime/JSValue.cpp

@@JSObject* JSValue::synthesizePrototype(E
118118
119119char* JSValue::description()
120120{
121  static const size_t size = 64;
 121 static const size_t size = 128;
122122 static char description[size];
123123
124124 if (!*this)

@@char* JSValue::description()
127127 snprintf(description, size, "Int32: %d", asInt32());
128128 else if (isDouble()) {
129129#if USE(JSVALUE64)
130  snprintf(description, size, "Double: %lf, %lx", asDouble(), reinterpretDoubleToIntptr(asDouble()));
 130 snprintf(description, size, "Double: %lx, %lf", reinterpretDoubleToIntptr(asDouble()), asDouble());
131131#else
132132 union {
133133 double asDouble;
134134 uint32_t asTwoInt32s[2];
135135 } u;
136136 u.asDouble = asDouble();
137  snprintf(description, size, "Double: %lf, %08x:%08x", asDouble(), u.asTwoInt32s[1], u.asTwoInt32s[0]);
 137 snprintf(description, size, "Double: %08x:%08x, %lf", u.asTwoInt32s[1], u.asTwoInt32s[0], asDouble());
138138#endif
139139 } else if (isCell())
140140 snprintf(description, size, "Cell: %p", asCell());
107713

Source/JavaScriptCore/runtime/JSVariableObject.h

3838
3939namespace JSC {
4040
 41 class LLIntOffsetsExtractor;
4142 class Register;
4243
4344 class JSVariableObject : public JSNonFinalObject {
4445 friend class JIT;
 46 friend class LLIntOffsetsExtractor;
4547
4648 public:
4749 typedef JSNonFinalObject Base;
107713

Source/JavaScriptCore/runtime/Options.cpp

@@unsigned maximumFunctionForConstructInli
5252
5353unsigned maximumInliningDepth;
5454
 55int32_t executionCounterValueForJITAfterWarmUp;
 56int32_t executionCounterValueForDontJITAnytimeSoon;
 57int32_t executionCounterValueForJITSoon;
 58
5559int32_t executionCounterValueForOptimizeAfterWarmUp;
5660int32_t executionCounterValueForOptimizeAfterLongWarmUp;
5761int32_t executionCounterValueForDontOptimizeAnytimeSoon;

@@void initializeOptions()
137141
138142 SET(maximumInliningDepth, 5);
139143
 144 SET(executionCounterValueForJITAfterWarmUp, -100);
 145 SET(executionCounterValueForDontJITAnytimeSoon, std::numeric_limits<int32_t>::min());
 146 SET(executionCounterValueForJITSoon, -100);
 147
140148 SET(executionCounterValueForOptimizeAfterWarmUp, -1000);
141149 SET(executionCounterValueForOptimizeAfterLongWarmUp, -5000);
142150 SET(executionCounterValueForDontOptimizeAnytimeSoon, std::numeric_limits<int32_t>::min());

@@void initializeOptions()
185193 if (cpusToUse < 1)
186194 cpusToUse = 1;
187195
 196 cpusToUse = 1;
 197
188198 SET(numberOfGCMarkers, cpusToUse);
189199
190200 ASSERT(executionCounterValueForDontOptimizeAnytimeSoon <= executionCounterValueForOptimizeAfterLongWarmUp);
107713

Source/JavaScriptCore/runtime/Options.h

@@extern unsigned maximumFunctionForConstr
3737
3838extern unsigned maximumInliningDepth; // Depth of inline stack, so 1 = no inlining, 2 = one level, etc.
3939
 40extern int32_t executionCounterValueForJITAfterWarmUp;
 41extern int32_t executionCounterValueForDontJITAnytimeSoon;
 42extern int32_t executionCounterValueForJITSoon;
 43
4044extern int32_t executionCounterValueForOptimizeAfterWarmUp;
4145extern int32_t executionCounterValueForOptimizeAfterLongWarmUp;
4246extern int32_t executionCounterValueForDontOptimizeAnytimeSoon;
107713

Source/JavaScriptCore/runtime/ScopeChain.h

@@namespace JSC {
3030 class JSGlobalData;
3131 class JSGlobalObject;
3232 class JSObject;
 33 class LLIntOffsetsExtractor;
3334 class ScopeChainIterator;
3435 class SlotVisitor;
3536

@@namespace JSC {
9192 static JS_EXPORTDATA const ClassInfo s_info;
9293
9394 private:
 95 friend class LLIntOffsetsExtractor;
 96
9497 static const unsigned StructureFlags = OverridesVisitChildren;
9598 };
9699
107713

Source/JavaScriptCore/runtime/Structure.cpp

@@Structure* Structure::addPropertyTransit
322322 transition->growPropertyStorageCapacity();
323323 return transition;
324324 }
325 
 325
326326 Structure* transition = create(globalData, structure);
327327
328328 transition->m_cachedPrototypeChain.setMayBeNull(globalData, transition, structure->m_cachedPrototypeChain.get());
107713

Source/JavaScriptCore/runtime/Structure.h

4545
4646namespace JSC {
4747
 48 class LLIntOffsetsExtractor;
4849 class PropertyNameArray;
4950 class PropertyNameArrayData;
5051 class StructureChain;

@@namespace JSC {
196197 static JS_EXPORTDATA const ClassInfo s_info;
197198
198199 private:
 200 friend class LLIntOffsetsExtractor;
 201
199202 JS_EXPORT_PRIVATE Structure(JSGlobalData&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*);
200203 Structure(JSGlobalData&);
201204 Structure(JSGlobalData&, const Structure*);
107713

Source/JavaScriptCore/runtime/StructureChain.h

3737
3838namespace JSC {
3939
 40 class LLIntOffsetsExtractor;
4041 class Structure;
4142
4243 class StructureChain : public JSCell {

@@namespace JSC {
7475 }
7576
7677 private:
 78 friend class LLIntOffsetsExtractor;
 79
7780 StructureChain(JSGlobalData&, Structure*);
7881 static void destroy(JSCell*);
7982 OwnArrayPtr<WriteBarrier<Structure> > m_vector;
107713

Source/JavaScriptCore/wtf/InlineASM.h

7070#define HIDE_SYMBOL(name)
7171#endif
7272
 73// FIXME: figure out how this works on all the platforms. I know that
 74// on Linux, the preferred form is ".Lstuff" as opposed to "Lstuff".
 75// Don't know about any of the others.
 76#if PLATFORM(MAC)
 77#define LOCAL_LABEL_STRING(name) "L" #name
 78#endif
 79
7380#endif // InlineASM_h
107713

Source/JavaScriptCore/wtf/Platform.h

922922#define ENABLE_JIT 1
923923#endif
924924
 925/* On some of the platforms where we have a JIT, we want to also have the
 926 low-level interpreter. */
 927#if !defined(ENABLE_LLINT) && ENABLE(JIT) && OS(DARWIN) && (CPU(X86) || CPU(ARM_THUMB2)) && USE(JSVALUE32_64)
 928#define ENABLE_LLINT 1
 929#endif
 930
 931/* If we have LLInt enabled and the JIT enabled, we also enable OSRing from
 932 LLInt to the JIT. */
 933#if !defined(ENABLE_LLINT_OSR_TO_JIT) && ENABLE(JIT) && ENABLE(LLINT)
 934#define ENABLE_LLINT_OSR_TO_JIT 1
 935#endif
 936
925937#if !defined(ENABLE_DFG_JIT) && ENABLE(JIT)
926938/* Enable the DFG JIT on X86 and X86_64. Only tested on Mac and GNU/Linux. */
927939#if (CPU(X86) || CPU(X86_64)) && (PLATFORM(MAC) || OS(LINUX))
107713

Source/JavaScriptCore/wtf/SentinelLinkedList.h

@@public:
8686
8787 iterator begin();
8888 iterator end();
 89
 90 bool isEmpty() { return begin() == end(); }
8991
9092private:
9193 RawNode m_headSentinel;
107713

Source/JavaScriptCore/wtf/text/StringImpl.h

@@typedef const struct __CFString * CFStri
4343// Landing the file moves in one patch, will follow on with patches to change the namespaces.
4444namespace JSC {
4545struct IdentifierCStringTranslator;
 46class LLIntOffsetsExtractor;
4647template <typename T> struct IdentifierCharBufferTranslator;
4748struct IdentifierLCharFromUCharTranslator;
4849}

@@class StringImpl {
7273 friend struct WTF::SubstringTranslator;
7374 friend struct WTF::UCharBufferTranslator;
7475 friend class AtomicStringImpl;
75 
 76 friend class JSC::LLIntOffsetsExtractor;
 77
7678private:
7779 enum BufferOwnership {
7880 BufferInternal,
107713

Source/WebCore/CMakeLists.txt

@@SET(WebCore_INCLUDE_DIRECTORIES
7474 "${JAVASCRIPTCORE_DIR}/debugger"
7575 "${JAVASCRIPTCORE_DIR}/interpreter"
7676 "${JAVASCRIPTCORE_DIR}/jit"
 77 "${JAVASCRIPTCORE_DIR}/llint"
7778 "${JAVASCRIPTCORE_DIR}/parser"
7879 "${JAVASCRIPTCORE_DIR}/profiler"
7980 "${JAVASCRIPTCORE_DIR}/runtime"
107713

Source/WebKit/ChangeLog

 12012-01-26 Filip Pizlo <fpizlo@apple.com>
 2
 3 JSC should be a triple-tier VM
 4 https://bugs.webkit.org/show_bug.cgi?id=75812
 5 <rdar://problem/10079694>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 Changed EFL's build system to include a new directory in JavaScriptCore.
 10
 11 * CMakeLists.txt:
 12
1132012-02-13 Nima Ghanavatian <nghanavatian@rim.com>
214
315 Initial upstreaming of selection handling code for BlackBerry port
107713

Source/WebKit/CMakeLists.txt

@@SET(WebKit_INCLUDE_DIRECTORIES
4444 "${JAVASCRIPTCORE_DIR}/debugger"
4545 "${JAVASCRIPTCORE_DIR}/interpreter"
4646 "${JAVASCRIPTCORE_DIR}/jit"
 47 "${JAVASCRIPTCORE_DIR}/llint"
4748 "${JAVASCRIPTCORE_DIR}/parser"
4849 "${JAVASCRIPTCORE_DIR}/profiler"
4950 "${JAVASCRIPTCORE_DIR}/runtime"
107713

Tools/ChangeLog

 12012-01-27 Filip Pizlo <fpizlo@apple.com>
 2
 3 JSC should be a triple-tier VM
 4 https://bugs.webkit.org/show_bug.cgi?id=75812
 5 <rdar://problem/10079694>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 Changed EFL's build system to include a new directory in JavaScriptCore.
 10
 11 * DumpRenderTree/efl/CMakeLists.txt:
 12
1132012-02-14 Jochen Eisinger <jochen@chromium.org>
214
315 [chromium] check that we're not running multiple modal dialogs at the same time
107713

Tools/DumpRenderTree/efl/CMakeLists.txt

@@SET(DumpRenderTree_INCLUDE_DIRECTORIES
7070 ${JAVASCRIPTCORE_DIR}
7171 ${JAVASCRIPTCORE_DIR}/API
7272 ${JAVASCRIPTCORE_DIR}/assembler
 73 ${JAVASCRIPTCORE_DIR}/bytecode
7374 ${JAVASCRIPTCORE_DIR}/dfg
7475 ${JAVASCRIPTCORE_DIR}/heap
7576 ${JAVASCRIPTCORE_DIR}/interpreter
7677 ${JAVASCRIPTCORE_DIR}/jit
 78 ${JAVASCRIPTCORE_DIR}/llint
7779 ${JAVASCRIPTCORE_DIR}/runtime
7880 ${JAVASCRIPTCORE_DIR}/ForwardingHeaders
7981 ${JAVASCRIPTCORE_DIR}/wtf
107713