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-06 Patrick Gansterer <paroga@webkit.org>
2371
3372 Unreviewed WinCE build fix after r106197.
106834

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
9697 interpreter/RegisterFile.cpp
9798
9899 jit/ExecutableAllocator.cpp
 100 jit/HostCallReturnValue.cpp
99101 jit/JITArithmetic32_64.cpp
100102 jit/JITArithmetic.cpp
101103 jit/JITCall32_64.cpp
106834

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 \
106834

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 += \
281283 Source/JavaScriptCore/jit/CompactJITCodeMap.h \
282284 Source/JavaScriptCore/jit/ExecutableAllocator.cpp \
283285 Source/JavaScriptCore/jit/ExecutableAllocator.h \
 286 Source/JavaScriptCore/jit/HostCallReturnValue.cpp \
 287 Source/JavaScriptCore/jit/HostCallReturnValue.h \
284288 Source/JavaScriptCore/jit/JITArithmetic32_64.cpp \
285289 Source/JavaScriptCore/jit/JITArithmetic.cpp \
286290 Source/JavaScriptCore/jit/JITCall32_64.cpp \

@@javascriptcore_sources += \
304308 Source/JavaScriptCore/jit/SpecializedThunkJIT.h \
305309 Source/JavaScriptCore/jit/ThunkGenerators.cpp \
306310 Source/JavaScriptCore/jit/ThunkGenerators.h \
 311 Source/JavaScriptCore/llint/LLIntData.h \
307312 Source/JavaScriptCore/os-win32/stdbool.h \
308313 Source/JavaScriptCore/os-win32/stdint.h \
309314 Source/JavaScriptCore/parser/ASTBuilder.h \

@@javascriptcore_sources += \
354359 Source/JavaScriptCore/runtime/CallData.cpp \
355360 Source/JavaScriptCore/runtime/CallData.h \
356361 Source/JavaScriptCore/runtime/ClassInfo.h \
 362 Source/JavaScriptCore/runtime/CodeSpecializationKind.h \
357363 Source/JavaScriptCore/runtime/CommonIdentifiers.cpp \
358364 Source/JavaScriptCore/runtime/CommonIdentifiers.h \
359365 Source/JavaScriptCore/runtime/CommonSlowPaths.h \

@@javascriptcore_sources += \
382388 Source/JavaScriptCore/runtime/ExceptionHelpers.h \
383389 Source/JavaScriptCore/runtime/Executable.cpp \
384390 Source/JavaScriptCore/runtime/Executable.h \
 391 Source/JavaScriptCore/runtime/ExecutionHarness.h \
385392 Source/JavaScriptCore/runtime/FunctionConstructor.cpp \
386393 Source/JavaScriptCore/runtime/FunctionConstructor.h \
387394 Source/JavaScriptCore/runtime/FunctionPrototype.cpp \
106834

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 \
106834

Source/JavaScriptCore/Target.pri

@@SOURCES += \
107107 interpreter/RegisterFile.cpp \
108108 jit/ExecutableAllocatorFixedVMPool.cpp \
109109 jit/ExecutableAllocator.cpp \
 110 jit/HostCallReturnValue.cpp \
110111 jit/JITArithmetic.cpp \
111112 jit/JITArithmetic32_64.cpp \
112113 jit/JITCall.cpp \
106834

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

17581758 >
17591759 </File>
17601760 <File
 1761 RelativePath="..\..\jit\HostCallReturnValue.cpp"
 1762 >
 1763 </File>
 1764 <File
17611765 RelativePath="..\..\jit\JIT.cpp"
17621766 >
17631767 </File>

18431847 </File>
18441848 </Filter>
18451849 <Filter
 1850 Name="llint"
 1851 >
 1852 <File
 1853 RelativePath="..\..\llint\LLIntData.h"
 1854 >
 1855 </File>
 1856 </Filter>
 1857 <Filter
18461858 Name="interpreter"
18471859 >
18481860 <File
106834

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 />
106834

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
106834

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, ); }; };

389422 86B99AE3117E578100DF5A90 /* StringBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86B99AE1117E578100DF5A90 /* StringBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
390423 86BB09C0138E381B0056702F /* DFGRepatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86BB09BE138E381B0056702F /* DFGRepatch.cpp */; };
391424 86BB09C1138E381B0056702F /* DFGRepatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 86BB09BF138E381B0056702F /* DFGRepatch.h */; };
392  86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */; };
 425 86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
393426 86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86C568DD11A213EE0007F7F0 /* MacroAssemblerARM.cpp */; };
394427 86C568E111A213EE0007F7F0 /* MacroAssemblerMIPS.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C568DE11A213EE0007F7F0 /* MacroAssemblerMIPS.h */; };
395428 86C568E211A213EE0007F7F0 /* MIPSAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C568DF11A213EE0007F7F0 /* MIPSAssembler.h */; };

758791/* End PBXBuildFile section */
759792
760793/* Begin PBXContainerItemProxy section */
 794 0F4680B114BA811500BFE272 /* PBXContainerItemProxy */ = {
 795 isa = PBXContainerItemProxy;
 796 containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
 797 proxyType = 1;
 798 remoteGlobalIDString = 0F4680A914BA7FD900BFE272;
 799 remoteInfo = "LLInt Offsets";
 800 };
 801 0F4680B314BA821400BFE272 /* PBXContainerItemProxy */ = {
 802 isa = PBXContainerItemProxy;
 803 containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
 804 proxyType = 1;
 805 remoteGlobalIDString = 0F46808E14BA7E5E00BFE272;
 806 remoteInfo = JSCLLIntOffsetsExtractor;
 807 };
761808 141214BE0A49190E00480255 /* PBXContainerItemProxy */ = {
762809 isa = PBXContainerItemProxy;
763810 containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;

803850/* End PBXContainerItemProxy section */
804851
805852/* Begin PBXCopyFilesBuildPhase section */
 853 0F46808D14BA7E5E00BFE272 /* CopyFiles */ = {
 854 isa = PBXCopyFilesBuildPhase;
 855 buildActionMask = 2147483647;
 856 dstPath = /usr/share/man/man1/;
 857 dstSubfolderSpec = 0;
 858 files = (
 859 );
 860 runOnlyForDeploymentPostprocessing = 1;
 861 };
806862 5DBB1511131D0B130056AD36 /* Copy Support Script */ = {
807863 isa = PBXCopyFilesBuildPhase;
808864 buildActionMask = 12;

843899 0BAC949E1338728400CF135B /* ThreadRestrictionVerifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadRestrictionVerifier.h; sourceTree = "<group>"; };
844900 0BCD83541485841200EA2003 /* TemporaryChange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemporaryChange.h; sourceTree = "<group>"; };
845901 0BF28A2811A33DC300638F84 /* SizeLimits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SizeLimits.cpp; sourceTree = "<group>"; };
 902 0F0B839514BCF45A00885B4F /* LLIntEntrypoints.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntEntrypoints.cpp; path = llint/LLIntEntrypoints.cpp; sourceTree = "<group>"; };
 903 0F0B839614BCF45A00885B4F /* LLIntEntrypoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntEntrypoints.h; path = llint/LLIntEntrypoints.h; sourceTree = "<group>"; };
 904 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; };
 905 0F0B839814BCF45A00885B4F /* LLIntThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntThunks.h; path = llint/LLIntThunks.h; sourceTree = "<group>"; };
846906 0F0B83A514BCF50400885B4F /* CodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeType.h; sourceTree = "<group>"; };
847907 0F0B83A814BCF55E00885B4F /* HandlerInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HandlerInfo.h; sourceTree = "<group>"; };
848908 0F0B83AA14BCF5B900885B4F /* ExpressionRangeInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExpressionRangeInfo.h; sourceTree = "<group>"; };

853913 0F0B83B314BCF85E00885B4F /* MethodCallLinkInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MethodCallLinkInfo.h; sourceTree = "<group>"; };
854914 0F0B83B614BCF8DF00885B4F /* GlobalResolveInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GlobalResolveInfo.h; sourceTree = "<group>"; };
855915 0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallReturnOffsetToBytecodeOffset.h; sourceTree = "<group>"; };
 916 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLIntCallLinkInfo.h; sourceTree = "<group>"; };
856917 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonSlowPaths.h; sourceTree = "<group>"; };
857918 0F16D724142C39A200CF784A /* BitVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BitVector.cpp; sourceTree = "<group>"; };
858919 0F21C26614BE5F5E00ADC64B /* JITDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITDriver.h; sourceTree = "<group>"; };
 920 0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeSpecializationKind.h; sourceTree = "<group>"; };
 921 0F21C27A14BE727300ADC64B /* ExecutionHarness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutionHarness.h; sourceTree = "<group>"; };
 922 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeConventions.h; sourceTree = "<group>"; };
859923 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakReferenceHarvester.h; sourceTree = "<group>"; };
860924 0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DFGCodeBlocks.cpp; sourceTree = "<group>"; };
861925 0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFGCodeBlocks.h; sourceTree = "<group>"; };

866930 0F431736146BAC65007E3890 /* ListableHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ListableHandler.h; sourceTree = "<group>"; };
867931 0F46807F14BA572700BFE272 /* JITExceptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITExceptions.cpp; sourceTree = "<group>"; };
868932 0F46808014BA572700BFE272 /* JITExceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITExceptions.h; sourceTree = "<group>"; };
 933 0F46808F14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; };
 934 0F46809D14BA7F8200BFE272 /* LLIntExceptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntExceptions.cpp; path = llint/LLIntExceptions.cpp; sourceTree = "<group>"; };
 935 0F46809E14BA7F8200BFE272 /* LLIntExceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntExceptions.h; path = llint/LLIntExceptions.h; sourceTree = "<group>"; };
 936 0F46809F14BA7F8200BFE272 /* LLIntHelpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntHelpers.cpp; path = llint/LLIntHelpers.cpp; sourceTree = "<group>"; };
 937 0F4680A014BA7F8200BFE272 /* LLIntHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntHelpers.h; path = llint/LLIntHelpers.h; sourceTree = "<group>"; };
 938 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntOffsetsExtractor.cpp; path = llint/LLIntOffsetsExtractor.cpp; sourceTree = "<group>"; };
 939 0F4680C514BBB16900BFE272 /* LLIntCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntCommon.h; path = llint/LLIntCommon.h; sourceTree = "<group>"; };
 940 0F4680C614BBB16900BFE272 /* LLIntOfflineAsmConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntOfflineAsmConfig.h; path = llint/LLIntOfflineAsmConfig.h; sourceTree = "<group>"; };
 941 0F4680C714BBB16900BFE272 /* LowLevelInterpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LowLevelInterpreter.cpp; path = llint/LowLevelInterpreter.cpp; sourceTree = "<group>"; };
 942 0F4680C814BBB16900BFE272 /* LowLevelInterpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LowLevelInterpreter.h; path = llint/LowLevelInterpreter.h; sourceTree = "<group>"; };
 943 0F4680CE14BBB3D100BFE272 /* LLIntData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntData.cpp; path = llint/LLIntData.cpp; sourceTree = "<group>"; };
 944 0F4680CF14BBB3D100BFE272 /* LLIntData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntData.h; path = llint/LLIntData.h; sourceTree = "<group>"; };
 945 0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HostCallReturnValue.cpp; sourceTree = "<group>"; };
 946 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HostCallReturnValue.h; sourceTree = "<group>"; };
869947 0F55F0F114D1063600AC7649 /* AbstractPC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AbstractPC.cpp; sourceTree = "<group>"; };
870948 0F55F0F214D1063600AC7649 /* AbstractPC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbstractPC.h; sourceTree = "<group>"; };
871949 0F5F08CC146BE602000472A9 /* DFGByteCodeCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGByteCodeCache.h; path = dfg/DFGByteCodeCache.h; sourceTree = "<group>"; };

15921670/* End PBXFileReference section */
15931671
15941672/* Begin PBXFrameworksBuildPhase section */
 1673 0F46808C14BA7E5E00BFE272 /* Frameworks */ = {
 1674 isa = PBXFrameworksBuildPhase;
 1675 buildActionMask = 2147483647;
 1676 files = (
 1677 );
 1678 runOnlyForDeploymentPostprocessing = 0;
 1679 };
15951680 1412111E0A48793C00480255 /* Frameworks */ = {
15961681 isa = PBXFrameworksBuildPhase;
15971682 buildActionMask = 2147483647;

16501735 141211200A48793C00480255 /* minidom */,
16511736 14BD59BF0A3E8F9000BAF59C /* testapi */,
16521737 6511230514046A4C002B101D /* testRegExp */,
 1738 0F46808F14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */,
16531739 );
16541740 name = Products;
16551741 sourceTree = "<group>";

16771763 F5C290E60284F98E018635CA /* JavaScriptCorePrefix.h */,
16781764 45E12D8806A49B0F00E9DF84 /* jsc.cpp */,
16791765 F68EBB8C0255D4C601FF60F7 /* config.h */,
 1766 0F46809C14BA7F4D00BFE272 /* llint */,
16801767 1432EBD70A34CAD400717B9F /* API */,
16811768 9688CB120ED12B4E001D649F /* assembler */,
16821769 969A078F0ED1D3AE00F1F681 /* bytecode */,

17161803 tabWidth = 4;
17171804 usesTabs = 0;
17181805 };
 1806 0F46809C14BA7F4D00BFE272 /* llint */ = {
 1807 isa = PBXGroup;
 1808 children = (
 1809 0F0B839514BCF45A00885B4F /* LLIntEntrypoints.cpp */,
 1810 0F0B839614BCF45A00885B4F /* LLIntEntrypoints.h */,
 1811 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */,
 1812 0F0B839814BCF45A00885B4F /* LLIntThunks.h */,
 1813 0F4680CE14BBB3D100BFE272 /* LLIntData.cpp */,
 1814 0F4680CF14BBB3D100BFE272 /* LLIntData.h */,
 1815 0F4680C514BBB16900BFE272 /* LLIntCommon.h */,
 1816 0F4680C614BBB16900BFE272 /* LLIntOfflineAsmConfig.h */,
 1817 0F4680C714BBB16900BFE272 /* LowLevelInterpreter.cpp */,
 1818 0F4680C814BBB16900BFE272 /* LowLevelInterpreter.h */,
 1819 0F46809D14BA7F8200BFE272 /* LLIntExceptions.cpp */,
 1820 0F46809E14BA7F8200BFE272 /* LLIntExceptions.h */,
 1821 0F46809F14BA7F8200BFE272 /* LLIntHelpers.cpp */,
 1822 0F4680A014BA7F8200BFE272 /* LLIntHelpers.h */,
 1823 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */,
 1824 );
 1825 name = llint;
 1826 sourceTree = "<group>";
 1827 };
17191828 141211000A48772600480255 /* tests */ = {
17201829 isa = PBXGroup;
17211830 children = (

17501859 1429D92C0ED22D7000B89619 /* jit */ = {
17511860 isa = PBXGroup;
17521861 children = (
 1862 0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */,
 1863 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */,
17531864 0F46807F14BA572700BFE272 /* JITExceptions.cpp */,
17541865 0F46808014BA572700BFE272 /* JITExceptions.h */,
17551866 0FD82E37141AB14200179C94 /* CompactJITCodeMap.h */,

21792290 7EF6E0BB0EB7A1EC0079AFAF /* runtime */ = {
21802291 isa = PBXGroup;
21812292 children = (
 2293 0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */,
 2294 0F21C27A14BE727300ADC64B /* ExecutionHarness.h */,
21822295 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */,
21832296 BCF605110E203EF800B9A64D /* ArgList.cpp */,
21842297 BCF605120E203EF800B9A64D /* ArgList.h */,

25532666 969A078F0ED1D3AE00F1F681 /* bytecode */ = {
25542667 isa = PBXGroup;
25552668 children = (
 2669 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */,
 2670 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */,
25562671 0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */,
25572672 0F93329414CA7DC10085F3C6 /* CallLinkStatus.h */,
25582673 0F93329514CA7DC10085F3C6 /* GetByIdStatus.cpp */,

31043219 86704B8A12DBA33700A9FE7B /* YarrPattern.h in Headers */,
31053220 86704B4312DB8A8100A9FE7B /* YarrSyntaxChecker.h in Headers */,
31063221 0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */,
 3222 0F4680A314BA7F8D00BFE272 /* LLIntExceptions.h in Headers */,
 3223 0F4680A514BA7F8D00BFE272 /* LLIntHelpers.h in Headers */,
31073224 0F46808214BA572D00BFE272 /* JITExceptions.h in Headers */,
 3225 0F4680CA14BBB16C00BFE272 /* LLIntCommon.h in Headers */,
 3226 0F4680CB14BBB17200BFE272 /* LLIntOfflineAsmConfig.h in Headers */,
 3227 0F4680CD14BBB17D00BFE272 /* LowLevelInterpreter.h in Headers */,
 3228 0F4680D314BBD16700BFE272 /* LLIntData.h in Headers */,
 3229 0F4680D514BBD24B00BFE272 /* HostCallReturnValue.h in Headers */,
 3230 0F0B839B14BCF46000885B4F /* LLIntEntrypoints.h in Headers */,
 3231 0F0B839D14BCF46600885B4F /* LLIntThunks.h in Headers */,
31083232 0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
31093233 0F0B83A914BCF56200885B4F /* HandlerInfo.h in Headers */,
31103234 0F0B83AB14BCF5BB00885B4F /* ExpressionRangeInfo.h in Headers */,

31133237 0F0B83B514BCF86200885B4F /* MethodCallLinkInfo.h in Headers */,
31143238 0F0B83B714BCF8E100885B4F /* GlobalResolveInfo.h in Headers */,
31153239 0F0B83B914BCF95F00885B4F /* CallReturnOffsetToBytecodeOffset.h in Headers */,
 3240 0F0FC45A14BD15F500B81154 /* LLIntCallLinkInfo.h in Headers */,
31163241 0F21C26814BE5F6800ADC64B /* JITDriver.h in Headers */,
 3242 0F21C27C14BE727600ADC64B /* ExecutionHarness.h in Headers */,
 3243 0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
 3244 0F21C27F14BEAA8200ADC64B /* BytecodeConventions.h in Headers */,
31173245 0F7B294A14C3CD29007C3DB1 /* DFGCCallHelpers.h in Headers */,
31183246 0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */,
31193247 0F7B294C14C3CD43007C3DB1 /* DFGByteCodeCache.h in Headers */,

31343262/* End PBXHeadersBuildPhase section */
31353263
31363264/* Begin PBXNativeTarget section */
 3265 0F46808E14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */ = {
 3266 isa = PBXNativeTarget;
 3267 buildConfigurationList = 0F46809A14BA7E5F00BFE272 /* Build configuration list for PBXNativeTarget "JSCLLIntOffsetsExtractor" */;
 3268 buildPhases = (
 3269 0F46808B14BA7E5E00BFE272 /* Sources */,
 3270 0F46808C14BA7E5E00BFE272 /* Frameworks */,
 3271 0F46808D14BA7E5E00BFE272 /* CopyFiles */,
 3272 );
 3273 buildRules = (
 3274 );
 3275 dependencies = (
 3276 0F4680B214BA811500BFE272 /* PBXTargetDependency */,
 3277 );
 3278 name = JSCLLIntOffsetsExtractor;
 3279 productName = JSCLLIntOffsetsExtractor;
 3280 productReference = 0F46808F14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */;
 3281 productType = "com.apple.product-type.tool";
 3282 };
31373283 1412111F0A48793C00480255 /* minidom */ = {
31383284 isa = PBXNativeTarget;
31393285 buildConfigurationList = 141211390A48798400480255 /* Build configuration list for PBXNativeTarget "minidom" */;

32603406 14BD59BE0A3E8F9000BAF59C /* testapi */,
32613407 932F5BDA0822A1C700736975 /* jsc */,
32623408 651122F714046A4C002B101D /* testRegExp */,
 3409 0F46808E14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */,
 3410 0F4680A914BA7FD900BFE272 /* LLInt Offsets */,
32633411 );
32643412 };
32653413/* End PBXProject section */
32663414
32673415/* Begin PBXShellScriptBuildPhase section */
 3416 0F4680AA14BA7FD900BFE272 /* Generate Derived Sources */ = {
 3417 isa = PBXShellScriptBuildPhase;
 3418 buildActionMask = 2147483647;
 3419 files = (
 3420 );
 3421 inputPaths = (
 3422 "$(SRCROOT)/llint/LowLevelAssembler.asm",
 3423 );
 3424 name = "Generate Derived Sources";
 3425 outputPaths = (
 3426 "$(BUILT_PRODUCTS_DIR)/LLIntOffsets/LLIntDesiredOffsets.h",
 3427 );
 3428 runOnlyForDeploymentPostprocessing = 0;
 3429 shellPath = /bin/sh;
 3430 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";
 3431 };
32683432 3713F014142905240036387F /* Check For Inappropriate Objective-C Class Names */ = {
32693433 isa = PBXShellScriptBuildPhase;
32703434 buildActionMask = 2147483647;

33703534 );
33713535 runOnlyForDeploymentPostprocessing = 0;
33723536 shellPath = /bin/sh;
3373  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";
 3537 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";
33743538 };
33753539 9319586B09D9F91A00A56FD4 /* Check For Global Initializers */ = {
33763540 isa = PBXShellScriptBuildPhase;

34053569/* End PBXShellScriptBuildPhase section */
34063570
34073571/* Begin PBXSourcesBuildPhase section */
 3572 0F46808B14BA7E5E00BFE272 /* Sources */ = {
 3573 isa = PBXSourcesBuildPhase;
 3574 buildActionMask = 2147483647;
 3575 files = (
 3576 0F4680A714BA7FA100BFE272 /* LLIntOffsetsExtractor.cpp in Sources */,
 3577 );
 3578 runOnlyForDeploymentPostprocessing = 0;
 3579 };
34083580 1412111D0A48793C00480255 /* Sources */ = {
34093581 isa = PBXSourcesBuildPhase;
34103582 buildActionMask = 2147483647;

36623834 86704B8612DBA33700A9FE7B /* YarrJIT.cpp in Sources */,
36633835 86704B8912DBA33700A9FE7B /* YarrPattern.cpp in Sources */,
36643836 86704B4212DB8A8100A9FE7B /* YarrSyntaxChecker.cpp in Sources */,
 3837 0F4680A414BA7F8D00BFE272 /* LLIntHelpers.cpp in Sources */,
 3838 0F4680A814BA7FAB00BFE272 /* LLIntExceptions.cpp in Sources */,
36653839 0F46808314BA573100BFE272 /* JITExceptions.cpp in Sources */,
 3840 0F4680CC14BBB17A00BFE272 /* LowLevelInterpreter.cpp in Sources */,
 3841 0F4680D214BBD16500BFE272 /* LLIntData.cpp in Sources */,
 3842 0F4680D414BBD24900BFE272 /* HostCallReturnValue.cpp in Sources */,
 3843 0F0B839A14BCF45D00885B4F /* LLIntEntrypoints.cpp in Sources */,
 3844 0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */,
36663845 0F0B83B014BCF71600885B4F /* CallLinkInfo.cpp in Sources */,
36673846 0F0B83B414BCF86000885B4F /* MethodCallLinkInfo.cpp in Sources */,
36683847 F69E86C314C6E551002C2C62 /* NumberOfCores.cpp in Sources */,

36883867/* End PBXSourcesBuildPhase section */
36893868
36903869/* Begin PBXTargetDependency section */
 3870 0F4680B214BA811500BFE272 /* PBXTargetDependency */ = {
 3871 isa = PBXTargetDependency;
 3872 target = 0F4680A914BA7FD900BFE272 /* LLInt Offsets */;
 3873 targetProxy = 0F4680B114BA811500BFE272 /* PBXContainerItemProxy */;
 3874 };
 3875 0F4680B414BA821400BFE272 /* PBXTargetDependency */ = {
 3876 isa = PBXTargetDependency;
 3877 target = 0F46808E14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */;
 3878 targetProxy = 0F4680B314BA821400BFE272 /* PBXContainerItemProxy */;
 3879 };
36913880 141214BF0A49190E00480255 /* PBXTargetDependency */ = {
36923881 isa = PBXTargetDependency;
36933882 target = 1412111F0A48793C00480255 /* minidom */;

37213910/* End PBXTargetDependency section */
37223911
37233912/* Begin XCBuildConfiguration section */
 3913 0F46809614BA7E5E00BFE272 /* Debug */ = {
 3914 isa = XCBuildConfiguration;
 3915 buildSettings = {
 3916 ALWAYS_SEARCH_USER_PATHS = NO;
 3917 ARCHS = "$(ARCHS_STANDARD_64_BIT)";
 3918 COPY_PHASE_STRIP = NO;
 3919 GCC_C_LANGUAGE_STANDARD = gnu99;
 3920 GCC_DYNAMIC_NO_PIC = NO;
 3921 GCC_ENABLE_OBJC_EXCEPTIONS = YES;
 3922 GCC_OPTIMIZATION_LEVEL = 0;
 3923 GCC_PREPROCESSOR_DEFINITIONS = (
 3924 "DEBUG=1",
 3925 "$(inherited)",
 3926 );
 3927 GCC_SYMBOLS_PRIVATE_EXTERN = NO;
 3928 GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
 3929 GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
 3930 GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
 3931 GCC_WARN_ABOUT_RETURN_TYPE = YES;
 3932 GCC_WARN_UNUSED_VARIABLE = YES;
 3933 "HEADER_SEARCH_PATHS[arch=*]" = (
 3934 .,
 3935 icu,
 3936 "$(BUILT_PRODUCTS_DIR)/LLIntOffsets",
 3937 "$(HEADER_SEARCH_PATHS)",
 3938 );
 3939 MACOSX_DEPLOYMENT_TARGET = 10.7;
 3940 ONLY_ACTIVE_ARCH = NO;
 3941 PRODUCT_NAME = "$(TARGET_NAME)";
 3942 SDKROOT = macosx;
 3943 USER_HEADER_SEARCH_PATHS = ". icu $(BUILT_PRODUCTS_DIR)/LLIntOffsets $(HEADER_SEARCH_PATHS)";
 3944 };
 3945 name = Debug;
 3946 };
 3947 0F46809714BA7E5E00BFE272 /* Release */ = {
 3948 isa = XCBuildConfiguration;
 3949 buildSettings = {
 3950 ALWAYS_SEARCH_USER_PATHS = NO;
 3951 ARCHS = "$(ARCHS_STANDARD_64_BIT)";
 3952 COPY_PHASE_STRIP = YES;
 3953 DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 3954 GCC_C_LANGUAGE_STANDARD = gnu99;
 3955 GCC_ENABLE_OBJC_EXCEPTIONS = YES;
 3956 GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
 3957 GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
 3958 GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
 3959 GCC_WARN_ABOUT_RETURN_TYPE = YES;
 3960 GCC_WARN_UNUSED_VARIABLE = YES;
 3961 "HEADER_SEARCH_PATHS[arch=*]" = (
 3962 .,
 3963 icu,
 3964 "$(BUILT_PRODUCTS_DIR)/LLIntOffsets$(HEADER_SEARCH_PATHS)",
 3965 );
 3966 MACOSX_DEPLOYMENT_TARGET = 10.7;
 3967 ONLY_ACTIVE_ARCH = NO;
 3968 PRODUCT_NAME = "$(TARGET_NAME)";
 3969 SDKROOT = macosx;
 3970 USER_HEADER_SEARCH_PATHS = ". icu $(BUILT_PRODUCTS_DIR)/LLIntOffsets $(HEADER_SEARCH_PATHS)";
 3971 };
 3972 name = Release;
 3973 };
 3974 0F46809814BA7E5E00BFE272 /* Profiling */ = {
 3975 isa = XCBuildConfiguration;
 3976 buildSettings = {
 3977 ALWAYS_SEARCH_USER_PATHS = NO;
 3978 ARCHS = "$(ARCHS_STANDARD_64_BIT)";
 3979 COPY_PHASE_STRIP = YES;
 3980 DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 3981 GCC_C_LANGUAGE_STANDARD = gnu99;
 3982 GCC_ENABLE_OBJC_EXCEPTIONS = YES;
 3983 GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
 3984 GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
 3985 GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
 3986 GCC_WARN_ABOUT_RETURN_TYPE = YES;
 3987 GCC_WARN_UNUSED_VARIABLE = YES;
 3988 "HEADER_SEARCH_PATHS[arch=*]" = (
 3989 .,
 3990 icu,
 3991 "$(BUILT_PRODUCTS_DIR)/LLIntOffsets",
 3992 "$(HEADER_SEARCH_PATHS)",
 3993 );
 3994 MACOSX_DEPLOYMENT_TARGET = 10.7;
 3995 ONLY_ACTIVE_ARCH = NO;
 3996 PRODUCT_NAME = "$(TARGET_NAME)";
 3997 SDKROOT = macosx;
 3998 USER_HEADER_SEARCH_PATHS = ". icu $(BUILT_PRODUCTS_DIR)/LLIntOffsets $(HEADER_SEARCH_PATHS)";
 3999 };
 4000 name = Profiling;
 4001 };
 4002 0F46809914BA7E5E00BFE272 /* Production */ = {
 4003 isa = XCBuildConfiguration;
 4004 buildSettings = {
 4005 ALWAYS_SEARCH_USER_PATHS = NO;
 4006 ARCHS = "$(ARCHS_STANDARD_64_BIT)";
 4007 COPY_PHASE_STRIP = YES;
 4008 DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 4009 GCC_C_LANGUAGE_STANDARD = gnu99;
 4010 GCC_ENABLE_OBJC_EXCEPTIONS = YES;
 4011 GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
 4012 GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
 4013 GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
 4014 GCC_WARN_ABOUT_RETURN_TYPE = YES;
 4015 GCC_WARN_UNUSED_VARIABLE = YES;
 4016 "HEADER_SEARCH_PATHS[arch=*]" = (
 4017 .,
 4018 icu,
 4019 "$(BUILT_PRODUCTS_DIR)/LLIntOffsets",
 4020 "$(HEADER_SEARCH_PATHS)",
 4021 );
 4022 MACOSX_DEPLOYMENT_TARGET = 10.7;
 4023 PRODUCT_NAME = "$(TARGET_NAME)";
 4024 SDKROOT = macosx;
 4025 USER_HEADER_SEARCH_PATHS = ". icu $(BUILT_PRODUCTS_DIR)/LLIntOffsets $(HEADER_SEARCH_PATHS)";
 4026 };
 4027 name = Production;
 4028 };
 4029 0F4680AD14BA7FD900BFE272 /* Debug */ = {
 4030 isa = XCBuildConfiguration;
 4031 buildSettings = {
 4032 PRODUCT_NAME = "Derived Sources copy";
 4033 };
 4034 name = Debug;
 4035 };
 4036 0F4680AE14BA7FD900BFE272 /* Release */ = {
 4037 isa = XCBuildConfiguration;
 4038 buildSettings = {
 4039 PRODUCT_NAME = "Derived Sources copy";
 4040 };
 4041 name = Release;
 4042 };
 4043 0F4680AF14BA7FD900BFE272 /* Profiling */ = {
 4044 isa = XCBuildConfiguration;
 4045 buildSettings = {
 4046 PRODUCT_NAME = "Derived Sources copy";
 4047 };
 4048 name = Profiling;
 4049 };
 4050 0F4680B014BA7FD900BFE272 /* Production */ = {
 4051 isa = XCBuildConfiguration;
 4052 buildSettings = {
 4053 PRODUCT_NAME = "Derived Sources copy";
 4054 };
 4055 name = Production;
 4056 };
37244057 1412113A0A48798400480255 /* Debug */ = {
37254058 isa = XCBuildConfiguration;
37264059 buildSettings = {

39624295/* End XCBuildConfiguration section */
39634296
39644297/* Begin XCConfigurationList section */
 4298 0F46809A14BA7E5F00BFE272 /* Build configuration list for PBXNativeTarget "JSCLLIntOffsetsExtractor" */ = {
 4299 isa = XCConfigurationList;
 4300 buildConfigurations = (
 4301 0F46809614BA7E5E00BFE272 /* Debug */,
 4302 0F46809714BA7E5E00BFE272 /* Release */,
 4303 0F46809814BA7E5E00BFE272 /* Profiling */,
 4304 0F46809914BA7E5E00BFE272 /* Production */,
 4305 );
 4306 defaultConfigurationIsVisible = 0;
 4307 defaultConfigurationName = Production;
 4308 };
 4309 0F4680AC14BA7FD900BFE272 /* Build configuration list for PBXAggregateTarget "LLInt Offsets" */ = {
 4310 isa = XCConfigurationList;
 4311 buildConfigurations = (
 4312 0F4680AD14BA7FD900BFE272 /* Debug */,
 4313 0F4680AE14BA7FD900BFE272 /* Release */,
 4314 0F4680AF14BA7FD900BFE272 /* Profiling */,
 4315 0F4680B014BA7FD900BFE272 /* Production */,
 4316 );
 4317 defaultConfigurationIsVisible = 0;
 4318 defaultConfigurationName = Production;
 4319 };
39654320 141211390A48798400480255 /* Build configuration list for PBXNativeTarget "minidom" */ = {
39664321 isa = XCConfigurationList;
39674322 buildConfigurations = (
106834

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/Noncopyable.h>
3939
4040namespace JSC {
106834

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())
106834

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
106834

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};
106834

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  printf("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n",
 360 printf("%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 printf("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 printf("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 printf("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 printf("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  printf("Clearing call from %p.\n", this);
 1833 printf("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)
106834

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
106834

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
106834

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
106834

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:
106834

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)
106834

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
106834

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(
106834

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;
106834

Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

3434#include "BatchedTransitionOptimizer.h"
3535#include "JSFunction.h"
3636#include "Interpreter.h"
 37#include "LowLevelInterpreter.h"
3738#include "ScopeChain.h"
3839#include "StrongInlines.h"
3940#include "UString.h"

@@RegisterID* BytecodeGenerator::emitResol
12931294#if ENABLE(JIT)
12941295 m_codeBlock->addGlobalResolveInfo(instructions().size());
12951296#endif
1296 #if ENABLE(INTERPRETER)
12971297 m_codeBlock->addGlobalResolveInstruction(instructions().size());
1298 #endif
12991298 bool dynamic = resolveResult.isDynamic() && resolveResult.depth();
13001299 ValueProfile* profile = emitProfiledOpcode(dynamic ? op_resolve_global_dynamic : op_resolve_global);
13011300 instructions().append(dst->index());

@@RegisterID* BytecodeGenerator::emitResol
13991398 return baseDst;
14001399 }
14011400
1402 
1403 
1404 
14051401 ValueProfile* profile = emitProfiledOpcode(op_resolve_with_base);
14061402 instructions().append(baseDst->index());
14071403 instructions().append(propDst->index());

@@void BytecodeGenerator::emitMethodCheck(
15091505
15101506RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
15111507{
1512 #if ENABLE(INTERPRETER)
15131508 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1514 #endif
15151509
15161510 ValueProfile* profile = emitProfiledOpcode(op_get_by_id);
15171511 instructions().append(dst->index());

@@RegisterID* BytecodeGenerator::emitGetAr
15371531
15381532RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
15391533{
1540 #if ENABLE(INTERPRETER)
15411534 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1542 #endif
15431535
15441536 emitOpcode(op_put_by_id);
15451537 instructions().append(base->index());

@@RegisterID* BytecodeGenerator::emitPutBy
15551547
15561548RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value)
15571549{
1558 #if ENABLE(INTERPRETER)
15591550 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1560 #endif
15611551
15621552 emitOpcode(op_put_by_id);
15631553 instructions().append(base->index());

@@RegisterID* BytecodeGenerator::emitCall(
18381828 instructions().append(func->index()); // func
18391829 instructions().append(callArguments.argumentCountIncludingThis()); // argCount
18401830 instructions().append(callArguments.registerOffset()); // registerOffset
 1831#if ENABLE(LLINT)
 1832 instructions().append(m_codeBlock->addLLIntCallLinkInfo());
 1833#else
18411834 instructions().append(0);
 1835#endif
18421836 instructions().append(0);
18431837 if (dst != ignoredResult()) {
18441838 ValueProfile* profile = emitProfiledOpcode(op_call_put_result);

@@RegisterID* BytecodeGenerator::emitConst
19421936 instructions().append(func->index()); // func
19431937 instructions().append(callArguments.argumentCountIncludingThis()); // argCount
19441938 instructions().append(callArguments.registerOffset()); // registerOffset
 1939#if ENABLE(LLINT)
 1940 instructions().append(m_codeBlock->addLLIntCallLinkInfo());
 1941#else
19451942 instructions().append(0);
 1943#endif
19461944 instructions().append(0);
19471945 if (dst != ignoredResult()) {
19481946 ValueProfile* profile = emitProfiledOpcode(op_call_put_result);

@@RegisterID* BytecodeGenerator::emitCatch
22032201{
22042202 m_usesExceptions = true;
22052203#if ENABLE(JIT)
 2204#if ENABLE(LLINT)
 2205 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))) };
 2206#else
22062207 HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel() };
 2208#endif
22072209#else
22082210 HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth };
22092211#endif
106834

Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

@@private:
606606 {
607607 UNUSED_PARAM(nodeIndex);
608608
609  ValueProfile* profile = m_inlineStackTop->m_profiledBlock->valueProfileForBytecodeOffset(bytecodeIndex);
610  ASSERT(profile);
611  PredictedType prediction = profile->computeUpdatedPrediction();
 609 PredictedType prediction = m_inlineStackTop->m_profiledBlock->valueProfilePredictionForBytecodeOffset(bytecodeIndex);
612610#if DFG_ENABLE(DEBUG_VERBOSE)
613611 printf("Dynamic [@%u, bc#%u] prediction: %s\n", nodeIndex, bytecodeIndex, predictionToString(prediction));
614612#endif

@@bool ByteCodeParser::handleInlining(bool
10431041
10441042 // If we get here then it looks like we should definitely inline this code. Proceed
10451043 // with parsing the code to get bytecode, so that we can then parse the bytecode.
 1044 // Note that if LLInt is enabled, the bytecode will always be available. Also note
 1045 // that if LLInt is enabled, we may inline a code block that has never been JITted
 1046 // before!
10461047 CodeBlock* codeBlock = m_codeBlockCache.get(CodeBlockKey(executable, kind), expectedFunction->scope());
10471048 if (!codeBlock)
10481049 return false;

@@bool ByteCodeParser::parseBlock(unsigned
17431744 m_inlineStackTop->m_profiledBlock, m_currentIndex);
17441745
17451746 if (methodCallStatus.isSet()
1746  && !getByIdStatus.isSet()
 1747 && !getByIdStatus.wasSeenInJIT()
17471748 && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
17481749 // It's monomorphic as far as we can tell, since the method_check was linked
17491750 // but the slow path (i.e. the normal get_by_id) never fired.

@@bool ByteCodeParser::parseBlock(unsigned
18121813
18131814 NEXT_OPCODE(op_get_by_id);
18141815 }
1815  case op_put_by_id: {
 1816 case op_put_by_id:
 1817 case op_put_by_id_transition_direct:
 1818 case op_put_by_id_transition_normal: {
18161819 NodeIndex value = get(currentInstruction[3].u.operand);
18171820 NodeIndex base = get(currentInstruction[1].u.operand);
18181821 unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
106834

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:
106834

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);
106834

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
673674 return JSValue::strictEqual(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
674675}
675676
676 EncodedJSValue DFG_OPERATION getHostCallReturnValue();
677 EncodedJSValue DFG_OPERATION getHostCallReturnValueWithExecState(ExecState*);
678 
679 #if CPU(X86_64)
680 asm (
681 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
682 HIDE_SYMBOL(getHostCallReturnValue) "\n"
683 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
684  "mov -40(%r13), %r13\n"
685  "mov %r13, %rdi\n"
686  "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
687 );
688 #elif CPU(X86)
689 asm (
690 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
691 HIDE_SYMBOL(getHostCallReturnValue) "\n"
692 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
693  "mov -40(%edi), %edi\n"
694  "mov %edi, 4(%esp)\n"
695  "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
696 );
697 #elif CPU(ARM_THUMB2)
698 asm (
699 ".text" "\n"
700 ".align 2" "\n"
701 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
702 HIDE_SYMBOL(getHostCallReturnValue) "\n"
703 ".thumb" "\n"
704 ".thumb_func " THUMB_FUNC_PARAM(getHostCallReturnValue) "\n"
705 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
706  "ldr r5, [r5, #-40]" "\n"
707  "cpy r0, r5" "\n"
708  "b " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
709 );
710 #endif
711 
712 EncodedJSValue DFG_OPERATION getHostCallReturnValueWithExecState(ExecState* exec)
713 {
714  JSGlobalData* globalData = &exec->globalData();
715  NativeCallFrameTracer tracer(globalData, exec);
716 
717  return JSValue::encode(exec->globalData().hostCallReturnValue);
718 }
719 
720677static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializationKind kind)
721678{
722679 ExecState* exec = execCallee->callerFrame();
106834

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
106834

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
146148 size_t waterMark();
147149 size_t highWaterMark();
106834

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;
106834

Source/JavaScriptCore/heap/MarkedAllocator.h

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

@@public:
3435 void setMarkedSpace(MarkedSpace* space) { m_markedSpace = space; }
3536
3637private:
 38 friend class LLIntOffsetsExtractor;
 39
3740 JS_EXPORT_PRIVATE void* allocateSlowCase();
3841 void* tryAllocate();
3942 void* tryAllocateHelper();
106834

Source/JavaScriptCore/heap/MarkedSpace.h

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

@@public:
7677 void didConsumeFreeList(MarkedBlock*);
7778
7879private:
 80 friend class LLIntOffsetsExtractor;
 81
7982 // [ 32... 256 ]
8083 static const size_t preciseStep = MarkedBlock::atomSize;
8184 static const size_t preciseCutoff = 256;
106834

Source/JavaScriptCore/interpreter/CallFrame.h

@@namespace JSC {
122122#if ENABLE(INTERPRETER)
123123 Instruction* returnVPC() const { return this[RegisterFile::ReturnPC].vPC(); }
124124#endif
 125#if ENABLE(LLINT)
 126 Instruction* currentVPC() const { return bitwise_cast<Instruction*>(this[RegisterFile::ArgumentCount].tag()); }
 127#endif
125128
126129 void setCallerFrame(CallFrame* callerFrame) { static_cast<Register*>(this)[RegisterFile::CallerFrame] = callerFrame; }
127130 void setScopeChain(ScopeChainNode* scopeChain) { static_cast<Register*>(this)[RegisterFile::ScopeChain] = scopeChain; }
106834

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();
106834

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
106834

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);
106834

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
689697 info.callReturnLocation = m_codeBlock->structureStubInfo(m_methodCallCompilationInfo[i].propertyAccessIndex).callReturnLocation;
690698 }
691699
692 #if ENABLE(DFG_JIT)
693  if (m_canBeOptimized) {
 700#if ENABLE(DFG_JIT) || ENABLE(LLINT)
 701 if (m_canBeOptimized
 702#if ENABLE(LLINT)
 703 || true
 704#endif
 705 ) {
694706 CompactJITCodeMap::Encoder jitCodeMapEncoder;
695707 for (unsigned bytecodeOffset = 0; bytecodeOffset < m_labels.size(); ++bytecodeOffset) {
696708 if (m_labels[bytecodeOffset].isSet())
106834

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
106834

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;
106834

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}
106834

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  printf("Entered optimize_from_loop with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
 1935 printf("%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
106834

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"
106834

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 printf("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 printf("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 printf("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 printf("%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 printf("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d: %08x:%08x",
 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#ifndef NDEBUG
 178 printf(": %s", value.description());
 179#endif
 180 printf("\n");
 181 LLINT_END();
 182}
 183
 184LLINT_HELPER_DECL(trace_prologue)
 185{
 186 printf("%p / %p: in prologue.\n", exec->codeBlock(), exec);
 187 LLINT_END();
 188}
 189
 190static void traceFunctionPrologue(ExecState* exec, const char* comment, CodeSpecializationKind kind)
 191{
 192 JSFunction* callee = asFunction(exec->callee());
 193 FunctionExecutable* executable = callee->jsExecutable();
 194 CodeBlock* codeBlock = &executable->generatedBytecodeFor(kind);
 195 printf("%p / %p: in %s of function %p, executable %p; numVars = %u, numParameters = %u, numCalleeRegisters = %u.\n",
 196 codeBlock, exec, comment, callee, executable,
 197 codeBlock->m_numVars, codeBlock->numParameters(), codeBlock->m_numCalleeRegisters);
 198}
 199
 200LLINT_HELPER_DECL(trace_prologue_function_for_call)
 201{
 202 traceFunctionPrologue(exec, "call prologue", CodeForCall);
 203 LLINT_END();
 204}
 205
 206LLINT_HELPER_DECL(trace_prologue_function_for_construct)
 207{
 208 traceFunctionPrologue(exec, "construct prologue", CodeForConstruct);
 209 LLINT_END();
 210}
 211
 212LLINT_HELPER_DECL(trace_arityCheck_for_call)
 213{
 214 traceFunctionPrologue(exec, "call arity check", CodeForCall);
 215 LLINT_END();
 216}
 217
 218LLINT_HELPER_DECL(trace_arityCheck_for_construct)
 219{
 220 traceFunctionPrologue(exec, "construct arity check", CodeForConstruct);
 221 LLINT_END();
 222}
 223
 224LLINT_HELPER_DECL(trace)
 225{
 226 printf("%p / %p: executing bc#%zu, ",
 227 exec->codeBlock(),
 228 exec,
 229 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()));
 230#ifndef NDEBUG
 231 printf("%s, ", opcodeNames[exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode)]);
 232#else
 233 printf("op#%u, ", exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode));
 234#endif
 235 printf("scope %p\n", exec->scopeChain());
 236 LLINT_END();
 237}
 238
 239LLINT_HELPER_DECL(special_trace)
 240{
 241 printf("%p / %p: executing special case bc#%zu, op#%u, return PC is %p\n",
 242 exec->codeBlock(),
 243 exec,
 244 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
 245 exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode),
 246 exec->returnPC().value());
 247 LLINT_END();
 248}
 249
 250inline bool shouldJIT(ExecState* exec)
 251{
 252 // You can modify this to turn off JITting without rebuilding the world.
 253 return exec->globalData().canUseJIT();
 254}
 255
 256enum EntryKind { Prologue, ArityCheck };
 257static HelperReturnType entryOSR(ExecState* exec, Instruction* pc, CodeBlock* codeBlock, const char *name, EntryKind kind)
 258{
 259#if ENABLE(JIT_VERBOSE_OSR)
 260 printf("%p: Entered %s with executeCounter = %d\n", codeBlock, name, codeBlock->llintExecuteCounter());
 261#endif
 262
 263 if (!shouldJIT(exec)) {
 264 codeBlock->dontJITAnytimeSoon();
 265 LLINT_RETURN_TWO(0, exec);
 266 }
 267 if (!codeBlock->jitCompile(exec->globalData())) {
 268#if ENABLE(JIT_VERBOSE_OSR)
 269 printf(" Code was already compiled.\n");
 270#endif
 271 }
 272 codeBlock->jitSoon();
 273 if (kind == Prologue)
 274 LLINT_RETURN_TWO(codeBlock->getJITCode().executableAddressAtOffset(0), exec);
 275 ASSERT(kind == ArityCheck);
 276 LLINT_RETURN_TWO(codeBlock->getJITCodeWithArityCheck().executableAddress(), exec);
 277}
 278
 279LLINT_HELPER_DECL(entry_osr)
 280{
 281 return entryOSR(exec, pc, exec->codeBlock(), "entry_osr", Prologue);
 282}
 283
 284LLINT_HELPER_DECL(entry_osr_function_for_call)
 285{
 286 return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall), "entry_osr_function_for_call", Prologue);
 287}
 288
 289LLINT_HELPER_DECL(entry_osr_function_for_construct)
 290{
 291 return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct), "entry_osr_function_for_construct", Prologue);
 292}
 293
 294LLINT_HELPER_DECL(entry_osr_function_for_call_arityCheck)
 295{
 296 return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall), "entry_osr_function_for_call_arityCheck", ArityCheck);
 297}
 298
 299LLINT_HELPER_DECL(entry_osr_function_for_construct_arityCheck)
 300{
 301 return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct), "entry_osr_function_for_construct_arityCheck", ArityCheck);
 302}
 303
 304LLINT_HELPER_DECL(loop_osr)
 305{
 306 CodeBlock* codeBlock = exec->codeBlock();
 307
 308#if ENABLE(JIT_VERBOSE_OSR)
 309 printf("%p: Entered loop_osr with executeCounter = %d\n", codeBlock, codeBlock->llintExecuteCounter());
 310#endif
 311
 312 if (!shouldJIT(exec)) {
 313 codeBlock->dontJITAnytimeSoon();
 314 LLINT_RETURN_TWO(0, exec);
 315 }
 316
 317 if (!codeBlock->jitCompile(exec->globalData())) {
 318#if ENABLE(JIT_VERBOSE_OSR)
 319 printf(" Code was already compiled.\n");
 320#endif
 321 }
 322 codeBlock->jitSoon();
 323
 324 ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT);
 325
 326 Vector<BytecodeAndMachineOffset> map;
 327 codeBlock->jitCodeMap()->decode(map);
 328 BytecodeAndMachineOffset* mapping = binarySearch<BytecodeAndMachineOffset, unsigned, BytecodeAndMachineOffset::getBytecodeIndex>(map.begin(), map.size(), pc - codeBlock->instructions().begin());
 329 ASSERT(mapping);
 330 ASSERT(mapping->m_bytecodeIndex == static_cast<unsigned>(pc - codeBlock->instructions().begin()));
 331
 332 void* jumpTarget = codeBlock->getJITCode().executableAddressAtOffset(mapping->m_machineCodeOffset);
 333 ASSERT(jumpTarget);
 334
 335 LLINT_RETURN_TWO(jumpTarget, exec);
 336}
 337
 338LLINT_HELPER_DECL(replace)
 339{
 340 CodeBlock* codeBlock = exec->codeBlock();
 341
 342#if ENABLE(JIT_VERBOSE_OSR)
 343 printf("%p: Entered replace with executeCounter = %d\n", codeBlock, codeBlock->llintExecuteCounter());
 344#endif
 345
 346 if (shouldJIT(exec)) {
 347 if (!codeBlock->jitCompile(exec->globalData())) {
 348#if ENABLE(JIT_VERBOSE_OSR)
 349 printf(" Code was already compiled.\n");
 350#endif
 351 }
 352 codeBlock->jitSoon();
 353 } else
 354 codeBlock->dontJITAnytimeSoon();
 355 LLINT_END();
 356}
 357
 358LLINT_HELPER_DECL(register_file_check)
 359{
 360 LLINT_BEGIN();
 361#if LLINT_HELPER_TRACING
 362 printf("Checking stack height with exec = %p.\n", exec);
 363 printf("CodeBlock = %p.\n", exec->codeBlock());
 364 printf("Num callee registers = %u.\n", exec->codeBlock()->m_numCalleeRegisters);
 365 printf("Num vars = %u.\n", exec->codeBlock()->m_numVars);
 366 printf("Current end is at %p.\n", exec->globalData().interpreter->registerFile().end());
 367#endif
 368 ASSERT(&exec->registers()[exec->codeBlock()->m_numCalleeRegisters] > exec->globalData().interpreter->registerFile().end());
 369 if (UNLIKELY(!exec->globalData().interpreter->registerFile().grow(&exec->registers()[exec->codeBlock()->m_numCalleeRegisters]))) {
 370 exec = exec->callerFrame();
 371 exec->globalData().exception = createStackOverflowError(exec);
 372 interpreterThrowInCaller(exec);
 373 pc = returnToThrowForThrownException(exec);
 374 }
 375 LLINT_END_IMPL();
 376}
 377
 378LLINT_HELPER_DECL(helper_call_arityCheck)
 379{
 380 LLINT_BEGIN();
 381 ExecState* newExec = CommonSlowPaths::arityCheckFor(exec, &exec->globalData().interpreter->registerFile(), CodeForCall);
 382 if (!newExec) {
 383 exec = exec->callerFrame();
 384 exec->globalData().exception = createStackOverflowError(exec);
 385 interpreterThrowInCaller(exec);
 386 LLINT_RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
 387 }
 388 LLINT_RETURN_TWO(0, newExec);
 389}
 390
 391LLINT_HELPER_DECL(helper_construct_arityCheck)
 392{
 393 LLINT_BEGIN();
 394 ExecState* newExec = CommonSlowPaths::arityCheckFor(exec, &exec->globalData().interpreter->registerFile(), CodeForConstruct);
 395 if (!newExec) {
 396 exec = exec->callerFrame();
 397 exec->globalData().exception = createStackOverflowError(exec);
 398 interpreterThrowInCaller(exec);
 399 LLINT_RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
 400 }
 401 LLINT_RETURN_TWO(0, newExec);
 402}
 403
 404LLINT_HELPER_DECL(helper_create_activation)
 405{
 406 LLINT_BEGIN();
 407#if LLINT_HELPER_TRACING
 408 printf("Creating an activation, exec = %p!\n", exec);
 409#endif
 410 JSActivation* activation = JSActivation::create(exec->globalData(), exec, static_cast<FunctionExecutable*>(exec->codeBlock()->ownerExecutable()));
 411 exec->setScopeChain(exec->scopeChain()->push(activation));
 412 LLINT_RETURN(JSValue(activation));
 413}
 414
 415LLINT_HELPER_DECL(helper_create_arguments)
 416{
 417 LLINT_BEGIN();
 418 JSValue arguments = JSValue(Arguments::create(exec->globalData(), exec));
 419 LLINT_CHECK_EXCEPTION();
 420 exec->uncheckedR(pc[1].u.operand) = arguments;
 421 exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)) = arguments;
 422 LLINT_END();
 423}
 424
 425LLINT_HELPER_DECL(helper_create_this)
 426{
 427 LLINT_BEGIN();
 428 JSFunction* constructor = asFunction(exec->callee());
 429
 430#if !ASSERT_DISABLED
 431 ConstructData constructData;
 432 ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
 433#endif
 434
 435 Structure* structure;
 436 JSValue proto = LLINT_OP(2).jsValue();
 437 if (proto.isObject())
 438 structure = asObject(proto)->inheritorID(exec->globalData());
 439 else
 440 structure = constructor->scope()->globalObject->emptyObjectStructure();
 441
 442 LLINT_RETURN(constructEmptyObject(exec, structure));
 443}
 444
 445LLINT_HELPER_DECL(helper_convert_this)
 446{
 447 LLINT_BEGIN();
 448 JSValue v1 = LLINT_OP(1).jsValue();
 449 ASSERT(v1.isPrimitive());
 450 LLINT_RETURN(v1.toThisObject(exec));
 451}
 452
 453LLINT_HELPER_DECL(helper_new_object)
 454{
 455 LLINT_BEGIN();
 456 LLINT_RETURN(constructEmptyObject(exec));
 457}
 458
 459LLINT_HELPER_DECL(helper_new_array)
 460{
 461 LLINT_BEGIN();
 462 LLINT_RETURN(constructArray(exec, bitwise_cast<JSValue*>(&LLINT_OP(2)), pc[3].u.operand));
 463}
 464
 465LLINT_HELPER_DECL(helper_new_array_buffer)
 466{
 467 LLINT_BEGIN();
 468 LLINT_RETURN(constructArray(exec, exec->codeBlock()->constantBuffer(pc[2].u.operand), pc[3].u.operand));
 469}
 470
 471LLINT_HELPER_DECL(helper_new_regexp)
 472{
 473 LLINT_BEGIN();
 474 RegExp* regExp = exec->codeBlock()->regexp(pc[2].u.operand);
 475 if (!regExp->isValid())
 476 LLINT_THROW(createSyntaxError(exec, "Invalid flag supplied to RegExp constructor."));
 477 LLINT_RETURN(RegExpObject::create(exec->globalData(), exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regExp));
 478}
 479
 480LLINT_HELPER_DECL(helper_not)
 481{
 482 LLINT_BEGIN();
 483 LLINT_RETURN(jsBoolean(!LLINT_OP_C(2).jsValue().toBoolean(exec)));
 484}
 485
 486LLINT_HELPER_DECL(helper_eq)
 487{
 488 LLINT_BEGIN();
 489 LLINT_RETURN(jsBoolean(JSValue::equal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
 490}
 491
 492LLINT_HELPER_DECL(helper_neq)
 493{
 494 LLINT_BEGIN();
 495 LLINT_RETURN(jsBoolean(!JSValue::equal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
 496}
 497
 498LLINT_HELPER_DECL(helper_stricteq)
 499{
 500 LLINT_BEGIN();
 501 LLINT_RETURN(jsBoolean(JSValue::strictEqual(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
 502}
 503
 504LLINT_HELPER_DECL(helper_nstricteq)
 505{
 506 LLINT_BEGIN();
 507 LLINT_RETURN(jsBoolean(!JSValue::strictEqual(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
 508}
 509
 510LLINT_HELPER_DECL(helper_less)
 511{
 512 LLINT_BEGIN();
 513 LLINT_RETURN(jsBoolean(jsLess<true>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
 514}
 515
 516LLINT_HELPER_DECL(helper_lesseq)
 517{
 518 LLINT_BEGIN();
 519 LLINT_RETURN(jsBoolean(jsLessEq<true>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
 520}
 521
 522LLINT_HELPER_DECL(helper_greater)
 523{
 524 LLINT_BEGIN();
 525 LLINT_RETURN(jsBoolean(jsLess<false>(exec, LLINT_OP_C(3).jsValue(), LLINT_OP_C(2).jsValue())));
 526}
 527
 528LLINT_HELPER_DECL(helper_greatereq)
 529{
 530 LLINT_BEGIN();
 531 LLINT_RETURN(jsBoolean(jsLessEq<false>(exec, LLINT_OP_C(3).jsValue(), LLINT_OP_C(2).jsValue())));
 532}
 533
 534LLINT_HELPER_DECL(helper_pre_inc)
 535{
 536 LLINT_BEGIN();
 537 LLINT_RETURN(jsNumber(LLINT_OP(1).jsValue().toNumber(exec) + 1));
 538}
 539
 540LLINT_HELPER_DECL(helper_pre_dec)
 541{
 542 LLINT_BEGIN();
 543 LLINT_RETURN(jsNumber(LLINT_OP(1).jsValue().toNumber(exec) - 1));
 544}
 545
 546LLINT_HELPER_DECL(helper_post_inc)
 547{
 548 LLINT_BEGIN();
 549 double result = LLINT_OP(2).jsValue().toNumber(exec);
 550 LLINT_OP(2) = jsNumber(result + 1);
 551 LLINT_RETURN(jsNumber(result));
 552}
 553
 554LLINT_HELPER_DECL(helper_post_dec)
 555{
 556 LLINT_BEGIN();
 557 double result = LLINT_OP(2).jsValue().toNumber(exec);
 558 LLINT_OP(2) = jsNumber(result - 1);
 559 LLINT_RETURN(jsNumber(result));
 560}
 561
 562LLINT_HELPER_DECL(helper_to_jsnumber)
 563{
 564 LLINT_BEGIN();
 565 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec)));
 566}
 567
 568LLINT_HELPER_DECL(helper_negate)
 569{
 570 LLINT_BEGIN();
 571 LLINT_RETURN(jsNumber(-LLINT_OP_C(2).jsValue().toNumber(exec)));
 572}
 573
 574LLINT_HELPER_DECL(helper_add)
 575{
 576 LLINT_BEGIN();
 577 JSValue v1 = LLINT_OP_C(2).jsValue();
 578 JSValue v2 = LLINT_OP_C(3).jsValue();
 579
 580#if LLINT_HELPER_TRACING
 581 printf("Trying to add %s", v1.description());
 582 printf(" to %s.\n", v2.description());
 583#endif
 584
 585 if (v1.isString() && !v2.isObject())
 586 LLINT_RETURN(jsString(exec, asString(v1), v2.toString(exec)));
 587
 588 if (v1.isNumber() && v2.isNumber())
 589 LLINT_RETURN(jsNumber(v1.asNumber() + v2.asNumber()));
 590
 591 LLINT_RETURN(jsAddSlowCase(exec, v1, v2));
 592}
 593
 594LLINT_HELPER_DECL(helper_mul)
 595{
 596 LLINT_BEGIN();
 597 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) * LLINT_OP_C(3).jsValue().toNumber(exec)));
 598}
 599
 600LLINT_HELPER_DECL(helper_sub)
 601{
 602 LLINT_BEGIN();
 603 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) - LLINT_OP_C(3).jsValue().toNumber(exec)));
 604}
 605
 606LLINT_HELPER_DECL(helper_div)
 607{
 608 LLINT_BEGIN();
 609 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) / LLINT_OP_C(3).jsValue().toNumber(exec)));
 610}
 611
 612LLINT_HELPER_DECL(helper_mod)
 613{
 614 LLINT_BEGIN();
 615 LLINT_RETURN(jsNumber(fmod(LLINT_OP_C(2).jsValue().toNumber(exec), LLINT_OP_C(3).jsValue().toNumber(exec))));
 616}
 617
 618LLINT_HELPER_DECL(helper_lshift)
 619{
 620 LLINT_BEGIN();
 621 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) << (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
 622}
 623
 624LLINT_HELPER_DECL(helper_rshift)
 625{
 626 LLINT_BEGIN();
 627 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) >> (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
 628}
 629
 630LLINT_HELPER_DECL(helper_urshift)
 631{
 632 LLINT_BEGIN();
 633 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toUInt32(exec) >> (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
 634}
 635
 636LLINT_HELPER_DECL(helper_bitand)
 637{
 638 LLINT_BEGIN();
 639 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) & LLINT_OP_C(3).jsValue().toInt32(exec)));
 640}
 641
 642LLINT_HELPER_DECL(helper_bitor)
 643{
 644 LLINT_BEGIN();
 645 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) | LLINT_OP_C(3).jsValue().toInt32(exec)));
 646}
 647
 648LLINT_HELPER_DECL(helper_bitxor)
 649{
 650 LLINT_BEGIN();
 651 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) ^ LLINT_OP_C(3).jsValue().toInt32(exec)));
 652}
 653
 654LLINT_HELPER_DECL(helper_bitnot)
 655{
 656 LLINT_BEGIN();
 657 LLINT_RETURN(jsNumber(~LLINT_OP_C(2).jsValue().toInt32(exec)));
 658}
 659
 660LLINT_HELPER_DECL(helper_check_has_instance)
 661{
 662 LLINT_BEGIN();
 663 JSValue baseVal = LLINT_OP_C(1).jsValue();
 664#ifndef NDEBUG
 665 TypeInfo typeInfo(UnspecifiedType);
 666 ASSERT(!baseVal.isObject()
 667 || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance());
 668#endif
 669 LLINT_THROW(createInvalidParamError(exec, "instanceof", baseVal));
 670}
 671
 672LLINT_HELPER_DECL(helper_instanceof)
 673{
 674 LLINT_BEGIN();
 675 LLINT_RETURN(jsBoolean(CommonSlowPaths::opInstanceOfSlow(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue())));
 676}
 677
 678LLINT_HELPER_DECL(helper_typeof)
 679{
 680 LLINT_BEGIN();
 681 LLINT_RETURN(jsTypeStringForValue(exec, LLINT_OP_C(2).jsValue()));
 682}
 683
 684LLINT_HELPER_DECL(helper_is_undefined)
 685{
 686 LLINT_BEGIN();
 687 JSValue v = LLINT_OP_C(2).jsValue();
 688 LLINT_RETURN(jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined()));
 689}
 690
 691LLINT_HELPER_DECL(helper_is_boolean)
 692{
 693 LLINT_BEGIN();
 694 LLINT_RETURN(jsBoolean(LLINT_OP_C(2).jsValue().isBoolean()));
 695}
 696
 697LLINT_HELPER_DECL(helper_is_number)
 698{
 699 LLINT_BEGIN();
 700 LLINT_RETURN(jsBoolean(LLINT_OP_C(2).jsValue().isNumber()));
 701}
 702
 703LLINT_HELPER_DECL(helper_is_string)
 704{
 705 LLINT_BEGIN();
 706 LLINT_RETURN(jsBoolean(isJSString(LLINT_OP_C(2).jsValue())));
 707}
 708
 709LLINT_HELPER_DECL(helper_is_object)
 710{
 711 LLINT_BEGIN();
 712 LLINT_RETURN(jsBoolean(jsIsObjectType(LLINT_OP_C(2).jsValue())));
 713}
 714
 715LLINT_HELPER_DECL(helper_is_function)
 716{
 717 LLINT_BEGIN();
 718 LLINT_RETURN(jsBoolean(jsIsFunctionType(LLINT_OP_C(2).jsValue())));
 719}
 720
 721LLINT_HELPER_DECL(helper_in)
 722{
 723 LLINT_BEGIN();
 724 LLINT_RETURN(jsBoolean(CommonSlowPaths::opIn(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
 725}
 726
 727LLINT_HELPER_DECL(helper_resolve)
 728{
 729 LLINT_BEGIN();
 730 LLINT_RETURN_PROFILED(op_resolve, CommonSlowPaths::opResolve(exec, exec->codeBlock()->identifier(pc[2].u.operand)));
 731}
 732
 733LLINT_HELPER_DECL(helper_resolve_skip)
 734{
 735 LLINT_BEGIN();
 736 LLINT_RETURN_PROFILED(
 737 op_resolve_skip,
 738 CommonSlowPaths::opResolveSkip(
 739 exec,
 740 exec->codeBlock()->identifier(pc[2].u.operand),
 741 pc[3].u.operand));
 742}
 743
 744static JSValue resolveGlobal(ExecState* exec, Instruction* pc)
 745{
 746 CodeBlock* codeBlock = exec->codeBlock();
 747 JSGlobalObject* globalObject = codeBlock->globalObject();
 748 ASSERT(globalObject->isGlobalObject());
 749 int property = pc[2].u.operand;
 750 Structure* structure = pc[3].u.structure.get();
 751
 752 ASSERT_UNUSED(structure, structure != globalObject->structure());
 753
 754 Identifier& ident = codeBlock->identifier(property);
 755 PropertySlot slot(globalObject);
 756
 757 if (globalObject->getPropertySlot(exec, ident, slot)) {
 758 JSValue result = slot.getValue(exec, ident);
 759 if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary()
 760 && slot.slotBase() == globalObject) {
 761 pc[3].u.structure.set(
 762 exec->globalData(), codeBlock->ownerExecutable(), globalObject->structure());
 763 pc[4] = slot.cachedOffset();
 764 }
 765
 766 return result;
 767 }
 768
 769 exec->globalData().exception = createUndefinedVariableError(exec, ident);
 770 return JSValue();
 771}
 772
 773LLINT_HELPER_DECL(helper_resolve_global)
 774{
 775 LLINT_BEGIN();
 776 LLINT_RETURN_PROFILED(op_resolve_global, resolveGlobal(exec, pc));
 777}
 778
 779LLINT_HELPER_DECL(helper_resolve_global_dynamic)
 780{
 781 LLINT_BEGIN();
 782 LLINT_RETURN_PROFILED(op_resolve_global_dynamic, resolveGlobal(exec, pc));
 783}
 784
 785LLINT_HELPER_DECL(helper_resolve_for_resolve_global_dynamic)
 786{
 787 LLINT_BEGIN();
 788 LLINT_RETURN_PROFILED(op_resolve_global_dynamic, CommonSlowPaths::opResolve(exec, exec->codeBlock()->identifier(pc[2].u.operand)));
 789}
 790
 791LLINT_HELPER_DECL(helper_resolve_base)
 792{
 793 LLINT_BEGIN();
 794 Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
 795 if (pc[3].u.operand) {
 796 JSValue base = JSC::resolveBase(exec, ident, exec->scopeChain(), true);
 797 if (!base)
 798 LLINT_THROW(createErrorForInvalidGlobalAssignment(exec, ident.ustring()));
 799 LLINT_RETURN(base);
 800 }
 801
 802 LLINT_RETURN_PROFILED(op_resolve_base, JSC::resolveBase(exec, ident, exec->scopeChain(), false));
 803}
 804
 805LLINT_HELPER_DECL(helper_ensure_property_exists)
 806{
 807 LLINT_BEGIN();
 808 JSObject* object = asObject(LLINT_OP(1).jsValue());
 809 PropertySlot slot(object);
 810 Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
 811 if (!object->getPropertySlot(exec, ident, slot))
 812 LLINT_THROW(createErrorForInvalidGlobalAssignment(exec, ident.ustring()));
 813 LLINT_END();
 814}
 815
 816LLINT_HELPER_DECL(helper_resolve_with_base)
 817{
 818 LLINT_BEGIN();
 819 JSValue result = CommonSlowPaths::opResolveWithBase(exec, exec->codeBlock()->identifier(pc[3].u.operand), LLINT_OP(1));
 820 LLINT_CHECK_EXCEPTION();
 821 LLINT_OP(2) = result;
 822 // FIXME: technically should have profiling, but we don't do it because the DFG won't use it.
 823 LLINT_END();
 824}
 825
 826LLINT_HELPER_DECL(helper_resolve_with_this)
 827{
 828 LLINT_BEGIN();
 829 JSValue result = CommonSlowPaths::opResolveWithThis(exec, exec->codeBlock()->identifier(pc[3].u.operand), LLINT_OP(1));
 830 LLINT_CHECK_EXCEPTION();
 831 LLINT_OP(2) = result;
 832 // FIXME: technically should have profiling, but we don't do it because the DFG won't use it.
 833 LLINT_END();
 834}
 835
 836LLINT_HELPER_DECL(helper_get_by_id)
 837{
 838 LLINT_BEGIN();
 839 CodeBlock* codeBlock = exec->codeBlock();
 840 Identifier& ident = codeBlock->identifier(pc[3].u.operand);
 841 JSValue baseValue = LLINT_OP_C(2).jsValue();
 842 PropertySlot slot(baseValue);
 843
 844 JSValue result = baseValue.get(exec, ident, slot);
 845 LLINT_CHECK_EXCEPTION();
 846 LLINT_OP(1) = result;
 847
 848 if (baseValue.isCell()
 849 && slot.isCacheable()
 850 && slot.slotBase() == baseValue
 851 && slot.cachedPropertyType() == PropertySlot::Value) {
 852
 853 JSCell* baseCell = baseValue.asCell();
 854 Structure* structure = baseCell->structure();
 855
 856 if (!structure->isUncacheableDictionary()
 857 && !structure->typeInfo().prohibitsPropertyCaching()) {
 858 pc[4].u.structure.set(
 859 exec->globalData(), codeBlock->ownerExecutable(), structure);
 860 pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue);
 861 }
 862 }
 863
 864 pc[OPCODE_LENGTH(op_get_by_id) - 1].u.profile->m_buckets[0] = JSValue::encode(result);
 865 LLINT_END();
 866}
 867
 868LLINT_HELPER_DECL(helper_get_arguments_length)
 869{
 870 LLINT_BEGIN();
 871 CodeBlock* codeBlock = exec->codeBlock();
 872 Identifier& ident = codeBlock->identifier(pc[3].u.operand);
 873 JSValue baseValue = LLINT_OP(2).jsValue();
 874 PropertySlot slot(baseValue);
 875 LLINT_RETURN(baseValue.get(exec, ident, slot));
 876}
 877
 878LLINT_HELPER_DECL(helper_put_by_id)
 879{
 880 LLINT_BEGIN();
 881 CodeBlock* codeBlock = exec->codeBlock();
 882 Identifier& ident = codeBlock->identifier(pc[2].u.operand);
 883
 884 JSValue baseValue = LLINT_OP_C(1).jsValue();
 885 PutPropertySlot slot(codeBlock->isStrictMode());
 886 if (pc[8].u.operand)
 887 asObject(baseValue)->putDirect(exec->globalData(), ident, LLINT_OP_C(3).jsValue(), slot);
 888 else
 889 baseValue.put(exec, ident, LLINT_OP_C(3).jsValue(), slot);
 890 LLINT_CHECK_EXCEPTION();
 891
 892 if (baseValue.isCell()
 893 && slot.isCacheable()) {
 894
 895 JSCell* baseCell = baseValue.asCell();
 896 Structure* structure = baseCell->structure();
 897
 898 if (!structure->isUncacheableDictionary()
 899 && !structure->typeInfo().prohibitsPropertyCaching()
 900 && baseCell == slot.base()) {
 901
 902 if (slot.type() == PutPropertySlot::NewProperty) {
 903 if (!structure->isDictionary() && structure->previousID()->propertyStorageCapacity() == structure->propertyStorageCapacity()) {
 904 // This is needed because some of the methods we call
 905 // below may GC.
 906 pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id);
 907
 908 normalizePrototypeChain(exec, baseCell);
 909
 910 ASSERT(structure->previousID()->isObject());
 911 pc[4].u.structure.set(
 912 exec->globalData(), codeBlock->ownerExecutable(), structure->previousID());
 913 pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue);
 914 pc[6].u.structure.set(
 915 exec->globalData(), codeBlock->ownerExecutable(), structure);
 916 StructureChain* chain = structure->prototypeChain(exec);
 917 ASSERT(chain);
 918 pc[7].u.structureChain.set(
 919 exec->globalData(), codeBlock->ownerExecutable(), chain);
 920
 921 if (pc[8].u.operand)
 922 pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id_transition_direct);
 923 else
 924 pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id_transition_normal);
 925 }
 926 } else {
 927 pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id);
 928 pc[4].u.structure.set(
 929 exec->globalData(), codeBlock->ownerExecutable(), structure);
 930 pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue);
 931 }
 932 }
 933 }
 934
 935 if (false && !strcmp(ident.ascii().data(), "renderReflections"))
 936 printf("Finishing access to renderReflections from LLInt slow path.\n");
 937
 938 LLINT_END();
 939}
 940
 941LLINT_HELPER_DECL(helper_del_by_id)
 942{
 943 LLINT_BEGIN();
 944 CodeBlock* codeBlock = exec->codeBlock();
 945 JSObject* baseObject = LLINT_OP_C(2).jsValue().toObject(exec);
 946 bool couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, codeBlock->identifier(pc[3].u.operand));
 947 LLINT_CHECK_EXCEPTION();
 948 if (!couldDelete && codeBlock->isStrictMode())
 949 LLINT_THROW(createTypeError(exec, "Unable to delete property."));
 950 LLINT_RETURN(jsBoolean(couldDelete));
 951}
 952
 953inline JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript)
 954{
 955 if (LIKELY(baseValue.isCell() && subscript.isString())) {
 956 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(exec, asString(subscript)->value(exec)))
 957 return result;
 958 }
 959
 960 if (subscript.isUInt32()) {
 961 uint32_t i = subscript.asUInt32();
 962 if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
 963 return asString(baseValue)->getIndex(exec, i);
 964
 965 if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i))
 966 return asByteArray(baseValue)->getIndex(exec, i);
 967
 968 return baseValue.get(exec, i);
 969 }
 970
 971 Identifier property(exec, subscript.toString(exec)->value(exec));
 972 return baseValue.get(exec, property);
 973}
 974
 975LLINT_HELPER_DECL(helper_get_by_val)
 976{
 977 LLINT_BEGIN();
 978 LLINT_RETURN_PROFILED(op_get_by_val, getByVal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue()));
 979}
 980
 981LLINT_HELPER_DECL(helper_get_argument_by_val)
 982{
 983 LLINT_BEGIN();
 984 JSValue arguments = LLINT_OP(2).jsValue();
 985 if (!arguments) {
 986 arguments = Arguments::create(exec->globalData(), exec);
 987 LLINT_CHECK_EXCEPTION();
 988 LLINT_OP(2) = arguments;
 989 exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)) = arguments;
 990 }
 991
 992 LLINT_RETURN(getByVal(exec, arguments, LLINT_OP_C(3).jsValue()));
 993}
 994
 995LLINT_HELPER_DECL(helper_get_by_pname)
 996{
 997 LLINT_BEGIN();
 998 LLINT_RETURN(getByVal(exec, LLINT_OP(2).jsValue(), LLINT_OP(3).jsValue()));
 999}
 1000
 1001LLINT_HELPER_DECL(helper_put_by_val)
 1002{
 1003 LLINT_BEGIN();
 1004 JSGlobalData& globalData = exec->globalData();
 1005
 1006 JSValue baseValue = LLINT_OP_C(1).jsValue();
 1007 JSValue subscript = LLINT_OP_C(2).jsValue();
 1008 JSValue value = LLINT_OP_C(3).jsValue();
 1009
 1010 if (LIKELY(subscript.isUInt32())) {
 1011 uint32_t i = subscript.asUInt32();
 1012 if (isJSArray(baseValue)) {
 1013 JSArray* jsArray = asArray(baseValue);
 1014 if (jsArray->canSetIndex(i))
 1015 jsArray->setIndex(globalData, i, value);
 1016 else
 1017 JSArray::putByIndex(jsArray, exec, i, value);
 1018 LLINT_END();
 1019 }
 1020 if (isJSByteArray(baseValue)
 1021 && asByteArray(baseValue)->canAccessIndex(i)) {
 1022 JSByteArray* jsByteArray = asByteArray(baseValue);
 1023 if (value.isInt32()) {
 1024 jsByteArray->setIndex(i, value.asInt32());
 1025 LLINT_END();
 1026 }
 1027 if (value.isNumber()) {
 1028 jsByteArray->setIndex(i, value.asNumber());
 1029 LLINT_END();
 1030 }
 1031 }
 1032 baseValue.put(exec, i, value);
 1033 LLINT_END();
 1034 }
 1035
 1036 Identifier property(exec, subscript.toString(exec)->value(exec));
 1037 LLINT_CHECK_EXCEPTION();
 1038 PutPropertySlot slot(exec->codeBlock()->isStrictMode());
 1039 baseValue.put(exec, property, value, slot);
 1040 LLINT_END();
 1041}
 1042
 1043LLINT_HELPER_DECL(helper_del_by_val)
 1044{
 1045 LLINT_BEGIN();
 1046 JSValue baseValue = LLINT_OP_C(2).jsValue();
 1047 JSObject* baseObject = baseValue.toObject(exec);
 1048
 1049 JSValue subscript = LLINT_OP_C(3).jsValue();
 1050
 1051 bool couldDelete;
 1052
 1053 uint32_t i;
 1054 if (subscript.getUInt32(i))
 1055 couldDelete = baseObject->methodTable()->deletePropertyByIndex(baseObject, exec, i);
 1056 else {
 1057 LLINT_CHECK_EXCEPTION();
 1058 Identifier property(exec, subscript.toString(exec)->value(exec));
 1059 LLINT_CHECK_EXCEPTION();
 1060 couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, property);
 1061 }
 1062
 1063 if (!couldDelete && exec->codeBlock()->isStrictMode())
 1064 LLINT_THROW(createTypeError(exec, "Unable to delete property."));
 1065
 1066 LLINT_RETURN(jsBoolean(couldDelete));
 1067}
 1068
 1069LLINT_HELPER_DECL(helper_put_by_index)
 1070{
 1071 LLINT_BEGIN();
 1072 LLINT_OP_C(1).jsValue().put(exec, pc[2].u.operand, LLINT_OP_C(3).jsValue());
 1073 LLINT_END();
 1074}
 1075
 1076LLINT_HELPER_DECL(helper_put_getter_setter)
 1077{
 1078 LLINT_BEGIN();
 1079 ASSERT(LLINT_OP(1).jsValue().isObject());
 1080 JSObject* baseObj = asObject(LLINT_OP(1).jsValue());
 1081
 1082 GetterSetter* accessor = GetterSetter::create(exec);
 1083 LLINT_CHECK_EXCEPTION();
 1084
 1085 JSValue getter = LLINT_OP(3).jsValue();
 1086 JSValue setter = LLINT_OP(4).jsValue();
 1087 ASSERT(getter.isObject() || getter.isUndefined());
 1088 ASSERT(setter.isObject() || setter.isUndefined());
 1089 ASSERT(getter.isObject() || setter.isObject());
 1090
 1091 if (!getter.isUndefined())
 1092 accessor->setGetter(exec->globalData(), asObject(getter));
 1093 if (!setter.isUndefined())
 1094 accessor->setSetter(exec->globalData(), asObject(setter));
 1095 baseObj->putDirectAccessor(
 1096 exec->globalData(),
 1097 exec->codeBlock()->identifier(pc[2].u.operand),
 1098 accessor, Accessor);
 1099 LLINT_END();
 1100}
 1101
 1102LLINT_HELPER_DECL(helper_jmp_scopes)
 1103{
 1104 LLINT_BEGIN();
 1105 unsigned count = pc[1].u.operand;
 1106 ScopeChainNode* tmp = exec->scopeChain();
 1107 while (count--)
 1108 tmp = tmp->pop();
 1109 exec->setScopeChain(tmp);
 1110 pc += pc[2].u.operand;
 1111 LLINT_END();
 1112}
 1113
 1114LLINT_HELPER_DECL(helper_jtrue)
 1115{
 1116 LLINT_BEGIN();
 1117 LLINT_BRANCH(op_jtrue, LLINT_OP_C(1).jsValue().toBoolean(exec));
 1118}
 1119
 1120LLINT_HELPER_DECL(helper_jfalse)
 1121{
 1122 LLINT_BEGIN();
 1123 LLINT_BRANCH(op_jfalse, !LLINT_OP_C(1).jsValue().toBoolean(exec));
 1124}
 1125
 1126LLINT_HELPER_DECL(helper_jless)
 1127{
 1128 LLINT_BEGIN();
 1129 LLINT_BRANCH(op_jless, jsLess<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
 1130}
 1131
 1132LLINT_HELPER_DECL(helper_jnless)
 1133{
 1134 LLINT_BEGIN();
 1135 LLINT_BRANCH(op_jnless, !jsLess<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
 1136}
 1137
 1138LLINT_HELPER_DECL(helper_jgreater)
 1139{
 1140 LLINT_BEGIN();
 1141 LLINT_BRANCH(op_jgreater, jsLess<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
 1142}
 1143
 1144LLINT_HELPER_DECL(helper_jngreater)
 1145{
 1146 LLINT_BEGIN();
 1147 LLINT_BRANCH(op_jngreater, !jsLess<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
 1148}
 1149
 1150LLINT_HELPER_DECL(helper_jlesseq)
 1151{
 1152 LLINT_BEGIN();
 1153 LLINT_BRANCH(op_jlesseq, jsLessEq<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
 1154}
 1155
 1156LLINT_HELPER_DECL(helper_jnlesseq)
 1157{
 1158 LLINT_BEGIN();
 1159 LLINT_BRANCH(op_jnlesseq, !jsLessEq<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
 1160}
 1161
 1162LLINT_HELPER_DECL(helper_jgreatereq)
 1163{
 1164 LLINT_BEGIN();
 1165 LLINT_BRANCH(op_jgreatereq, jsLessEq<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
 1166}
 1167
 1168LLINT_HELPER_DECL(helper_jngreatereq)
 1169{
 1170 LLINT_BEGIN();
 1171 LLINT_BRANCH(op_jngreatereq, !jsLessEq<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
 1172}
 1173
 1174LLINT_HELPER_DECL(helper_switch_imm)
 1175{
 1176 LLINT_BEGIN();
 1177 JSValue scrutinee = LLINT_OP_C(3).jsValue();
 1178 ASSERT(scrutinee.isDouble());
 1179 double value = scrutinee.asDouble();
 1180 int32_t intValue = static_cast<int32_t>(value);
 1181 int defaultOffset = pc[2].u.operand;
 1182 if (value == intValue) {
 1183 CodeBlock* codeBlock = exec->codeBlock();
 1184 pc += codeBlock->immediateSwitchJumpTable(pc[1].u.operand).offsetForValue(intValue, defaultOffset);
 1185 } else
 1186 pc += defaultOffset;
 1187 LLINT_END();
 1188}
 1189
 1190LLINT_HELPER_DECL(helper_switch_string)
 1191{
 1192 LLINT_BEGIN();
 1193 JSValue scrutinee = LLINT_OP_C(3).jsValue();
 1194 int defaultOffset = pc[2].u.operand;
 1195 if (!scrutinee.isString())
 1196 pc += defaultOffset;
 1197 else {
 1198 CodeBlock* codeBlock = exec->codeBlock();
 1199 pc += codeBlock->stringSwitchJumpTable(pc[1].u.operand).offsetForValue(asString(scrutinee)->value(exec).impl(), defaultOffset);
 1200 }
 1201 LLINT_END();
 1202}
 1203
 1204LLINT_HELPER_DECL(helper_new_func)
 1205{
 1206 LLINT_BEGIN();
 1207 CodeBlock* codeBlock = exec->codeBlock();
 1208 ASSERT(codeBlock->codeType() != FunctionCode
 1209 || !codeBlock->needsFullScopeChain()
 1210 || exec->uncheckedR(codeBlock->activationRegister()).jsValue());
 1211#if LLINT_HELPER_TRACING
 1212 printf("Creating function!\n");
 1213#endif
 1214 LLINT_RETURN(codeBlock->functionDecl(pc[2].u.operand)->make(exec, exec->scopeChain()));
 1215}
 1216
 1217LLINT_HELPER_DECL(helper_new_func_exp)
 1218{
 1219 LLINT_BEGIN();
 1220 CodeBlock* codeBlock = exec->codeBlock();
 1221 FunctionExecutable* function = codeBlock->functionExpr(pc[2].u.operand);
 1222 JSFunction* func = function->make(exec, exec->scopeChain());
 1223
 1224 if (!function->name().isNull()) {
 1225 JSStaticScopeObject* functionScopeObject = JSStaticScopeObject::create(exec, function->name(), func, ReadOnly | DontDelete);
 1226 func->setScope(exec->globalData(), func->scope()->push(functionScopeObject));
 1227 }
 1228
 1229 LLINT_RETURN(func);
 1230}
 1231
 1232static HelperReturnType handleHostCall(ExecState* execCallee, Instruction* pc, JSValue callee, CodeSpecializationKind kind)
 1233{
 1234 ExecState* exec = execCallee->callerFrame();
 1235 JSGlobalData* globalData = &exec->globalData();
 1236
 1237 execCallee->setScopeChain(exec->scopeChain());
 1238 execCallee->setCodeBlock(0);
 1239
 1240 if (kind == CodeForCall) {
 1241 CallData callData;
 1242 CallType callType = getCallData(callee, callData);
 1243
 1244 ASSERT(callType != CallTypeJS);
 1245
 1246 if (callType == CallTypeHost) {
 1247 globalData->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
 1248
 1249 LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
 1250 }
 1251
 1252#if LLINT_HELPER_TRACING
 1253 printf("Call callee is not a function: %s\n", callee.description());
 1254#endif
 1255
 1256 ASSERT(callType == CallTypeNone);
 1257 LLINT_CALL_THROW(exec, pc, createNotAFunctionError(exec, callee));
 1258 }
 1259
 1260 ASSERT(kind == CodeForConstruct);
 1261
 1262 ConstructData constructData;
 1263 ConstructType constructType = getConstructData(callee, constructData);
 1264
 1265 ASSERT(constructType != ConstructTypeJS);
 1266
 1267 if (constructType == ConstructTypeHost) {
 1268 globalData->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
 1269
 1270 LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
 1271 }
 1272
 1273#if LLINT_HELPER_TRACING
 1274 printf("Constructor callee is not a function: %s\n", callee.description());
 1275#endif
 1276
 1277 ASSERT(constructType == ConstructTypeNone);
 1278 LLINT_CALL_THROW(exec, pc, createNotAConstructorError(exec, callee));
 1279}
 1280
 1281inline HelperReturnType setUpCall(ExecState* execCallee, Instruction* pc, CodeSpecializationKind kind, JSValue calleeAsValue, LLIntCallLinkInfo* callLinkInfo = 0)
 1282{
 1283 JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
 1284 if (!calleeAsFunctionCell)
 1285 return handleHostCall(execCallee, pc, calleeAsValue, kind);
 1286
 1287 JSFunction* callee = asFunction(calleeAsFunctionCell);
 1288 execCallee->setScopeChain(callee->scopeUnchecked());
 1289 ExecutableBase* executable = callee->executable();
 1290
 1291 MacroAssemblerCodePtr codePtr;
 1292 CodeBlock* codeBlock = 0;
 1293 if (executable->isHostFunction())
 1294 codePtr = executable->generatedJITCodeFor(kind).addressForCall();
 1295 else {
 1296 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
 1297 JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind);
 1298 if (error)
 1299 LLINT_CALL_THROW(execCallee->callerFrame(), pc, error);
 1300 codeBlock = &functionExecutable->generatedBytecodeFor(kind);
 1301 ASSERT(codeBlock);
 1302 if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
 1303 codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
 1304 else
 1305 codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
 1306 }
 1307
 1308 if (callLinkInfo) {
 1309 if (callLinkInfo->isOnList())
 1310 callLinkInfo->remove();
 1311 ExecState* execCaller = execCallee->callerFrame();
 1312 callLinkInfo->callee.set(execCaller->globalData(), execCaller->codeBlock()->ownerExecutable(), callee);
 1313 callLinkInfo->lastSeenCallee.set(execCaller->globalData(), execCaller->codeBlock()->ownerExecutable(), callee);
 1314 callLinkInfo->machineCodeTarget = codePtr;
 1315 if (codeBlock)
 1316 codeBlock->linkIncomingCall(callLinkInfo);
 1317 }
 1318
 1319 LLINT_CALL_RETURN(execCallee, pc, codePtr.executableAddress());
 1320}
 1321
 1322inline HelperReturnType genericCall(ExecState* exec, Instruction* pc, CodeSpecializationKind kind)
 1323{
 1324 // This needs to:
 1325 // - Set up a call frame.
 1326 // - Figure out what to call and compile it if necessary.
 1327 // - If possible, link the call's inline cache.
 1328 // - Return a tuple of machine code address to call and the new call frame.
 1329
 1330 JSValue calleeAsValue = LLINT_OP_C(1).jsValue();
 1331
 1332 ExecState* execCallee = exec + pc[3].u.operand;
 1333
 1334 execCallee->setArgumentCountIncludingThis(pc[2].u.operand);
 1335 execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue;
 1336 execCallee->setCallerFrame(exec);
 1337
 1338 ASSERT(pc[4].u.callLinkInfo);
 1339 return setUpCall(execCallee, pc, kind, calleeAsValue, pc[4].u.callLinkInfo);
 1340}
 1341
 1342LLINT_HELPER_DECL(helper_call)
 1343{
 1344 LLINT_BEGIN();
 1345 return genericCall(exec, pc, CodeForCall);
 1346}
 1347
 1348LLINT_HELPER_DECL(helper_construct)
 1349{
 1350 LLINT_BEGIN();
 1351 return genericCall(exec, pc, CodeForConstruct);
 1352}
 1353
 1354LLINT_HELPER_DECL(helper_call_varargs)
 1355{
 1356 LLINT_BEGIN();
 1357 // This needs to:
 1358 // - Set up a call frame while respecting the variable arguments.
 1359 // - Figure out what to call and compile it if necessary.
 1360 // - Return a tuple of machine code address to call and the new call frame.
 1361
 1362 JSValue calleeAsValue = LLINT_OP_C(1).jsValue();
 1363
 1364 ExecState* execCallee = loadVarargs(
 1365 exec, &exec->globalData().interpreter->registerFile(),
 1366 LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue(), pc[4].u.operand);
 1367 LLINT_CALL_CHECK_EXCEPTION(exec, pc);
 1368
 1369 execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue;
 1370 execCallee->setCallerFrame(exec);
 1371 exec->uncheckedR(RegisterFile::ArgumentCount).tag() = bitwise_cast<int32_t>(pc + OPCODE_LENGTH(op_call_varargs));
 1372
 1373 return setUpCall(execCallee, pc, CodeForCall, calleeAsValue);
 1374}
 1375
 1376LLINT_HELPER_DECL(helper_call_eval)
 1377{
 1378 LLINT_BEGIN();
 1379 JSValue calleeAsValue = LLINT_OP(1).jsValue();
 1380
 1381 ExecState* execCallee = exec + pc[3].u.operand;
 1382 JSGlobalData& globalData = exec->globalData();
 1383
 1384 execCallee->setArgumentCountIncludingThis(pc[2].u.operand);
 1385 execCallee->setCallerFrame(exec);
 1386 execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue;
 1387 execCallee->setScopeChain(exec->scopeChain());
 1388 execCallee->setReturnPC(bitwise_cast<Instruction*>(&llint_generic_return_point));
 1389 execCallee->setCodeBlock(0);
 1390 exec->uncheckedR(RegisterFile::ArgumentCount).tag() = bitwise_cast<int32_t>(pc + OPCODE_LENGTH(op_call_eval));
 1391
 1392 if (!isHostFunction(calleeAsValue, globalFuncEval))
 1393 return setUpCall(execCallee, pc, CodeForCall, calleeAsValue);
 1394
 1395 globalData.hostCallReturnValue = eval(execCallee);
 1396 LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
 1397}
 1398
 1399LLINT_HELPER_DECL(helper_tear_off_activation)
 1400{
 1401 LLINT_BEGIN();
 1402 ASSERT(exec->codeBlock()->needsFullScopeChain());
 1403 JSValue activationValue = LLINT_OP(1).jsValue();
 1404 if (!activationValue) {
 1405 if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)).jsValue()) {
 1406 if (!exec->codeBlock()->isStrictMode())
 1407 asArguments(v)->tearOff(exec);
 1408 }
 1409 LLINT_END();
 1410 }
 1411 JSActivation* activation = asActivation(activationValue);
 1412 activation->tearOff(exec->globalData());
 1413 if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)).jsValue())
 1414 asArguments(v)->didTearOffActivation(exec->globalData(), activation);
 1415 LLINT_END();
 1416}
 1417
 1418LLINT_HELPER_DECL(helper_tear_off_arguments)
 1419{
 1420 LLINT_BEGIN();
 1421 ASSERT(exec->codeBlock()->usesArguments() && !exec->codeBlock()->needsFullScopeChain());
 1422 asArguments(exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)).jsValue())->tearOff(exec);
 1423 LLINT_END();
 1424}
 1425
 1426LLINT_HELPER_DECL(helper_strcat)
 1427{
 1428 LLINT_BEGIN();
 1429 LLINT_RETURN(jsString(exec, &LLINT_OP(2), pc[3].u.operand));
 1430}
 1431
 1432LLINT_HELPER_DECL(helper_to_primitive)
 1433{
 1434 LLINT_BEGIN();
 1435 LLINT_RETURN(LLINT_OP_C(2).jsValue().toPrimitive(exec));
 1436}
 1437
 1438LLINT_HELPER_DECL(helper_get_pnames)
 1439{
 1440 LLINT_BEGIN();
 1441 JSValue v = LLINT_OP(2).jsValue();
 1442 if (v.isUndefinedOrNull()) {
 1443 pc += pc[5].u.operand;
 1444 LLINT_END();
 1445 }
 1446
 1447 JSObject* o = v.toObject(exec);
 1448 Structure* structure = o->structure();
 1449 JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
 1450 if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(exec))
 1451 jsPropertyNameIterator = JSPropertyNameIterator::create(exec, o);
 1452
 1453 LLINT_OP(1) = JSValue(jsPropertyNameIterator);
 1454 LLINT_OP(2) = JSValue(o);
 1455 LLINT_OP(3) = Register::withInt(0);
 1456 LLINT_OP(4) = Register::withInt(jsPropertyNameIterator->size());
 1457
 1458 pc += OPCODE_LENGTH(op_get_pnames);
 1459 LLINT_END();
 1460}
 1461
 1462LLINT_HELPER_DECL(helper_next_pname)
 1463{
 1464 LLINT_BEGIN();
 1465 JSObject* base = asObject(LLINT_OP(2).jsValue());
 1466 JSString* property = asString(LLINT_OP(1).jsValue());
 1467 if (base->hasProperty(exec, Identifier(exec, property->value(exec)))) {
 1468 // Go to target.
 1469 pc += pc[6].u.operand;
 1470 } // Else, don't change the PC, so the interpreter will reloop.
 1471 LLINT_END();
 1472}
 1473
 1474LLINT_HELPER_DECL(helper_push_scope)
 1475{
 1476 LLINT_BEGIN();
 1477 JSValue v = LLINT_OP(1).jsValue();
 1478 JSObject* o = v.toObject(exec);
 1479 LLINT_CHECK_EXCEPTION();
 1480
 1481 LLINT_OP(1) = o;
 1482 exec->setScopeChain(exec->scopeChain()->push(o));
 1483
 1484 LLINT_END();
 1485}
 1486
 1487LLINT_HELPER_DECL(helper_pop_scope)
 1488{
 1489 LLINT_BEGIN();
 1490 exec->setScopeChain(exec->scopeChain()->pop());
 1491 LLINT_END();
 1492}
 1493
 1494LLINT_HELPER_DECL(helper_push_new_scope)
 1495{
 1496 LLINT_BEGIN();
 1497 CodeBlock* codeBlock = exec->codeBlock();
 1498 JSObject* scope = JSStaticScopeObject::create(exec, codeBlock->identifier(pc[2].u.operand), LLINT_OP(3).jsValue(), DontDelete);
 1499 exec->setScopeChain(exec->scopeChain()->push(scope));
 1500 LLINT_RETURN(scope);
 1501}
 1502
 1503LLINT_HELPER_DECL(helper_throw)
 1504{
 1505 LLINT_BEGIN();
 1506 LLINT_THROW(LLINT_OP_C(1).jsValue());
 1507}
 1508
 1509LLINT_HELPER_DECL(helper_throw_reference_error)
 1510{
 1511 LLINT_BEGIN();
 1512 LLINT_THROW(createReferenceError(exec, LLINT_OP_C(1).jsValue().toString(exec)->value(exec)));
 1513}
 1514
 1515LLINT_HELPER_DECL(helper_debug)
 1516{
 1517 LLINT_BEGIN();
 1518 int debugHookID = pc[1].u.operand;
 1519 int firstLine = pc[2].u.operand;
 1520 int lastLine = pc[3].u.operand;
 1521
 1522 exec->globalData().interpreter->debug(exec, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
 1523
 1524 LLINT_END();
 1525}
 1526
 1527LLINT_HELPER_DECL(helper_profile_will_call)
 1528{
 1529 LLINT_BEGIN();
 1530 (*Profiler::enabledProfilerReference())->willExecute(exec, LLINT_OP(1).jsValue());
 1531 LLINT_END();
 1532}
 1533
 1534LLINT_HELPER_DECL(helper_profile_did_call)
 1535{
 1536 LLINT_BEGIN();
 1537 (*Profiler::enabledProfilerReference())->didExecute(exec, LLINT_OP(1).jsValue());
 1538 LLINT_END();
 1539}
 1540
 1541} } // namespace JSC::LLInt
 1542
 1543#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 = JSGlobalData::heap + Heap::m_objectSpace + MarkedSpace::m_preciseSizeClasses + sizeClassIndex * sizeof MarkedAllocator
 586
 587 # FIXME: we can get the global data in one load from the stack.
 588 loadp CodeBlock[cfr], scratch1
 589 loadp CodeBlock::m_globalData[scratch1], scratch1
 590
 591 # Get the object from the free list.
 592 loadp offsetOfMySizeClass + MarkedAllocator::m_firstFreeCell[scratch1], result
 593 btpz result, slowCase
 594
 595 # Remove the object from the free list.
 596 loadp [result], scratch2
 597 storep scratch2, offsetOfMySizeClass + MarkedAllocator::m_firstFreeCell[scratch1]
 598
 599 # Initialize the object.
 600 loadp classInfoOffset[scratch1], scratch2
 601 storep scratch2, [result]
 602 storep structure, JSCell::m_structure[result]
 603 storep 0, JSObject::m_inheritorID[result]
 604 addp sizeof JSObject, result, scratch1
 605 storep scratch1, JSObject::m_propertyStorage[result]
 606 end
 607end
 608
 609_llint_op_create_this:
 610 traceExecution()
 611 loadi 8[PC], t0
 612 assertNotConstant(t0)
 613 bineq TagOffset[cfr, t0, 8], CellTag, .opCreateThisSlow
 614 loadi PayloadOffset[cfr, t0, 8], t0
 615 loadp JSCell::m_structure[t0], t1
 616 bbb Structure::m_typeInfo + TypeInfo::m_type[t1], ObjectType, .opCreateThisSlow
 617 loadp JSObject::m_inheritorID[t0], t2
 618 btpz t2, .opCreateThisSlow
 619 allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t2, t0, t1, t3, .opCreateThisSlow)
 620 loadi 4[PC], t1
 621 storei CellTag, TagOffset[cfr, t1, 8]
 622 storei t0, PayloadOffset[cfr, t1, 8]
 623 dispatch(3)
 624
 625.opCreateThisSlow:
 626 callHelper(_llint_helper_create_this)
 627 dispatch(3)
 628
 629
 630_llint_op_get_callee:
 631 traceExecution()
 632 loadi 4[PC], t0
 633 loadp PayloadOffset + Callee[cfr], t1
 634 storei CellTag, TagOffset[cfr, t0, 8]
 635 storei t1, PayloadOffset[cfr, t0, 8]
 636 dispatch(2)
 637
 638
 639_llint_op_convert_this:
 640 traceExecution()
 641 loadi 4[PC], t0
 642 bineq TagOffset[cfr, t0, 8], CellTag, .opConvertThisSlow
 643 loadi PayloadOffset[cfr, t0, 8], t0
 644 loadp JSCell::m_structure[t0], t0
 645 bbb Structure::m_typeInfo + TypeInfo::m_type[t0], ObjectType, .opConvertThisSlow
 646 dispatch(2)
 647
 648.opConvertThisSlow:
 649 callHelper(_llint_helper_convert_this)
 650 dispatch(2)
 651
 652
 653_llint_op_new_object:
 654 traceExecution()
 655 loadp CodeBlock[cfr], t0
 656 loadp CodeBlock::m_globalObject[t0], t0
 657 loadp JSGlobalObject::m_emptyObjectStructure[t0], t1
 658 allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t1, t0, t2, t3, .opNewObjectSlow)
 659 loadi 4[PC], t1
 660 storei CellTag, TagOffset[cfr, t1, 8]
 661 storei t0, PayloadOffset[cfr, t1, 8]
 662 dispatch(2)
 663
 664.opNewObjectSlow:
 665 callHelper(_llint_helper_new_object)
 666 dispatch(2)
 667
 668
 669_llint_op_new_array:
 670 traceExecution()
 671 callHelper(_llint_helper_new_array)
 672 dispatch(4)
 673
 674
 675_llint_op_new_array_buffer:
 676 traceExecution()
 677 callHelper(_llint_helper_new_array_buffer)
 678 dispatch(4)
 679
 680
 681_llint_op_new_regexp:
 682 traceExecution()
 683 callHelper(_llint_helper_new_regexp)
 684 dispatch(3)
 685
 686
 687_llint_op_mov:
 688 traceExecution()
 689 loadi 8[PC], t1
 690 loadi 4[PC], t0
 691 loadConstantOrVariable(t1, t2, t3)
 692 storei t2, TagOffset[cfr, t0, 8]
 693 storei t3, PayloadOffset[cfr, t0, 8]
 694 dispatch(3)
 695
 696
 697_llint_op_not:
 698 traceExecution()
 699 loadi 8[PC], t0
 700 loadi 4[PC], t1
 701 loadConstantOrVariable(t0, t2, t3)
 702 bineq t2, BooleanTag, .opNotSlow
 703 xori 1, t3
 704 storei t2, TagOffset[cfr, t1, 8]
 705 storei t3, PayloadOffset[cfr, t1, 8]
 706 dispatch(3)
 707
 708.opNotSlow:
 709 callHelper(_llint_helper_not)
 710 dispatch(3)
 711
 712
 713_llint_op_eq:
 714 traceExecution()
 715 loadi 12[PC], t2
 716 loadi 8[PC], t0
 717 loadConstantOrVariable(t2, t3, t1)
 718 loadConstantOrVariable2Reg(t0, t2, t0)
 719 bineq t2, t3, .opEqSlow
 720 bieq t2, CellTag, .opEqSlow
 721 bib t2, LowestTag, .opEqSlow
 722 loadi 4[PC], t2
 723 cieq t0, t1, t0
 724 storei BooleanTag, TagOffset[cfr, t2, 8]
 725 storei t0, PayloadOffset[cfr, t2, 8]
 726 dispatch(4)
 727
 728.opEqSlow:
 729 callHelper(_llint_helper_eq)
 730 dispatch(4)
 731
 732
 733_llint_op_eq_null:
 734 traceExecution()
 735 loadi 8[PC], t0
 736 loadi 4[PC], t3
 737 assertNotConstant(t0)
 738 loadi TagOffset[cfr, t0, 8], t1
 739 loadi PayloadOffset[cfr, t0, 8], t0
 740 bineq t1, CellTag, .opEqNullImmediate
 741 loadp JSCell::m_structure[t0], t1
 742 tbnz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1
 743 jmp .opEqNullNotImmediate
 744.opEqNullImmediate:
 745 cieq t1, NullTag, t2
 746 cieq t1, UndefinedTag, t1
 747 ori t2, t1
 748.opEqNullNotImmediate:
 749 storei BooleanTag, TagOffset[cfr, t3, 8]
 750 storei t1, PayloadOffset[cfr, t3, 8]
 751 dispatch(3)
 752
 753
 754_llint_op_neq:
 755 traceExecution()
 756 loadi 12[PC], t2
 757 loadi 8[PC], t0
 758 loadConstantOrVariable(t2, t3, t1)
 759 loadConstantOrVariable2Reg(t0, t2, t0)
 760 bineq t2, t3, .opNeqSlow
 761 bieq t2, CellTag, .opNeqSlow
 762 bib t2, LowestTag, .opNeqSlow
 763 loadi 4[PC], t2
 764 cineq t0, t1, t0
 765 storei BooleanTag, TagOffset[cfr, t2, 8]
 766 storei t0, PayloadOffset[cfr, t2, 8]
 767 dispatch(4)
 768
 769.opNeqSlow:
 770 callHelper(_llint_helper_neq)
 771 dispatch(4)
 772
 773
 774_llint_op_neq_null:
 775 traceExecution()
 776 loadi 8[PC], t0
 777 loadi 4[PC], t3
 778 assertNotConstant(t0)
 779 loadi TagOffset[cfr, t0, 8], t1
 780 loadi PayloadOffset[cfr, t0, 8], t0
 781 bineq t1, CellTag, .opNeqNullImmediate
 782 loadp JSCell::m_structure[t0], t1
 783 tbz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1
 784 jmp .opNeqNullNotImmediate
 785.opNeqNullImmediate:
 786 cineq t1, NullTag, t2
 787 cineq t1, UndefinedTag, t1
 788 andi t2, t1
 789.opNeqNullNotImmediate:
 790 storei BooleanTag, TagOffset[cfr, t3, 8]
 791 storei t1, PayloadOffset[cfr, t3, 8]
 792 dispatch(3)
 793
 794
 795macro strictEq(equalityOperation, helper)
 796 loadi 12[PC], t2
 797 loadi 8[PC], t0
 798 loadConstantOrVariable(t2, t3, t1)
 799 loadConstantOrVariable2Reg(t0, t2, t0)
 800 bineq t2, t3, .slow
 801 bib t2, LowestTag, .slow
 802 bineq t2, CellTag, .notString
 803 loadp JSCell::m_structure[t0], t2
 804 loadp JSCell::m_structure[t1], t3
 805 bbneq Structure::m_typeInfo + TypeInfo::m_type[t2], StringType, .notString
 806 bbeq Structure::m_typeInfo + TypeInfo::m_type[t3], StringType, .slow
 807.notString:
 808 loadi 4[PC], t2
 809 equalityOperation(t0, t1, t0)
 810 storei BooleanTag, TagOffset[cfr, t2, 8]
 811 storei t0, PayloadOffset[cfr, t2, 8]
 812 dispatch(4)
 813
 814.slow:
 815 callHelper(helper)
 816 dispatch(4)
 817end
 818
 819_llint_op_stricteq:
 820 traceExecution()
 821 strictEq(macro (left, right, result) cieq left, right, result end, _llint_helper_stricteq)
 822
 823
 824_llint_op_nstricteq:
 825 traceExecution()
 826 strictEq(macro (left, right, result) cineq left, right, result end, _llint_helper_nstricteq)
 827
 828
 829_llint_op_less:
 830 traceExecution()
 831 callHelper(_llint_helper_less)
 832 dispatch(4)
 833
 834
 835_llint_op_lesseq:
 836 traceExecution()
 837 callHelper(_llint_helper_lesseq)
 838 dispatch(4)
 839
 840
 841_llint_op_greater:
 842 traceExecution()
 843 callHelper(_llint_helper_greater)
 844 dispatch(4)
 845
 846
 847_llint_op_greatereq:
 848 traceExecution()
 849 callHelper(_llint_helper_greatereq)
 850 dispatch(4)
 851
 852
 853_llint_op_pre_inc:
 854 traceExecution()
 855 loadi 4[PC], t0
 856 bineq TagOffset[cfr, t0, 8], Int32Tag, .opPreIncSlow
 857 loadi PayloadOffset[cfr, t0, 8], t1
 858 baddio 1, t1, .opPreIncSlow
 859 storei t1, PayloadOffset[cfr, t0, 8]
 860 dispatch(2)
 861
 862.opPreIncSlow:
 863 callHelper(_llint_helper_pre_inc)
 864 dispatch(2)
 865
 866
 867_llint_op_pre_dec:
 868 traceExecution()
 869 loadi 4[PC], t0
 870 bineq TagOffset[cfr, t0, 8], Int32Tag, .opPreDecSlow
 871 loadi PayloadOffset[cfr, t0, 8], t1
 872 bsubio 1, t1, .opPreDecSlow
 873 storei t1, PayloadOffset[cfr, t0, 8]
 874 dispatch(2)
 875
 876.opPreDecSlow:
 877 callHelper(_llint_helper_pre_dec)
 878 dispatch(2)
 879
 880
 881_llint_op_post_inc:
 882 traceExecution()
 883 loadi 8[PC], t0
 884 loadi 4[PC], t1
 885 bineq TagOffset[cfr, t0, 8], Int32Tag, .opPostIncSlow
 886 bieq t0, t1, .opPostIncDone
 887 loadi PayloadOffset[cfr, t0, 8], t2
 888 move t2, t3
 889 baddio 1, t3, .opPostIncSlow
 890 storei Int32Tag, TagOffset[cfr, t1, 8]
 891 storei t2, PayloadOffset[cfr, t1, 8]
 892 storei t3, PayloadOffset[cfr, t0, 8]
 893.opPostIncDone:
 894 dispatch(3)
 895
 896.opPostIncSlow:
 897 callHelper(_llint_helper_post_inc)
 898 dispatch(3)
 899
 900
 901_llint_op_post_dec:
 902 traceExecution()
 903 loadi 8[PC], t0
 904 loadi 4[PC], t1
 905 bineq TagOffset[cfr, t0, 8], Int32Tag, .opPostDecSlow
 906 bieq t0, t1, .opPostDecDone
 907 loadi PayloadOffset[cfr, t0, 8], t2
 908 move t2, t3
 909 bsubio 1, t3, .opPostDecSlow
 910 storei Int32Tag, TagOffset[cfr, t1, 8]
 911 storei t2, PayloadOffset[cfr, t1, 8]
 912 storei t3, PayloadOffset[cfr, t0, 8]
 913.opPostDecDone:
 914 dispatch(3)
 915
 916.opPostDecSlow:
 917 callHelper(_llint_helper_post_dec)
 918 dispatch(3)
 919
 920
 921_llint_op_to_jsnumber:
 922 traceExecution()
 923 loadi 8[PC], t0
 924 loadi 4[PC], t1
 925 loadConstantOrVariable(t0, t2, t3)
 926 bieq t2, Int32Tag, .opToJsnumberIsInt
 927 biaeq t2, EmptyValueTag, .opToJsnumberSlow
 928.opToJsnumberIsInt:
 929 storei t2, TagOffset[cfr, t1, 8]
 930 storei t3, PayloadOffset[cfr, t1, 8]
 931 dispatch(3)
 932
 933.opToJsnumberSlow:
 934 callHelper(_llint_helper_to_jsnumber)
 935 dispatch(3)
 936
 937
 938_llint_op_negate:
 939 traceExecution()
 940 loadi 8[PC], t0
 941 loadi 4[PC], t3
 942 loadConstantOrVariable(t0, t1, t2)
 943 bineq t1, Int32Tag, .opNegateSrcNotInt
 944 btiz t2, 0x7fffffff, .opNegateSlow
 945 negi t2
 946 storei Int32Tag, TagOffset[cfr, t3, 8]
 947 storei t2, PayloadOffset[cfr, t3, 8]
 948 dispatch(3)
 949.opNegateSrcNotInt:
 950 bia t1, LowestTag, .opNegateSlow
 951 xori 0x80000000, t1
 952 storei t1, TagOffset[cfr, t3, 8]
 953 storei t2, PayloadOffset[cfr, t3, 8]
 954 dispatch(3)
 955
 956.opNegateSlow:
 957 callHelper(_llint_helper_negate)
 958 dispatch(3)
 959
 960
 961macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, helper)
 962 loadi 12[PC], t2
 963 loadi 8[PC], t0
 964 loadConstantOrVariable(t2, t3, t1)
 965 loadConstantOrVariable2Reg(t0, t2, t0)
 966 bineq t2, Int32Tag, .op1NotInt
 967 bineq t3, Int32Tag, .op2NotInt
 968 loadi 4[PC], t2
 969 integerOperationAndStore(t3, t1, t0, .slow, t2)
 970 dispatch(5)
 971
 972.op1NotInt:
 973 # First operand is definitely not an int, the second operand could be anything.
 974 bia t2, LowestTag, .slow
 975 bib t3, LowestTag, .op1NotIntOp2Double
 976 bineq t3, Int32Tag, .slow
 977 ci2d t1, ft1
 978 jmp .op1NotIntReady
 979.op1NotIntOp2Double:
 980 fii2d t1, t3, ft1
 981.op1NotIntReady:
 982 loadi 4[PC], t1
 983 fii2d t0, t2, ft0
 984 doubleOperation(ft1, ft0)
 985 stored ft0, [cfr, t1, 8]
 986 dispatch(5)
 987
 988.op2NotInt:
 989 # First operand is definitely an int, the second operand is definitely not.
 990 loadi 4[PC], t2
 991 bia t3, LowestTag, .slow
 992 ci2d t0, ft0
 993 fii2d t1, t3, ft1
 994 doubleOperation(ft1, ft0)
 995 stored ft0, [cfr, t2, 8]
 996 dispatch(5)
 997
 998.slow:
 999 callHelper(helper)
 1000 dispatch(5)
 1001end
 1002
 1003macro binaryOp(integerOperation, doubleOperation, helper)
 1004 binaryOpCustomStore(
 1005 macro (int32Tag, left, right, slow, index)
 1006 integerOperation(left, right, slow)
 1007 storei int32Tag, TagOffset[cfr, index, 8]
 1008 storei right, PayloadOffset[cfr, index, 8]
 1009 end,
 1010 doubleOperation, helper)
 1011end
 1012
 1013_llint_op_add:
 1014 traceExecution()
 1015 binaryOp(
 1016 macro (left, right, slow) baddio left, right, slow end,
 1017 macro (left, right) addd left, right end,
 1018 _llint_helper_add)
 1019
 1020
 1021_llint_op_mul:
 1022 traceExecution()
 1023 binaryOpCustomStore(
 1024 macro (int32Tag, left, right, slow, index)
 1025 const scratch = int32Tag # We know that we can reuse the int32Tag register since it has a constant.
 1026 move right, scratch
 1027 bmulio left, scratch, slow
 1028 btinz scratch, .done
 1029 bilt left, 0, slow
 1030 bilt right, 0, slow
 1031 .done:
 1032 storei Int32Tag, TagOffset[cfr, index, 8]
 1033 storei scratch, PayloadOffset[cfr, index, 8]
 1034 end,
 1035 macro (left, right) muld left, right end,
 1036 _llint_helper_mul)
 1037
 1038
 1039_llint_op_sub:
 1040 traceExecution()
 1041 binaryOp(
 1042 macro (left, right, slow) bsubio left, right, slow end,
 1043 macro (left, right) subd left, right end,
 1044 _llint_helper_sub)
 1045
 1046
 1047_llint_op_div:
 1048 traceExecution()
 1049 binaryOpCustomStore(
 1050 macro (int32Tag, left, right, slow, index)
 1051 ci2d left, ft0
 1052 ci2d right, ft1
 1053 divd ft0, ft1
 1054 bcd2i ft1, right, .notInt
 1055 storei int32Tag, TagOffset[cfr, index, 8]
 1056 storei right, PayloadOffset[cfr, index, 8]
 1057 jmp .done
 1058 .notInt:
 1059 stored ft1, [cfr, index, 8]
 1060 .done:
 1061 end,
 1062 macro (left, right) divd left, right end,
 1063 _llint_helper_div)
 1064
 1065
 1066_llint_op_mod:
 1067 traceExecution()
 1068 callHelper(_llint_helper_mod)
 1069 dispatch(4)
 1070
 1071
 1072macro bitOp(operation, helper, advance)
 1073 loadi 12[PC], t2
 1074 loadi 8[PC], t0
 1075 loadConstantOrVariable(t2, t3, t1)
 1076 loadConstantOrVariable2Reg(t0, t2, t0)
 1077 bineq t3, Int32Tag, .slow
 1078 bineq t2, Int32Tag, .slow
 1079 loadi 4[PC], t2
 1080 operation(t1, t0, .slow)
 1081 storei t3, TagOffset[cfr, t2, 8]
 1082 storei t0, PayloadOffset[cfr, t2, 8]
 1083 dispatch(advance)
 1084
 1085.slow:
 1086 callHelper(helper)
 1087 dispatch(advance)
 1088end
 1089
 1090_llint_op_lshift:
 1091 traceExecution()
 1092 bitOp(
 1093 macro (left, right, slow) lshifti left, right end,
 1094 _llint_helper_lshift,
 1095 4)
 1096
 1097
 1098_llint_op_rshift:
 1099 traceExecution()
 1100 bitOp(
 1101 macro (left, right, slow) rshifti left, right end,
 1102 _llint_helper_rshift,
 1103 4)
 1104
 1105
 1106_llint_op_urshift:
 1107 traceExecution()
 1108 bitOp(
 1109 macro (left, right, slow)
 1110 urshifti left, right
 1111 bilt right, 0, slow
 1112 end,
 1113 _llint_helper_urshift,
 1114 4)
 1115
 1116
 1117_llint_op_bitand:
 1118 traceExecution()
 1119 bitOp(
 1120 macro (left, right, slow) andi left, right end,
 1121 _llint_helper_bitand,
 1122 5)
 1123
 1124
 1125_llint_op_bitxor:
 1126 traceExecution()
 1127 bitOp(
 1128 macro (left, right, slow) xori left, right end,
 1129 _llint_helper_bitxor,
 1130 5)
 1131
 1132
 1133_llint_op_bitor:
 1134 traceExecution()
 1135 bitOp(
 1136 macro (left, right, slow) ori left, right end,
 1137 _llint_helper_bitor,
 1138 5)
 1139
 1140
 1141_llint_op_bitnot:
 1142 traceExecution()
 1143 loadi 8[PC], t1
 1144 loadi 4[PC], t0
 1145 loadConstantOrVariable(t1, t2, t3)
 1146 bineq t2, Int32Tag, .opBitnotSlow
 1147 noti t3
 1148 storei t2, TagOffset[cfr, t0, 8]
 1149 storei t3, PayloadOffset[cfr, t0, 8]
 1150 dispatch(3)
 1151
 1152.opBitnotSlow:
 1153 callHelper(_llint_helper_bitnot)
 1154 dispatch(3)
 1155
 1156
 1157_llint_op_check_has_instance:
 1158 traceExecution()
 1159 loadi 4[PC], t1
 1160 loadConstantOrVariablePayload(t1, CellTag, t0, .opCheckHasInstanceSlow)
 1161 loadp JSCell::m_structure[t0], t0
 1162 btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsHasInstance, .opCheckHasInstanceSlow
 1163 dispatch(2)
 1164
 1165.opCheckHasInstanceSlow:
 1166 callHelper(_llint_helper_check_has_instance)
 1167 dispatch(2)
 1168
 1169
 1170_llint_op_instanceof:
 1171 traceExecution()
 1172 # Check that baseVal implements the default HasInstance behavior.
 1173 # FIXME: This should be deprecated.
 1174 loadi 12[PC], t1
 1175 loadConstantOrVariablePayloadUnchecked(t1, t0)
 1176 loadp JSCell::m_structure[t0], t0
 1177 btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsDefaultHasInstance, .opInstanceofSlow
 1178
 1179 # Actually do the work.
 1180 loadi 16[PC], t0
 1181 loadi 4[PC], t3
 1182 loadConstantOrVariablePayload(t0, CellTag, t1, .opInstanceofSlow)
 1183 loadp JSCell::m_structure[t1], t2
 1184 bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opInstanceofSlow
 1185 loadi 8[PC], t0
 1186 loadConstantOrVariablePayload(t0, CellTag, t2, .opInstanceofSlow)
 1187
 1188 # Register state: t1 = prototype, t2 = value
 1189 move 1, t0
 1190.opInstanceofLoop:
 1191 loadp JSCell::m_structure[t2], t2
 1192 loadi Structure::m_prototype + PayloadOffset[t2], t2
 1193 bpeq t2, t1, .opInstanceofDone
 1194 btinz t2, .opInstanceofLoop
 1195
 1196 move 0, t0
 1197.opInstanceofDone:
 1198 storei BooleanTag, TagOffset[cfr, t3, 8]
 1199 storei t0, PayloadOffset[cfr, t3, 8]
 1200 dispatch(5)
 1201
 1202.opInstanceofSlow:
 1203 callHelper(_llint_helper_instanceof)
 1204 dispatch(5)
 1205
 1206
 1207_llint_op_typeof:
 1208 traceExecution()
 1209 callHelper(_llint_helper_typeof)
 1210 dispatch(3)
 1211
 1212
 1213_llint_op_is_undefined:
 1214 traceExecution()
 1215 callHelper(_llint_helper_is_undefined)
 1216 dispatch(3)
 1217
 1218
 1219_llint_op_is_boolean:
 1220 traceExecution()
 1221 callHelper(_llint_helper_is_boolean)
 1222 dispatch(3)
 1223
 1224
 1225_llint_op_is_number:
 1226 traceExecution()
 1227 callHelper(_llint_helper_is_number)
 1228 dispatch(3)
 1229
 1230
 1231_llint_op_is_string:
 1232 traceExecution()
 1233 callHelper(_llint_helper_is_string)
 1234 dispatch(3)
 1235
 1236
 1237_llint_op_is_object:
 1238 traceExecution()
 1239 callHelper(_llint_helper_is_object)
 1240 dispatch(3)
 1241
 1242
 1243_llint_op_is_function:
 1244 traceExecution()
 1245 callHelper(_llint_helper_is_function)
 1246 dispatch(3)
 1247
 1248
 1249_llint_op_in:
 1250 traceExecution()
 1251 callHelper(_llint_helper_in)
 1252 dispatch(4)
 1253
 1254
 1255_llint_op_resolve:
 1256 traceExecution()
 1257 callHelper(_llint_helper_resolve)
 1258 dispatch(4)
 1259
 1260
 1261_llint_op_resolve_skip:
 1262 traceExecution()
 1263 callHelper(_llint_helper_resolve_skip)
 1264 dispatch(5)
 1265
 1266
 1267macro resolveGlobal(size, slow)
 1268 # Operands are as follows:
 1269 # 4[PC] Destination for the load.
 1270 # 8[PC] Property identifier index in the code block.
 1271 # 12[PC] Structure pointer, initialized to 0 by bytecode generator.
 1272 # 16[PC] Offset in global object, initialized to 0 by bytecode generator.
 1273 loadp CodeBlock[cfr], t0
 1274 loadp CodeBlock::m_globalObject[t0], t0
 1275 loadp JSCell::m_structure[t0], t1
 1276 bpneq t1, 12[PC], slow
 1277 loadi 16[PC], t1
 1278 loadp JSObject::m_propertyStorage[t0], t0
 1279 loadi TagOffset[t0, t1, 8], t2
 1280 loadi PayloadOffset[t0, t1, 8], t3
 1281 loadi 4[PC], t0
 1282 storei t2, TagOffset[cfr, t0, 8]
 1283 storei t3, PayloadOffset[cfr, t0, 8]
 1284 loadi (size - 1) * 4[PC], t0
 1285 valueProfile(t2, t3, t0)
 1286end
 1287
 1288_llint_op_resolve_global:
 1289 traceExecution()
 1290 resolveGlobal(6, .opResolveGlobalSlow)
 1291 dispatch(6)
 1292
 1293.opResolveGlobalSlow:
 1294 callHelper(_llint_helper_resolve_global)
 1295 dispatch(6)
 1296
 1297
 1298# Gives you the scope in t0, while allowing you to optionally perform additional checks on the
 1299# scopes as they are traversed. scopeCheck() is called with two arguments: the register
 1300# holding the scope, and a register that can be used for scratch. Note that this does not
 1301# use t3, so you can hold stuff in t3 if need be.
 1302macro getScope(deBruijinIndexOperand, scopeCheck)
 1303 loadp ScopeChain + PayloadOffset[cfr], t0
 1304 loadi deBruijinIndexOperand, t2
 1305
 1306 btiz t2, .done
 1307
 1308 loadp CodeBlock[cfr], t1
 1309 bineq CodeBlock::m_codeType[t1], FunctionCode, .loop
 1310 btbz CodeBlock::m_needsFullScopeChain[t1], .loop
 1311
 1312 loadi CodeBlock::m_activationRegister[t1], t1
 1313
 1314 # Need to conditionally skip over one scope.
 1315 bieq TagOffset[cfr, t1, 8], EmptyValueTag, .noActivation
 1316 scopeCheck(t0, t1)
 1317 loadp ScopeChainNode::next[t0], t0
 1318.noActivation:
 1319 subi 1, t2
 1320
 1321 btiz t2, .done
 1322.loop:
 1323 scopeCheck(t0, t1)
 1324 loadp ScopeChainNode::next[t0], t0
 1325 subi 1, t2
 1326 btinz t2, .loop
 1327
 1328.done:
 1329end
 1330
 1331_llint_op_resolve_global_dynamic:
 1332 traceExecution()
 1333 loadp JITStackFrame::globalData[sp], t3
 1334 loadp JSGlobalData::activationStructure[t3], t3
 1335 getScope(
 1336 20[PC],
 1337 macro (scope, scratch)
 1338 loadp ScopeChainNode::object[scope], scratch
 1339 bpneq JSCell::m_structure[scratch], t3, .opResolveGlobalDynamicSuperSlow
 1340 end)
 1341 resolveGlobal(7, .opResolveGlobalDynamicSlow)
 1342 dispatch(7)
 1343
 1344.opResolveGlobalDynamicSuperSlow:
 1345 callHelper(_llint_helper_resolve_for_resolve_global_dynamic)
 1346 dispatch(7)
 1347
 1348.opResolveGlobalDynamicSlow:
 1349 callHelper(_llint_helper_resolve_global_dynamic)
 1350 dispatch(7)
 1351
 1352
 1353_llint_op_get_scoped_var:
 1354 traceExecution()
 1355 # Operands are as follows:
 1356 # 4[PC] Destination for the load.
 1357 # 8[PC] Index of register in the scope.
 1358 # 12[PC] De Bruijin index.
 1359 getScope(12[PC], macro (scope, scratch) end)
 1360 loadi 4[PC], t1
 1361 loadi 8[PC], t2
 1362 loadp ScopeChainNode::object[t0], t0
 1363 loadp JSVariableObject::m_registers[t0], t0
 1364 loadi TagOffset[t0, t2, 8], t3
 1365 loadi PayloadOffset[t0, t2, 8], t0
 1366 storei t3, TagOffset[cfr, t1, 8]
 1367 storei t0, PayloadOffset[cfr, t1, 8]
 1368 loadi 16[PC], t1
 1369 valueProfile(t3, t0, t1)
 1370 dispatch(5)
 1371
 1372
 1373_llint_op_put_scoped_var:
 1374 traceExecution()
 1375 getScope(8[PC], macro (scope, scratch) end)
 1376 loadi 12[PC], t1
 1377 loadConstantOrVariable(t1, t3, t2)
 1378 loadi 4[PC], t1
 1379 writeBarrier(t3, t2)
 1380 loadp ScopeChainNode::object[t0], t0
 1381 loadp JSVariableObject::m_registers[t0], t0
 1382 storei t3, TagOffset[t0, t1, 8]
 1383 storei t2, PayloadOffset[t0, t1, 8]
 1384 dispatch(4)
 1385
 1386
 1387_llint_op_get_global_var:
 1388 traceExecution()
 1389 loadi 8[PC], t1
 1390 loadi 4[PC], t3
 1391 loadp CodeBlock[cfr], t0
 1392 loadp CodeBlock::m_globalObject[t0], t0
 1393 loadp JSGlobalObject::m_registers[t0], t0
 1394 loadi TagOffset[t0, t1, 8], t2
 1395 loadi PayloadOffset[t0, t1, 8], t1
 1396 storei t2, TagOffset[cfr, t3, 8]
 1397 storei t1, PayloadOffset[cfr, t3, 8]
 1398 loadi 12[PC], t3
 1399 valueProfile(t2, t1, t3)
 1400 dispatch(4)
 1401
 1402
 1403_llint_op_put_global_var:
 1404 traceExecution()
 1405 loadi 8[PC], t1
 1406 loadp CodeBlock[cfr], t0
 1407 loadp CodeBlock::m_globalObject[t0], t0
 1408 loadp JSGlobalObject::m_registers[t0], t0
 1409 loadConstantOrVariable(t1, t2, t3)
 1410 loadi 4[PC], t1
 1411 writeBarrier(t2, t3)
 1412 storei t2, TagOffset[t0, t1, 8]
 1413 storei t3, PayloadOffset[t0, t1, 8]
 1414 dispatch(3)
 1415
 1416
 1417_llint_op_resolve_base:
 1418 traceExecution()
 1419 callHelper(_llint_helper_resolve_base)
 1420 dispatch(5)
 1421
 1422
 1423_llint_op_ensure_property_exists:
 1424 traceExecution()
 1425 callHelper(_llint_helper_ensure_property_exists)
 1426 dispatch(3)
 1427
 1428
 1429_llint_op_resolve_with_base:
 1430 traceExecution()
 1431 callHelper(_llint_helper_resolve_with_base)
 1432 dispatch(5)
 1433
 1434
 1435_llint_op_resolve_with_this:
 1436 traceExecution()
 1437 callHelper(_llint_helper_resolve_with_this)
 1438 dispatch(5)
 1439
 1440
 1441_llint_op_get_by_id:
 1442 traceExecution()
 1443 # We only do monomorphic get_by_id caching for now, and we do not modify the
 1444 # opcode. We do, however, allow for the cache to change anytime if fails, since
 1445 # ping-ponging is free. At best we get lucky and the get_by_id will continue
 1446 # to take fast path on the new cache. At worst we take slow path, which is what
 1447 # we would have been doing anyway.
 1448 loadi 8[PC], t0
 1449 loadi 16[PC], t1
 1450 loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdSlow)
 1451 loadi 20[PC], t2
 1452 loadp JSObject::m_propertyStorage[t3], t0
 1453 bpneq JSCell::m_structure[t3], t1, .opGetByIdSlow
 1454 loadi 4[PC], t1
 1455 loadi TagOffset[t0, t2], t3
 1456 loadi PayloadOffset[t0, t2], t2
 1457 storei t3, TagOffset[cfr, t1, 8]
 1458 storei t2, PayloadOffset[cfr, t1, 8]
 1459 loadi 32[PC], t1
 1460 valueProfile(t3, t2, t1)
 1461 dispatch(9)
 1462
 1463.opGetByIdSlow:
 1464 callHelper(_llint_helper_get_by_id)
 1465 dispatch(9)
 1466
 1467
 1468_llint_op_get_arguments_length:
 1469 traceExecution()
 1470 loadi 8[PC], t0
 1471 loadi 4[PC], t1
 1472 bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opGetArgumentsLengthSlow
 1473 loadi ArgumentCount + PayloadOffset[cfr], t2
 1474 subi 1, t2
 1475 storei Int32Tag, TagOffset[cfr, t1, 8]
 1476 storei t2, PayloadOffset[cfr, t1, 8]
 1477 dispatch(4)
 1478
 1479.opGetArgumentsLengthSlow:
 1480 callHelper(_llint_helper_get_arguments_length)
 1481 dispatch(4)
 1482
 1483
 1484_llint_op_put_by_id:
 1485 traceExecution()
 1486 loadi 4[PC], t3
 1487 loadi 16[PC], t1
 1488 loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow)
 1489 loadi 12[PC], t2
 1490 loadp JSObject::m_propertyStorage[t0], t3
 1491 bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow
 1492 loadi 20[PC], t1
 1493 loadConstantOrVariable2Reg(t2, t0, t2)
 1494 writeBarrier(t0, t2)
 1495 storei t0, TagOffset[t3, t1]
 1496 storei t2, PayloadOffset[t3, t1]
 1497 dispatch(9)
 1498
 1499.opPutByIdSlow:
 1500 callHelper(_llint_helper_put_by_id)
 1501 dispatch(9)
 1502
 1503
 1504macro putByIdTransition(additionalChecks)
 1505 traceExecution()
 1506 loadi 4[PC], t3
 1507 loadi 16[PC], t1
 1508 loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow)
 1509 loadi 12[PC], t2
 1510 bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow
 1511 additionalChecks(t1, t3, .opPutByIdSlow)
 1512 loadi 20[PC], t1
 1513 loadp JSObject::m_propertyStorage[t0], t3
 1514 addp t1, t3
 1515 loadConstantOrVariable2Reg(t2, t1, t2)
 1516 writeBarrier(t1, t2)
 1517 storei t1, TagOffset[t3]
 1518 loadi 24[PC], t1
 1519 storei t2, PayloadOffset[t3]
 1520 storep t1, JSCell::m_structure[t0]
 1521 dispatch(9)
 1522end
 1523
 1524_llint_op_put_by_id_transition_direct:
 1525 putByIdTransition(macro (oldStructure, scratch, slow) end)
 1526
 1527
 1528_llint_op_put_by_id_transition_normal:
 1529 putByIdTransition(
 1530 macro (oldStructure, scratch, slow)
 1531 const protoCell = oldStructure # Reusing the oldStructure register for the proto
 1532
 1533 loadp 28[PC], scratch
 1534 assert(macro (ok) btpnz scratch, ok end)
 1535 loadp StructureChain::m_vector[scratch], scratch
 1536 assert(macro (ok) btpnz scratch, ok end)
 1537 bieq Structure::m_prototype + TagOffset[oldStructure], NullTag, .done
 1538 .loop:
 1539 loadi Structure::m_prototype + PayloadOffset[oldStructure], protoCell
 1540 loadp JSCell::m_structure[protoCell], oldStructure
 1541 bpneq oldStructure, [scratch], slow
 1542 addp 4, scratch
 1543 bineq Structure::m_prototype + TagOffset[oldStructure], NullTag, .loop
 1544 .done:
 1545 end)
 1546
 1547
 1548_llint_op_del_by_id:
 1549 traceExecution()
 1550 callHelper(_llint_helper_del_by_id)
 1551 dispatch(4)
 1552
 1553
 1554_llint_op_get_by_val:
 1555 traceExecution()
 1556 loadp CodeBlock[cfr], t1
 1557 loadi 8[PC], t2
 1558 loadi 12[PC], t3
 1559 loadp CodeBlock::m_globalData[t1], t1
 1560 loadConstantOrVariablePayload(t2, CellTag, t0, .opGetByValSlow)
 1561 loadp JSGlobalData::jsArrayClassInfo[t1], t2
 1562 loadConstantOrVariablePayload(t3, Int32Tag, t1, .opGetByValSlow)
 1563 bpneq [t0], t2, .opGetByValSlow
 1564 loadp JSArray::m_storage[t0], t3
 1565 biaeq t1, JSArray::m_vectorLength[t0], .opGetByValSlow
 1566 loadi 4[PC], t0
 1567 loadi ArrayStorage::m_vector + TagOffset[t3, t1, 8], t2
 1568 loadi ArrayStorage::m_vector + PayloadOffset[t3, t1, 8], t1
 1569 bieq t2, EmptyValueTag, .opGetByValSlow
 1570 storei t2, TagOffset[cfr, t0, 8]
 1571 storei t1, PayloadOffset[cfr, t0, 8]
 1572 loadi 16[PC], t0
 1573 valueProfile(t2, t1, t0)
 1574 dispatch(5)
 1575
 1576.opGetByValSlow:
 1577 callHelper(_llint_helper_get_by_val)
 1578 dispatch(5)
 1579
 1580
 1581_llint_op_get_argument_by_val:
 1582 traceExecution()
 1583 loadi 8[PC], t0
 1584 loadi 12[PC], t1
 1585 bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opGetArgumentByValSlow
 1586 loadConstantOrVariablePayload(t1, Int32Tag, t2, .opGetArgumentByValSlow)
 1587 addi 1, t2
 1588 loadi ArgumentCount + PayloadOffset[cfr], t1
 1589 biaeq t2, t1, .opGetArgumentByValSlow
 1590 negi t2
 1591 loadi 4[PC], t3
 1592 loadi ThisArgumentOffset + TagOffset[cfr, t2, 8], t0
 1593 loadi ThisArgumentOffset + PayloadOffset[cfr, t2, 8], t1
 1594 storei t0, TagOffset[cfr, t3, 8]
 1595 storei t1, PayloadOffset[cfr, t3, 8]
 1596 dispatch(5)
 1597
 1598.opGetArgumentByValSlow:
 1599 callHelper(_llint_helper_get_argument_by_val)
 1600 dispatch(5)
 1601
 1602
 1603_llint_op_get_by_pname:
 1604 traceExecution()
 1605 loadi 12[PC], t0
 1606 loadConstantOrVariablePayload(t0, CellTag, t1, .opGetByPnameSlow)
 1607 loadi 16[PC], t0
 1608 bpneq t1, PayloadOffset[cfr, t0, 8], .opGetByPnameSlow
 1609 loadi 8[PC], t0
 1610 loadConstantOrVariablePayload(t0, CellTag, t2, .opGetByPnameSlow)
 1611 loadi 20[PC], t0
 1612 loadi PayloadOffset[cfr, t0, 8], t3
 1613 loadp JSCell::m_structure[t2], t0
 1614 bpneq t0, JSPropertyNameIterator::m_cachedStructure[t3], .opGetByPnameSlow
 1615 loadi 24[PC], t0
 1616 loadi [cfr, t0, 8], t0
 1617 subi 1, t0
 1618 biaeq t0, JSPropertyNameIterator::m_numCacheableSlots[t3], .opGetByPnameSlow
 1619 loadp JSObject::m_propertyStorage[t2], t2
 1620 loadi TagOffset[t2, t0, 8], t1
 1621 loadi PayloadOffset[t2, t0, 8], t3
 1622 loadi 4[PC], t0
 1623 storei t1, TagOffset[cfr, t0, 8]
 1624 storei t3, PayloadOffset[cfr, t0, 8]
 1625 dispatch(7)
 1626
 1627.opGetByPnameSlow:
 1628 callHelper(_llint_helper_get_by_pname)
 1629 dispatch(7)
 1630
 1631
 1632_llint_op_put_by_val:
 1633 traceExecution()
 1634 loadi 4[PC], t0
 1635 loadConstantOrVariablePayload(t0, CellTag, t1, .opPutByValSlow)
 1636 loadi 8[PC], t0
 1637 loadConstantOrVariablePayload(t0, Int32Tag, t2, .opPutByValSlow)
 1638 loadp CodeBlock[cfr], t0
 1639 loadp CodeBlock::m_globalData[t0], t0
 1640 loadp JSGlobalData::jsArrayClassInfo[t0], t0
 1641 bpneq [t1], t0, .opPutByValSlow
 1642 biaeq t2, JSArray::m_vectorLength[t1], .opPutByValSlow
 1643 loadp JSArray::m_storage[t1], t0
 1644 bieq ArrayStorage::m_vector + TagOffset[t0, t2, 8], EmptyValueTag, .opPutByValEmpty
 1645.opPutByValStoreResult:
 1646 loadi 12[PC], t3
 1647 loadConstantOrVariable2Reg(t3, t1, t3)
 1648 writeBarrier(t1, t3)
 1649 storei t1, ArrayStorage::m_vector + TagOffset[t0, t2, 8]
 1650 storei t3, ArrayStorage::m_vector + PayloadOffset[t0, t2, 8]
 1651 dispatch(4)
 1652
 1653.opPutByValEmpty:
 1654 addi 1, ArrayStorage::m_numValuesInVector[t0]
 1655 bib t2, ArrayStorage::m_length[t0], .opPutByValStoreResult
 1656 addi 1, t2, t1
 1657 storei t1, ArrayStorage::m_length[t0]
 1658 jmp .opPutByValStoreResult
 1659
 1660.opPutByValSlow:
 1661 callHelper(_llint_helper_put_by_val)
 1662 dispatch(4)
 1663
 1664
 1665_llint_op_del_by_val:
 1666 traceExecution()
 1667 callHelper(_llint_helper_del_by_val)
 1668 dispatch(4)
 1669
 1670
 1671_llint_op_put_by_index:
 1672 traceExecution()
 1673 callHelper(_llint_helper_put_by_index)
 1674 dispatch(4)
 1675
 1676
 1677_llint_op_put_getter_setter:
 1678 traceExecution()
 1679 callHelper(_llint_helper_put_getter_setter)
 1680 dispatch(5)
 1681
 1682
 1683_llint_op_loop:
 1684 nop
 1685_llint_op_jmp:
 1686 traceExecution()
 1687 dispatchBranch(4[PC])
 1688
 1689
 1690_llint_op_jmp_scopes:
 1691 traceExecution()
 1692 callHelper(_llint_helper_jmp_scopes)
 1693 dispatch(0)
 1694
 1695
 1696macro jumpTrueOrFalse(conditionOp, slow)
 1697 loadi 4[PC], t1
 1698 loadConstantOrVariablePayload(t1, BooleanTag, t0, .slow)
 1699 conditionOp(t0, .target)
 1700 dispatch(3)
 1701
 1702.target:
 1703 dispatchBranch(8[PC])
 1704
 1705.slow:
 1706 callHelper(slow)
 1707 dispatch(0)
 1708end
 1709
 1710_llint_op_loop_if_true:
 1711 nop
 1712_llint_op_jtrue:
 1713 traceExecution()
 1714 jumpTrueOrFalse(
 1715 macro (value, target) btinz value, target end,
 1716 _llint_helper_jtrue)
 1717
 1718
 1719_llint_op_loop_if_false:
 1720 nop
 1721_llint_op_jfalse:
 1722 traceExecution()
 1723 jumpTrueOrFalse(
 1724 macro (value, target) btiz value, target end,
 1725 _llint_helper_jfalse)
 1726
 1727
 1728macro equalNull(cellHandler, immediateHandler)
 1729 loadi 4[PC], t0
 1730 loadi TagOffset[cfr, t0, 8], t1
 1731 loadi PayloadOffset[cfr, t0, 8], t0
 1732 bineq t1, CellTag, .immediate
 1733 loadp JSCell::m_structure[t0], t2
 1734 cellHandler(Structure::m_typeInfo + TypeInfo::m_flags[t2], .target)
 1735 dispatch(3)
 1736
 1737.target:
 1738 dispatchBranch(8[PC])
 1739
 1740.immediate:
 1741 ori 1, t1
 1742 immediateHandler(t1, .target)
 1743 dispatch(3)
 1744end
 1745
 1746_llint_op_jeq_null:
 1747 traceExecution()
 1748 equalNull(
 1749 macro (value, target) btbnz value, MasqueradesAsUndefined, target end,
 1750 macro (value, target) bieq value, NullTag, target end)
 1751
 1752
 1753_llint_op_jneq_null:
 1754 traceExecution()
 1755 equalNull(
 1756 macro (value, target) btbz value, MasqueradesAsUndefined, target end,
 1757 macro (value, target) bineq value, NullTag, target end)
 1758
 1759
 1760_llint_op_jneq_ptr:
 1761 traceExecution()
 1762 loadi 4[PC], t0
 1763 loadi 8[PC], t1
 1764 bineq TagOffset[cfr, t0, 8], CellTag, .opJneqPtrBranch
 1765 bpeq PayloadOffset[cfr, t0, 8], t1, .opJneqPtrFallThrough
 1766.opJneqPtrBranch:
 1767 dispatchBranch(12[PC])
 1768.opJneqPtrFallThrough:
 1769 dispatch(4)
 1770
 1771
 1772macro compare(integerCompare, doubleCompare, helper)
 1773 loadi 4[PC], t2
 1774 loadi 8[PC], t3
 1775 loadConstantOrVariable(t2, t0, t1)
 1776 loadConstantOrVariable2Reg(t3, t2, t3)
 1777 bineq t0, Int32Tag, .op1NotInt
 1778 bineq t2, Int32Tag, .op2NotInt
 1779 integerCompare(t1, t3, .jumpTarget)
 1780 dispatch(4)
 1781
 1782.op1NotInt:
 1783 bia t0, LowestTag, .slow
 1784 bib t2, LowestTag, .op1NotIntOp2Double
 1785 bineq t2, Int32Tag, .slow
 1786 ci2d t3, ft1
 1787 jmp .op1NotIntReady
 1788.op1NotIntOp2Double:
 1789 fii2d t3, t2, ft1
 1790.op1NotIntReady:
 1791 fii2d t1, t0, ft0
 1792 doubleCompare(ft0, ft1, .jumpTarget)
 1793 dispatch(4)
 1794
 1795.op2NotInt:
 1796 ci2d t1, ft0
 1797 bia t2, LowestTag, .slow
 1798 fii2d t3, t2, ft1
 1799 doubleCompare(ft0, ft1, .jumpTarget)
 1800 dispatch(4)
 1801
 1802.jumpTarget:
 1803 dispatchBranch(12[PC])
 1804
 1805.slow:
 1806 callHelper(helper)
 1807 dispatch(0)
 1808end
 1809
 1810_llint_op_loop_if_less:
 1811 nop
 1812_llint_op_jless:
 1813 traceExecution()
 1814 compare(
 1815 macro (left, right, target) bilt left, right, target end,
 1816 macro (left, right, target) bdlt left, right, target end,
 1817 _llint_helper_jless)
 1818
 1819
 1820_llint_op_jnless:
 1821 traceExecution()
 1822 compare(
 1823 macro (left, right, target) bigteq left, right, target end,
 1824 macro (left, right, target) bdgtequn left, right, target end,
 1825 _llint_helper_jnless)
 1826
 1827
 1828_llint_op_loop_if_greater:
 1829 nop
 1830_llint_op_jgreater:
 1831 traceExecution()
 1832 compare(
 1833 macro (left, right, target) bigt left, right, target end,
 1834 macro (left, right, target) bdgt left, right, target end,
 1835 _llint_helper_jgreater)
 1836
 1837
 1838_llint_op_jngreater:
 1839 traceExecution()
 1840 compare(
 1841 macro (left, right, target) bilteq left, right, target end,
 1842 macro (left, right, target) bdltequn left, right, target end,
 1843 _llint_helper_jngreater)
 1844
 1845
 1846_llint_op_loop_if_lesseq:
 1847 nop
 1848_llint_op_jlesseq:
 1849 traceExecution()
 1850 compare(
 1851 macro (left, right, target) bilteq left, right, target end,
 1852 macro (left, right, target) bdlteq left, right, target end,
 1853 _llint_helper_jlesseq)
 1854
 1855
 1856_llint_op_jnlesseq:
 1857 traceExecution()
 1858 compare(
 1859 macro (left, right, target) bigt left, right, target end,
 1860 macro (left, right, target) bdgtun left, right, target end,
 1861 _llint_helper_jnlesseq)
 1862
 1863
 1864_llint_op_loop_if_greatereq:
 1865 nop
 1866_llint_op_jgreatereq:
 1867 traceExecution()
 1868 compare(
 1869 macro (left, right, target) bigteq left, right, target end,
 1870 macro (left, right, target) bdgteq left, right, target end,
 1871 _llint_helper_jgreatereq)
 1872
 1873
 1874_llint_op_jngreatereq:
 1875 traceExecution()
 1876 compare(
 1877 macro (left, right, target) bilt left, right, target end,
 1878 macro (left, right, target) bdltun left, right, target end,
 1879 _llint_helper_jngreatereq)
 1880
 1881
 1882_llint_op_loop_hint:
 1883 traceExecution()
 1884 checkSwitchToJITForLoop()
 1885 dispatch(1)
 1886
 1887
 1888_llint_op_switch_imm:
 1889 traceExecution()
 1890 loadi 12[PC], t2
 1891 loadi 4[PC], t3
 1892 loadConstantOrVariable(t2, t1, t0)
 1893 loadp CodeBlock[cfr], t2
 1894 loadp CodeBlock::m_rareData[t2], t2
 1895 muli sizeof SimpleJumpTable, t3 # FIXME: would be nice to peephole this!
 1896 loadp CodeBlock::RareData::m_immediateSwitchJumpTables + VectorBufferOffset[t2], t2
 1897 addp t3, t2
 1898 bineq t1, Int32Tag, .opSwitchImmNotInt
 1899 subi SimpleJumpTable::min[t2], t0
 1900 biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchImmFallThrough
 1901 loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t3
 1902 loadi [t3, t0, 4], t1
 1903 btiz t1, .opSwitchImmFallThrough
 1904 dispatchBranchWithOffset(t1)
 1905
 1906.opSwitchImmNotInt:
 1907 bib t1, LowestTag, .opSwitchImmSlow # Go to slow path if it's a double.
 1908.opSwitchImmFallThrough:
 1909 dispatchBranch(8[PC])
 1910
 1911.opSwitchImmSlow:
 1912 callHelper(_llint_helper_switch_imm)
 1913 dispatch(0)
 1914
 1915
 1916_llint_op_switch_char:
 1917 traceExecution()
 1918 loadi 12[PC], t2
 1919 loadi 4[PC], t3
 1920 loadConstantOrVariable(t2, t1, t0)
 1921 loadp CodeBlock[cfr], t2
 1922 loadp CodeBlock::m_rareData[t2], t2
 1923 muli sizeof SimpleJumpTable, t3
 1924 loadp CodeBlock::RareData::m_characterSwitchJumpTables + VectorBufferOffset[t2], t2
 1925 addp t3, t2
 1926 bineq t1, CellTag, .opSwitchCharFallThrough
 1927 loadp JSCell::m_structure[t0], t1
 1928 bbneq Structure::m_typeInfo + TypeInfo::m_type[t1], StringType, .opSwitchCharFallThrough
 1929 loadp JSString::m_value[t0], t0
 1930 bineq StringImpl::m_length[t0], 1, .opSwitchCharFallThrough
 1931 loadp StringImpl::m_data8[t0], t1
 1932 btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit
 1933 loadh [t1], t0
 1934 jmp .opSwitchCharReady
 1935.opSwitchChar8Bit:
 1936 loadb [t1], t0
 1937.opSwitchCharReady:
 1938 subi SimpleJumpTable::min[t2], t0
 1939 biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchCharFallThrough
 1940 loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t2
 1941 loadi [t2, t0, 4], t1
 1942 btiz t1, .opSwitchImmFallThrough
 1943 dispatchBranchWithOffset(t1)
 1944
 1945.opSwitchCharFallThrough:
 1946 dispatchBranch(8[PC])
 1947
 1948
 1949_llint_op_switch_string:
 1950 traceExecution()
 1951 callHelper(_llint_helper_switch_string)
 1952 dispatch(0)
 1953
 1954
 1955_llint_op_new_func:
 1956 traceExecution()
 1957 btiz 12[PC], .opNewFuncUnchecked
 1958 loadi 4[PC], t1
 1959 bineq TagOffset[cfr, t1, 8], EmptyValueTag, .opNewFuncDone
 1960.opNewFuncUnchecked:
 1961 callHelper(_llint_helper_new_func)
 1962.opNewFuncDone:
 1963 dispatch(4)
 1964
 1965
 1966_llint_op_new_func_exp:
 1967 traceExecution()
 1968 callHelper(_llint_helper_new_func_exp)
 1969 dispatch(3)
 1970
 1971
 1972macro doCall(helper)
 1973 loadi 4[PC], t0
 1974 loadi 16[PC], t1
 1975 loadp LLIntCallLinkInfo::callee[t1], t2
 1976 loadConstantOrVariablePayload(t0, CellTag, t3, .opCallSlow)
 1977 bineq t3, t2, .opCallSlow
 1978 loadi 12[PC], t3
 1979 addp 24, PC
 1980 lshifti 3, t3
 1981 addp cfr, t3 # t3 contains the new value of cfr
 1982 loadp JSFunction::m_scopeChain[t2], t0
 1983 storei t2, Callee + PayloadOffset[t3]
 1984 storei t0, ScopeChain + PayloadOffset[t3]
 1985 loadi 8 - 24[PC], t2
 1986 storei PC, ArgumentCount + TagOffset[cfr]
 1987 storep cfr, CallerFrame[t3]
 1988 storei t2, ArgumentCount + PayloadOffset[t3]
 1989 storei CellTag, Callee + TagOffset[t3]
 1990 storei CellTag, ScopeChain + TagOffset[t3]
 1991 move t3, cfr
 1992 call LLIntCallLinkInfo::machineCodeTarget[t1]
 1993 dispatchAfterCall()
 1994
 1995.opCallSlow:
 1996 slowPathForCall(6, helper)
 1997end
 1998
 1999_llint_op_call:
 2000 traceExecution()
 2001 doCall(_llint_helper_call)
 2002
 2003
 2004_llint_op_construct:
 2005 traceExecution()
 2006 doCall(_llint_helper_construct)
 2007
 2008
 2009_llint_op_call_varargs:
 2010 traceExecution()
 2011 slowPathForCall(6, _llint_helper_call_varargs)
 2012
 2013
 2014_llint_op_call_eval:
 2015 traceExecution()
 2016
 2017 # Eval is executed in one of two modes:
 2018 #
 2019 # 1) We find that we're really invoking eval() in which case the
 2020 # execution is perfomed entirely inside the helper, and it
 2021 # returns the PC of a function that just returns the return value
 2022 # that the eval returned.
 2023 #
 2024 # 2) We find that we're invoking something called eval() that is not
 2025 # the real eval. Then the helper returns the PC of the thing to
 2026 # call, and we call it.
 2027 #
 2028 # This allows us to handle two cases, which would require a total of
 2029 # up to four pieces of state that cannot be easily packed into two
 2030 # registers (C functions can return up to two registers, easily):
 2031 #
 2032 # - The call frame register. This may or may not have been modified
 2033 # by the helper, but the convention is that it returns it. It's not
 2034 # totally clear if that's necessary, since the cfr is callee save.
 2035 # But that's our style in this here interpreter so we stick with it.
 2036 #
 2037 # - A bit to say if the helper successfully executed the eval and has
 2038 # the return value, or did not execute the eval but has a PC for us
 2039 # to call.
 2040 #
 2041 # - Either:
 2042 # - The JS return value (two registers), or
 2043 #
 2044 # - The PC to call.
 2045 #
 2046 # It turns out to be easier to just always have this return the cfr
 2047 # and a PC to call, and that PC may be a dummy thunk that just
 2048 # returns the JS value that the eval returned.
 2049
 2050 slowPathForCall(4, _llint_helper_call_eval)
 2051
 2052
 2053_llint_generic_return_point:
 2054 dispatchAfterCall()
 2055
 2056
 2057_llint_op_tear_off_activation:
 2058 traceExecution()
 2059 loadi 4[PC], t0
 2060 loadi 8[PC], t1
 2061 bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opTearOffActivationCreated
 2062 bieq TagOffset[cfr, t1, 8], EmptyValueTag, .opTearOffActivationNotCreated
 2063.opTearOffActivationCreated:
 2064 callHelper(_llint_helper_tear_off_activation)
 2065.opTearOffActivationNotCreated:
 2066 dispatch(3)
 2067
 2068
 2069_llint_op_tear_off_arguments:
 2070 traceExecution()
 2071 loadi 4[PC], t0
 2072 subi 1, t0 # Get the unmodifiedArgumentsRegister
 2073 bieq TagOffset[cfr, t0, 8], EmptyValueTag, .opTearOffArgumentsNotCreated
 2074 callHelper(_llint_helper_tear_off_arguments)
 2075.opTearOffArgumentsNotCreated:
 2076 dispatch(2)
 2077
 2078
 2079macro doReturn()
 2080 loadp ReturnPC[cfr], t2
 2081 loadp CallerFrame[cfr], cfr
 2082 restoreReturnAddressBeforeReturn(t2)
 2083 ret
 2084end
 2085
 2086_llint_op_ret:
 2087 traceExecution()
 2088 checkSwitchToJITForEpilogue()
 2089 loadi 4[PC], t2
 2090 loadConstantOrVariable(t2, t1, t0)
 2091 doReturn()
 2092
 2093
 2094_llint_op_call_put_result:
 2095 loadi 4[PC], t2
 2096 loadi 8[PC], t3
 2097 storei t1, TagOffset[cfr, t2, 8]
 2098 storei t0, PayloadOffset[cfr, t2, 8]
 2099 valueProfile(t1, t0, t3)
 2100 traceExecution() # Needs to be here because it would clobber t1, t0
 2101 dispatch(3)
 2102
 2103
 2104_llint_op_ret_object_or_this:
 2105 traceExecution()
 2106 checkSwitchToJITForEpilogue()
 2107 loadi 4[PC], t2
 2108 loadConstantOrVariable(t2, t1, t0)
 2109 bineq t1, CellTag, .opRetObjectOrThisNotObject
 2110 loadp JSCell::m_structure[t0], t2
 2111 bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opRetObjectOrThisNotObject
 2112 doReturn()
 2113
 2114.opRetObjectOrThisNotObject:
 2115 loadi 8[PC], t2
 2116 loadConstantOrVariable(t2, t1, t0)
 2117 doReturn()
 2118
 2119
 2120_llint_op_method_check:
 2121 traceExecution()
 2122 # We ignore method checks and use normal get_by_id optimizations.
 2123 dispatch(1)
 2124
 2125
 2126_llint_op_strcat:
 2127 traceExecution()
 2128 callHelper(_llint_helper_strcat)
 2129 dispatch(4)
 2130
 2131
 2132_llint_op_to_primitive:
 2133 traceExecution()
 2134 loadi 8[PC], t2
 2135 loadi 4[PC], t3
 2136 loadConstantOrVariable(t2, t1, t0)
 2137 bineq t1, CellTag, .opToPrimitiveIsImm
 2138 loadp JSCell::m_structure[t0], t2
 2139 bbneq Structure::m_typeInfo + TypeInfo::m_type[t2], StringType, .opToPrimitiveSlowCase
 2140.opToPrimitiveIsImm:
 2141 storei t1, TagOffset[cfr, t3, 8]
 2142 storei t0, PayloadOffset[cfr, t3, 8]
 2143 dispatch(3)
 2144
 2145.opToPrimitiveSlowCase:
 2146 callHelper(_llint_helper_to_primitive)
 2147 dispatch(3)
 2148
 2149
 2150_llint_op_get_pnames:
 2151 traceExecution()
 2152 callHelper(_llint_helper_get_pnames)
 2153 dispatch(0) # The helper either advances the PC or jumps us to somewhere else.
 2154
 2155
 2156_llint_op_next_pname:
 2157 traceExecution()
 2158 loadi 12[PC], t1
 2159 loadi 16[PC], t2
 2160 loadi PayloadOffset[cfr, t1, 8], t0
 2161 bieq t0, PayloadOffset[cfr, t2, 8], .opNextPnameEnd
 2162 loadi 20[PC], t2
 2163 loadi PayloadOffset[cfr, t2, 8], t2
 2164 loadp JSPropertyNameIterator::m_jsStrings[t2], t3
 2165 loadi [t3, t0, 8], t3
 2166 addi 1, t0
 2167 storei t0, PayloadOffset[cfr, t1, 8]
 2168 loadi 4[PC], t1
 2169 storei CellTag, TagOffset[cfr, t1, 8]
 2170 storei t3, PayloadOffset[cfr, t1, 8]
 2171 loadi 8[PC], t3
 2172 loadi PayloadOffset[cfr, t3, 8], t3
 2173 loadp JSCell::m_structure[t3], t1
 2174 bpneq t1, JSPropertyNameIterator::m_cachedStructure[t2], .opNextPnameSlow
 2175 loadp JSPropertyNameIterator::m_cachedPrototypeChain[t2], t0
 2176 loadp StructureChain::m_vector[t0], t0
 2177 btpz [t0], .opNextPnameTarget
 2178.opNextPnameCheckPrototypeLoop:
 2179 bieq Structure::m_prototype + TagOffset[t1], NullTag, .opNextPnameSlow
 2180 loadp Structure::m_prototype + PayloadOffset[t1], t2
 2181 loadp JSCell::m_structure[t2], t1
 2182 bpneq t1, [t0], .opNextPnameSlow
 2183 addp 4, t0
 2184 btpnz [t0], .opNextPnameCheckPrototypeLoop
 2185.opNextPnameTarget:
 2186 dispatchBranch(24[PC])
 2187
 2188.opNextPnameEnd:
 2189 dispatch(7)
 2190
 2191.opNextPnameSlow:
 2192 callHelper(_llint_helper_next_pname) # This either keeps the PC where it was (causing us to loop) or sets it to target.
 2193 dispatch(0)
 2194
 2195
 2196_llint_op_push_scope:
 2197 traceExecution()
 2198 callHelper(_llint_helper_push_scope)
 2199 dispatch(2)
 2200
 2201
 2202_llint_op_pop_scope:
 2203 traceExecution()
 2204 callHelper(_llint_helper_pop_scope)
 2205 dispatch(1)
 2206
 2207
 2208_llint_op_push_new_scope:
 2209 traceExecution()
 2210 callHelper(_llint_helper_push_new_scope)
 2211 dispatch(4)
 2212
 2213
 2214_llint_op_catch:
 2215 # This is where we end up from the JIT's throw trampoline (because the
 2216 # machine code return address will be set to _llint_op_catch), and from
 2217 # the interpreter's throw trampoline (see _llint_throw_trampoline).
 2218 # The JIT throwing protocol calls for the cfr to be in t0. The throwing
 2219 # code must have known that we were throwing to the interpreter, and have
 2220 # set JSGlobalData::targetInterpreterPCForThrow.
 2221 move t0, cfr
 2222 loadp JITStackFrame::globalData[sp], t3
 2223 loadi JSGlobalData::targetInterpreterPCForThrow[t3], PC
 2224 loadi JSGlobalData::exception + PayloadOffset[t3], t0
 2225 loadi JSGlobalData::exception + TagOffset[t3], t1
 2226 storei 0, JSGlobalData::exception + PayloadOffset[t3]
 2227 storei EmptyValueTag, JSGlobalData::exception + TagOffset[t3]
 2228 loadi 4[PC], t2
 2229 storei t0, PayloadOffset[cfr, t2, 8]
 2230 storei t1, TagOffset[cfr, t2, 8]
 2231 traceExecution() # This needs to be here because we don't want to clobber t0, t1, t2, t3 above.
 2232 dispatch(2)
 2233
 2234
 2235_llint_op_throw:
 2236 traceExecution()
 2237 callHelper(_llint_helper_throw)
 2238 dispatch(2)
 2239
 2240
 2241_llint_op_throw_reference_error:
 2242 traceExecution()
 2243 callHelper(_llint_helper_throw_reference_error)
 2244 dispatch(2)
 2245
 2246
 2247_llint_op_jsr:
 2248 traceExecution()
 2249 loadi 4[PC], t0
 2250 addi 3 * 4, PC, t1
 2251 storei t1, [cfr, t0, 8]
 2252 dispatchBranch(8[PC])
 2253
 2254
 2255_llint_op_sret:
 2256 traceExecution()
 2257 loadi 4[PC], t0
 2258 loadp [cfr, t0, 8], PC
 2259 dispatch(0)
 2260
 2261
 2262_llint_op_debug:
 2263 traceExecution()
 2264 callHelper(_llint_helper_debug)
 2265 dispatch(4)
 2266
 2267
 2268_llint_op_profile_will_call:
 2269 traceExecution()
 2270 loadp JITStackFrame::enabledProfilerReference[sp], t0
 2271 btpz [t0], .opProfileWillCallDone
 2272 callHelper(_llint_helper_profile_will_call)
 2273.opProfileWillCallDone:
 2274 dispatch(2)
 2275
 2276
 2277_llint_op_profile_did_call:
 2278 traceExecution()
 2279 loadp JITStackFrame::enabledProfilerReference[sp], t0
 2280 btpz [t0], .opProfileWillCallDone
 2281 callHelper(_llint_helper_profile_did_call)
 2282.opProfileDidCallDone:
 2283 dispatch(2)
 2284
 2285
 2286_llint_op_end:
 2287 traceExecution()
 2288 checkSwitchToJITForEpilogue()
 2289 loadi 4[PC], t0
 2290 loadi TagOffset[cfr, t0, 8], t1
 2291 loadi PayloadOffset[cfr, t0, 8], t0
 2292 doReturn()
 2293
 2294
 2295_llint_throw_from_helper_trampoline:
 2296 # When throwing from the interpreter (i.e. throwing from LLIntHelpers), so
 2297 # the throw target is not necessarily interpreted code, we come to here.
 2298 # This essentially emulates the JIT's throwing protocol.
 2299 loadp JITStackFrame::globalData[sp], t1
 2300 loadp JSGlobalData::callFrameForThrow[t1], t0
 2301 jmp JSGlobalData::targetMachinePCForThrow[t1]
 2302
 2303
 2304_llint_throw_during_call_trampoline:
 2305 preserveReturnAddressAfterCall(t2)
 2306 loadp JITStackFrame::globalData[sp], t1
 2307 loadp JSGlobalData::callFrameForThrow[t1], t0
 2308 jmp JSGlobalData::targetMachinePCForThrow[t1]
 2309
 2310
 2311# Lastly, make sure that we can link even though we don't support all opcodes.
 2312# These opcodes should never arise when using LLInt or either JIT. We assert
 2313# as much.
 2314
 2315macro notSupported()
 2316 if ASSERT_ENABLED
 2317 crash()
 2318 else
 2319 # We should use whatever the smallest possible instruction is, just to
 2320 # ensure that there is a gap between instruction labels. If multiple
 2321 # smallest instructions exist, we should pick the one that is most
 2322 # likely result in execution being halted. Currently that is the break
 2323 # instruction on all architectures we're interested in. (Break is int3
 2324 # on Intel, which is 1 byte, and bkpt on ARMv7, which is 2 bytes.)
 2325 break
 2326 end
 2327end
 2328
 2329_llint_op_get_array_length:
 2330 notSupported()
 2331
 2332_llint_op_get_by_id_chain:
 2333 notSupported()
 2334
 2335_llint_op_get_by_id_custom_chain:
 2336 notSupported()
 2337
 2338_llint_op_get_by_id_custom_proto:
 2339 notSupported()
 2340
 2341_llint_op_get_by_id_custom_self:
 2342 notSupported()
 2343
 2344_llint_op_get_by_id_generic:
 2345 notSupported()
 2346
 2347_llint_op_get_by_id_getter_chain:
 2348 notSupported()
 2349
 2350_llint_op_get_by_id_getter_proto:
 2351 notSupported()
 2352
 2353_llint_op_get_by_id_getter_self:
 2354 notSupported()
 2355
 2356_llint_op_get_by_id_proto:
 2357 notSupported()
 2358
 2359_llint_op_get_by_id_self:
 2360 notSupported()
 2361
 2362_llint_op_get_string_length:
 2363 notSupported()
 2364
 2365_llint_op_put_by_id_generic:
 2366 notSupported()
 2367
 2368_llint_op_put_by_id_replace:
 2369 notSupported()
 2370
 2371_llint_op_put_by_id_transition:
 2372 notSupported()
 2373
 2374
 2375# Indicate the end of LLInt.
 2376_llint_end:
 2377 crash()
 2378
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 if couldBeExpression
 374 expr = parseExpression
 375 if @tokens[@idx] == "["
 376 parseAddress(expr)
 377 else
 378 expr
 379 end
 380 elsif @tokens[@idx] == "["
 381 parseAddress(Immediate.new(@tokens[@idx].codeOrigin, 0))
 382 elsif isLabel @tokens[@idx]
 383 result = LabelReference.new(@tokens[@idx].codeOrigin, Label.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string))
 384 @idx += 1
 385 result
 386 elsif isLocalLabel @tokens[@idx]
 387 result = LocalLabelReference.new(@tokens[@idx].codeOrigin, LocalLabel.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string))
 388 @idx += 1
 389 result
 390 else
 391 parseError(comment)
 392 end
 393 end
 394
 395 def parseMacroVariables
 396 skipNewLine
 397 consume(/\A\(\Z/)
 398 variables = []
 399 loop {
 400 skipNewLine
 401 if @tokens[@idx] == ")"
 402 @idx += 1
 403 break
 404 elsif isIdentifier(@tokens[@idx])
 405 variables << Variable.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
 406 @idx += 1
 407 skipNewLine
 408 if @tokens[@idx] == ")"
 409 @idx += 1
 410 break
 411 elsif @tokens[@idx] == ","
 412 @idx += 1
 413 else
 414 parseError
 415 end
 416 else
 417 parseError
 418 end
 419 }
 420 variables
 421 end
 422
 423 def parseSequence(final, comment)
 424 firstCodeOrigin = @tokens[@idx].codeOrigin
 425 list = []
 426 loop {
 427 if (@idx == @tokens.length and not final) or (final and @tokens[@idx] =~ final)
 428 break
 429 elsif @tokens[@idx] == "\n"
 430 # ignore
 431 @idx += 1
 432 elsif @tokens[@idx] == "const"
 433 @idx += 1
 434 parseError unless isVariable @tokens[@idx]
 435 variable = Variable.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
 436 @idx += 1
 437 parseError unless @tokens[@idx] == "="
 438 @idx += 1
 439 value = parseOperand("while inside of const #{variable.name}")
 440 list << ConstDecl.new(@tokens[@idx].codeOrigin, variable, value)
 441 elsif @tokens[@idx] == "error"
 442 list << Error.new(@tokens[@idx].codeOrigin)
 443 @idx += 1
 444 elsif @tokens[@idx] == "if"
 445 codeOrigin = @tokens[@idx].codeOrigin
 446 @idx += 1
 447 skipNewLine
 448 predicate = parsePredicate
 449 consume(/\A((then)|(\n))\Z/)
 450 skipNewLine
 451 ifThenElse = IfThenElse.new(codeOrigin, predicate, parseSequence(/\A((else)|(end)|(elsif))\Z/, "while inside of \"if #{predicate.dump}\""))
 452 list << ifThenElse
 453 while @tokens[@idx] == "elsif"
 454 codeOrigin = @tokens[@idx].codeOrigin
 455 @idx += 1
 456 skipNewLine
 457 predicate = parsePredicate
 458 consume(/\A((then)|(\n))\Z/)
 459 skipNewLine
 460 elseCase = IfThenElse.new(codeOrigin, predicate, parseSequence(/\A((else)|(end)|(elsif))\Z/, "while inside of \"if #{predicate.dump}\""))
 461 ifThenElse.elseCase = elseCase
 462 ifThenElse = elseCase
 463 end
 464 if @tokens[@idx] == "else"
 465 @idx += 1
 466 ifThenElse.elseCase = parseSequence(/\Aend\Z/, "while inside of else case for \"if #{predicate.dump}\"")
 467 @idx += 1
 468 else
 469 parseError unless @tokens[@idx] == "end"
 470 @idx += 1
 471 end
 472 elsif @tokens[@idx] == "macro"
 473 codeOrigin = @tokens[@idx].codeOrigin
 474 @idx += 1
 475 skipNewLine
 476 parseError unless isIdentifier(@tokens[@idx])
 477 name = @tokens[@idx].string
 478 @idx += 1
 479 variables = parseMacroVariables
 480 body = parseSequence(/\Aend\Z/, "while inside of macro #{name}")
 481 @idx += 1
 482 list << Macro.new(codeOrigin, name, variables, body)
 483 elsif isInstruction @tokens[@idx]
 484 codeOrigin = @tokens[@idx].codeOrigin
 485 name = @tokens[@idx].string
 486 @idx += 1
 487 if (not final and @idx == @tokens.size) or (final and @tokens[@idx] =~ final)
 488 # Zero operand instruction, and it's the last one.
 489 list << Instruction.new(codeOrigin, name, [])
 490 break
 491 elsif @tokens[@idx] == "\n"
 492 # Zero operand instruction.
 493 list << Instruction.new(codeOrigin, name, [])
 494 @idx += 1
 495 else
 496 # It's definitely an instruction, and it has at least one operand.
 497 operands = []
 498 endOfSequence = false
 499 loop {
 500 operands << parseOperand("while inside of instruction #{name}")
 501 if (not final and @idx == @tokens.size) or (final and @tokens[@idx] =~ final)
 502 # The end of the instruction and of the sequence.
 503 endOfSequence = true
 504 break
 505 elsif @tokens[@idx] == ","
 506 # Has another operand.
 507 @idx += 1
 508 elsif @tokens[@idx] == "\n"
 509 # The end of the instruction.
 510 @idx += 1
 511 break
 512 else
 513 parseError("Expected a comma, newline, or #{final} after #{operands.last.dump}")
 514 end
 515 }
 516 list << Instruction.new(codeOrigin, name, operands)
 517 if endOfSequence
 518 break
 519 end
 520 end
 521 elsif isIdentifier @tokens[@idx]
 522 codeOrigin = @tokens[@idx].codeOrigin
 523 name = @tokens[@idx].string
 524 @idx += 1
 525 if @tokens[@idx] == "("
 526 # Macro invocation.
 527 @idx += 1
 528 operands = []
 529 skipNewLine
 530 if @tokens[@idx] == ")"
 531 @idx += 1
 532 else
 533 loop {
 534 skipNewLine
 535 if @tokens[@idx] == "macro"
 536 # It's a macro lambda!
 537 codeOriginInner = @tokens[@idx].codeOrigin
 538 @idx += 1
 539 variables = parseMacroVariables
 540 body = parseSequence(/\Aend\Z/, "while inside of anonymous macro passed as argument to #{name}")
 541 @idx += 1
 542 operands << Macro.new(codeOriginInner, nil, variables, body)
 543 else
 544 operands << parseOperand("while inside of macro call to #{name}")
 545 end
 546 skipNewLine
 547 if @tokens[@idx] == ")"
 548 @idx += 1
 549 break
 550 elsif @tokens[@idx] == ","
 551 @idx += 1
 552 else
 553 parseError "Unexpected #{@tokens[@idx].string.inspect} while parsing invocation of macro #{name}"
 554 end
 555 }
 556 end
 557 list << MacroCall.new(codeOrigin, name, operands)
 558 else
 559 parseError "Expected \"(\" after #{name}"
 560 end
 561 elsif isLabel @tokens[@idx] or isLocalLabel @tokens[@idx]
 562 codeOrigin = @tokens[@idx].codeOrigin
 563 name = @tokens[@idx].string
 564 @idx += 1
 565 parseError unless @tokens[@idx] == ":"
 566 # It's a label.
 567 if isLabel name
 568 list << Label.forName(codeOrigin, name)
 569 else
 570 list << LocalLabel.forName(codeOrigin, name)
 571 end
 572 @idx += 1
 573 else
 574 parseError "Expecting terminal #{final} #{comment}"
 575 end
 576 }
 577 Sequence.new(firstCodeOrigin, list)
 578 end
 579end
 580
 581def parse(tokens)
 582 parser = Parser.new(tokens)
 583 parser.parseSequence(nil, "")
 584end
 585
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()
106834

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
106834

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)
106834

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 {
124124
125125 OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[registerArraySize]);
126126 WriteBarrier<Unknown>* registers = registerArray.get() + registerOffset;
127 
 127
128128 // Copy all arguments that can be captured by name or by the arguments object.
129129 for (int i = 0; i < m_numCapturedArgs; ++i) {
130130 int index = CallFrame::argumentOffset(i);
106834

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:
106834

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 {
162163 static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
163164
164165 private:
 166 friend class LLIntOffsetsExtractor;
 167
165168 const ClassInfo* m_classInfo;
166169 WriteBarrier<Structure> m_structure;
167170 };
106834

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 {
142143 static void visitChildren(JSCell*, SlotVisitor&);
143144
144145 private:
 146 friend class LLIntOffsetsExtractor;
 147
145148 JS_EXPORT_PRIVATE bool isHostFunctionNonInline() const;
146149
147150 static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&);
106834

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}
106834

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();
106834

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);
106834

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 {
264265 JSObject(JSGlobalData&, Structure*, PropertyStorage inlineStorage);
265266
266267 private:
 268 friend class LLIntOffsetsExtractor;
 269
267270 // Nobody should ever ask any of these questions on something already known to be a JSObject.
268271 using JSCell::isAPIValueWrapper;
269272 using JSCell::isGetterSetter;

@@COMPILE_ASSERT((JSFinalObject_inlineStor
377380 static void destroy(JSCell*);
378381
379382 private:
 383 friend class LLIntOffsetsExtractor;
 384
380385 explicit JSFinalObject(JSGlobalData& globalData, Structure* structure)
381386 : JSObject(globalData, structure, m_inlineStorage)
382387 {
106834

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;
106834

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;
106834

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
106834

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());
106834

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;
106834

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);
106834

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;
106834

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
106834

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());
106834

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*);
106834

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;
106834

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
106834

Source/JavaScriptCore/wtf/Platform.h

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

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;
106834

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,
106834

Source/WebCore/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 No new tests because no behavior changed.
 12
 13 * CMakeLists.txt:
 14
1152012-02-06 Caio Marcelo de Oliveira Filho <caio.oliveira@openbossa.org>
216
317 Provide more attribute methods in Element
106834

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"
106834

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-06 Robin Cao <robin.cao@torchmobile.com.cn>
214
315 [BlackBerry] Remove unused variable in BackingStore
106834

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"
106834

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-06 Eric Seidel <eric@webkit.org>
214
315 webkit-patch apply-from-bug should be able to apply non-reviewed patches
106834

Tools/DumpRenderTree/efl/CMakeLists.txt

@@SET(DumpRenderTree_INCLUDE_DIRECTORIES
6868 ${JAVASCRIPTCORE_DIR}
6969 ${JAVASCRIPTCORE_DIR}/API
7070 ${JAVASCRIPTCORE_DIR}/assembler
 71 ${JAVASCRIPTCORE_DIR}/bytecode
7172 ${JAVASCRIPTCORE_DIR}/dfg
7273 ${JAVASCRIPTCORE_DIR}/heap
7374 ${JAVASCRIPTCORE_DIR}/interpreter
7475 ${JAVASCRIPTCORE_DIR}/jit
 76 ${JAVASCRIPTCORE_DIR}/llint
7577 ${JAVASCRIPTCORE_DIR}/runtime
7678 ${JAVASCRIPTCORE_DIR}/ForwardingHeaders
7779 ${JAVASCRIPTCORE_DIR}/wtf
106834