"${JAVASCRIPTCORE_DIR}/debugger"
"${JAVASCRIPTCORE_DIR}/interpreter"
"${JAVASCRIPTCORE_DIR}/jit"
- "${JAVASCRIPTCORE_DIR}/llint"
"${JAVASCRIPTCORE_DIR}/parser"
"${JAVASCRIPTCORE_DIR}/profiler"
"${JAVASCRIPTCORE_DIR}/runtime"
interpreter/RegisterFile.cpp
jit/ExecutableAllocator.cpp
- jit/HostCallReturnValue.cpp
jit/JITArithmetic32_64.cpp
jit/JITArithmetic.cpp
jit/JITCall32_64.cpp
+2012-02-21 Adam Roben <aroben@apple.com>
+
+ Roll out r108309, r108323, and r108326
+
+ They broke the 32-bit Lion build.
+
+ Original bugs is <http://webkit.org/b/75812> <rdar://problem/10079694>.
+
+ * CMakeLists.txt:
+ * GNUmakefile.am:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops:
+ * JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * assembler/LinkBuffer.h:
+ * assembler/MacroAssemblerCodeRef.h:
+ * bytecode/BytecodeConventions.h: Removed.
+ * bytecode/CallLinkStatus.cpp:
+ * bytecode/CallLinkStatus.h:
+ * bytecode/CodeBlock.cpp:
+ * bytecode/CodeBlock.h:
+ * bytecode/GetByIdStatus.cpp:
+ * bytecode/GetByIdStatus.h:
+ * bytecode/Instruction.h:
+ * bytecode/LLIntCallLinkInfo.h: Removed.
+ * bytecode/MethodCallLinkStatus.cpp:
+ * bytecode/Opcode.cpp:
+ * bytecode/Opcode.h:
+ * bytecode/PutByIdStatus.cpp:
+ * bytecode/PutByIdStatus.h:
+ * bytecompiler/BytecodeGenerator.cpp:
+ * dfg/DFGByteCodeParser.cpp:
+ * dfg/DFGCapabilities.h:
+ * dfg/DFGOSRExitCompiler.cpp:
+ * dfg/DFGOperations.cpp:
+ * heap/Heap.h:
+ * heap/MarkStack.cpp:
+ * heap/MarkedAllocator.h:
+ * heap/MarkedSpace.h:
+ * interpreter/CallFrame.cpp:
+ * interpreter/CallFrame.h:
+ * interpreter/Interpreter.cpp:
+ * interpreter/Interpreter.h:
+ * interpreter/RegisterFile.h:
+ * jit/ExecutableAllocator.h:
+ * jit/HostCallReturnValue.cpp: Removed.
+ * jit/HostCallReturnValue.h: Removed.
+ * jit/JIT.cpp:
+ * jit/JITCode.h:
+ * jit/JITDriver.h:
+ * jit/JITExceptions.cpp:
+ * jit/JITInlineMethods.h:
+ * jit/JITStubs.cpp:
+ * jit/JITStubs.h:
+ * jit/JSInterfaceJIT.h:
+ * llint/LLIntCommon.h: Removed.
+ * llint/LLIntData.cpp: Removed.
+ * llint/LLIntData.h: Removed.
+ * llint/LLIntEntrypoints.cpp: Removed.
+ * llint/LLIntEntrypoints.h: Removed.
+ * llint/LLIntExceptions.cpp: Removed.
+ * llint/LLIntExceptions.h: Removed.
+ * llint/LLIntOfflineAsmConfig.h: Removed.
+ * llint/LLIntOffsetsExtractor.cpp: Removed.
+ * llint/LLIntSlowPaths.cpp: Removed.
+ * llint/LLIntSlowPaths.h: Removed.
+ * llint/LLIntThunks.cpp: Removed.
+ * llint/LLIntThunks.h: Removed.
+ * llint/LowLevelInterpreter.asm: Removed.
+ * llint/LowLevelInterpreter.cpp: Removed.
+ * llint/LowLevelInterpreter.h: Removed.
+ * offlineasm/armv7.rb: Removed.
+ * offlineasm/asm.rb: Removed.
+ * offlineasm/ast.rb: Removed.
+ * offlineasm/backends.rb: Removed.
+ * offlineasm/generate_offset_extractor.rb: Removed.
+ * offlineasm/instructions.rb: Removed.
+ * offlineasm/offset_extractor_constants.rb: Removed.
+ * offlineasm/offsets.rb: Removed.
+ * offlineasm/opt.rb: Removed.
+ * offlineasm/parser.rb: Removed.
+ * offlineasm/registers.rb: Removed.
+ * offlineasm/self_hash.rb: Removed.
+ * offlineasm/settings.rb: Removed.
+ * offlineasm/transform.rb: Removed.
+ * offlineasm/x86.rb: Removed.
+ * runtime/CodeSpecializationKind.h: Removed.
+ * runtime/CommonSlowPaths.h:
+ * runtime/Executable.cpp:
+ * runtime/Executable.h:
+ * runtime/ExecutionHarness.h: Removed.
+ * runtime/JSArray.h:
+ * runtime/JSCell.h:
+ * runtime/JSFunction.h:
+ * runtime/JSGlobalData.cpp:
+ * runtime/JSGlobalData.h:
+ * runtime/JSGlobalObject.h:
+ * runtime/JSObject.h:
+ * runtime/JSPropertyNameIterator.h:
+ * runtime/JSString.h:
+ * runtime/JSTypeInfo.h:
+ * runtime/JSValue.cpp:
+ * runtime/JSValue.h:
+ * runtime/JSVariableObject.h:
+ * runtime/Options.cpp:
+ * runtime/Options.h:
+ * runtime/ScopeChain.h:
+ * runtime/Structure.cpp:
+ * runtime/Structure.h:
+ * runtime/StructureChain.h:
+ * wtf/InlineASM.h:
+ * wtf/Platform.h:
+ * wtf/SentinelLinkedList.h:
+ * wtf/text/StringImpl.h:
+
2012-02-21 Gustavo Noronha Silva <kov@debian.org> and Bob Tracy <rct@frus.com>
Does not build on IA64, SPARC and Alpha
-I$(srcdir)/Source/JavaScriptCore/interpreter \
-I$(srcdir)/Source/JavaScriptCore/jit \
-I$(srcdir)/Source/JavaScriptCore/jit \
- -I$(srcdir)/Source/JavaScriptCore/llint \
-I$(srcdir)/Source/JavaScriptCore/parser \
-I$(srcdir)/Source/JavaScriptCore/profiler \
-I$(srcdir)/Source/JavaScriptCore/runtime \
Source/JavaScriptCore/assembler/RepatchBuffer.h \
Source/JavaScriptCore/assembler/SH4Assembler.h \
Source/JavaScriptCore/assembler/X86Assembler.h \
- Source/JavaScriptCore/bytecode/BytecodeConventions.h \
Source/JavaScriptCore/bytecode/CallLinkInfo.cpp \
Source/JavaScriptCore/bytecode/CallLinkInfo.h \
Source/JavaScriptCore/bytecode/CallLinkStatus.cpp \
Source/JavaScriptCore/bytecode/Instruction.h \
Source/JavaScriptCore/bytecode/JumpTable.cpp \
Source/JavaScriptCore/bytecode/JumpTable.h \
- Source/JavaScriptCore/bytecode/LLIntCallLinkInfo.h \
Source/JavaScriptCore/bytecode/LineInfo.h \
Source/JavaScriptCore/bytecode/MethodCallLinkInfo.cpp \
Source/JavaScriptCore/bytecode/MethodCallLinkInfo.h \
Source/JavaScriptCore/jit/CompactJITCodeMap.h \
Source/JavaScriptCore/jit/ExecutableAllocator.cpp \
Source/JavaScriptCore/jit/ExecutableAllocator.h \
- Source/JavaScriptCore/jit/HostCallReturnValue.cpp \
- Source/JavaScriptCore/jit/HostCallReturnValue.h \
Source/JavaScriptCore/jit/JITArithmetic32_64.cpp \
Source/JavaScriptCore/jit/JITArithmetic.cpp \
Source/JavaScriptCore/jit/JITCall32_64.cpp \
Source/JavaScriptCore/jit/SpecializedThunkJIT.h \
Source/JavaScriptCore/jit/ThunkGenerators.cpp \
Source/JavaScriptCore/jit/ThunkGenerators.h \
- Source/JavaScriptCore/llint/LLIntData.h \
Source/JavaScriptCore/os-win32/stdbool.h \
Source/JavaScriptCore/os-win32/stdint.h \
Source/JavaScriptCore/parser/ASTBuilder.h \
Source/JavaScriptCore/runtime/CallData.cpp \
Source/JavaScriptCore/runtime/CallData.h \
Source/JavaScriptCore/runtime/ClassInfo.h \
- Source/JavaScriptCore/runtime/CodeSpecializationKind.h \
Source/JavaScriptCore/runtime/CommonIdentifiers.cpp \
Source/JavaScriptCore/runtime/CommonIdentifiers.h \
Source/JavaScriptCore/runtime/CommonSlowPaths.h \
Source/JavaScriptCore/runtime/ExceptionHelpers.h \
Source/JavaScriptCore/runtime/Executable.cpp \
Source/JavaScriptCore/runtime/Executable.h \
- Source/JavaScriptCore/runtime/ExecutionHarness.h \
Source/JavaScriptCore/runtime/FunctionConstructor.cpp \
Source/JavaScriptCore/runtime/FunctionConstructor.h \
Source/JavaScriptCore/runtime/FunctionPrototype.cpp \
$$SOURCE_DIR/debugger \
$$SOURCE_DIR/interpreter \
$$SOURCE_DIR/jit \
- $$SOURCE_DIR/llint \
$$SOURCE_DIR/parser \
$$SOURCE_DIR/profiler \
$$SOURCE_DIR/runtime \
>
</File>
<File
- RelativePath="..\..\jit\HostCallReturnValue.cpp"
- >
- </File>
- <File
RelativePath="..\..\jit\JIT.cpp"
>
</File>
</File>
</Filter>
<Filter
- Name="llint"
- >
- <File
- RelativePath="..\..\llint\LLIntData.h"
- >
- </File>
- </Filter>
- <Filter
Name="interpreter"
>
<File
>
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(ConfigurationBuildDir)\obj\JavaScriptCore\DerivedSources\";../../;../../API/;../../parser/;../../bytecompiler/;../../dfg/;../../jit/;../../llint/;../../runtime/;../../tools/;../../bytecode/;../../interpreter/;../../wtf/;../../profiler;../../assembler/;../../debugger/;../../heap/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private";"$(ConfigurationBuildDir)\include";"$(ConfigurationBuildDir)\include\JavaScriptCore";"$(ConfigurationBuildDir)\include\private";"$(WebKitLibrariesDir)\include\pthreads""
+ AdditionalIncludeDirectories=""$(ConfigurationBuildDir)\obj\JavaScriptCore\DerivedSources\";../../;../../API/;../../parser/;../../bytecompiler/;../../dfg/;../../jit/;../../runtime/;../../tools/;../../bytecode/;../../interpreter/;../../wtf/;../../profiler;../../assembler/;../../debugger/;../../heap/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private";"$(ConfigurationBuildDir)\include";"$(ConfigurationBuildDir)\include\JavaScriptCore";"$(ConfigurationBuildDir)\include\private";"$(WebKitLibrariesDir)\include\pthreads""
PreprocessorDefinitions="__STD_C"
ForcedIncludeFiles="ICUVersion.h"
/>
debugger
interpreter
jit
- llint
parser
profiler
runtime
objects = {
/* Begin PBXAggregateTarget section */
- 0F4680A914BA7FD900BFE272 /* LLInt Offsets */ = {
- isa = PBXAggregateTarget;
- buildConfigurationList = 0F4680AC14BA7FD900BFE272 /* Build configuration list for PBXAggregateTarget "LLInt Offsets" */;
- buildPhases = (
- 0F4680AA14BA7FD900BFE272 /* Generate Derived Sources */,
- );
- name = "LLInt Offsets";
- productName = "Derived Sources";
- };
65FB3F6609D11E9100F49DEB /* Derived Sources */ = {
isa = PBXAggregateTarget;
buildConfigurationList = 65FB3F7709D11EBD00F49DEB /* Build configuration list for PBXAggregateTarget "Derived Sources" */;
65FB3F6509D11E9100F49DEB /* Generate Derived Sources */,
5D35DEE10C7C140B008648B2 /* Generate DTrace header */,
);
- dependencies = (
- 0F4680B414BA821400BFE272 /* PBXTargetDependency */,
- );
name = "Derived Sources";
productName = "Derived Sources";
};
0BAC94A01338728400CF135B /* ThreadRestrictionVerifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BAC949E1338728400CF135B /* ThreadRestrictionVerifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
0BCD83571485845200EA2003 /* TemporaryChange.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BCD83541485841200EA2003 /* TemporaryChange.h */; settings = {ATTRIBUTES = (Private, ); }; };
0BF28A2911A33DC300638F84 /* SizeLimits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0BF28A2811A33DC300638F84 /* SizeLimits.cpp */; };
- 0F0B839A14BCF45D00885B4F /* LLIntEntrypoints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839514BCF45A00885B4F /* LLIntEntrypoints.cpp */; };
- 0F0B839B14BCF46000885B4F /* LLIntEntrypoints.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B839614BCF45A00885B4F /* LLIntEntrypoints.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */; };
- 0F0B839D14BCF46600885B4F /* LLIntThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B839814BCF45A00885B4F /* LLIntThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F0B83A714BCF50700885B4F /* CodeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83A514BCF50400885B4F /* CodeType.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F0B83A914BCF56200885B4F /* HandlerInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83A814BCF55E00885B4F /* HandlerInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F0B83AB14BCF5BB00885B4F /* ExpressionRangeInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83AA14BCF5B900885B4F /* ExpressionRangeInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F0B83B514BCF86200885B4F /* MethodCallLinkInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83B314BCF85E00885B4F /* MethodCallLinkInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F0B83B714BCF8E100885B4F /* GlobalResolveInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83B614BCF8DF00885B4F /* GlobalResolveInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F0B83B914BCF95F00885B4F /* CallReturnOffsetToBytecodeOffset.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0F0FC45A14BD15F500B81154 /* LLIntCallLinkInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F16D726142C39C000CF784A /* BitVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F16D724142C39A200CF784A /* BitVector.cpp */; };
0F21C26814BE5F6800ADC64B /* JITDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C26614BE5F5E00ADC64B /* JITDriver.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0F21C27C14BE727600ADC64B /* ExecutionHarness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27A14BE727300ADC64B /* ExecutionHarness.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0F21C27F14BEAA8200ADC64B /* BytecodeConventions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F242DA713F3B1E8007ADD4C /* WeakReferenceHarvester.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F2C556F14738F3100121E4F /* DFGCodeBlocks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F2C557014738F3500121E4F /* DFGCodeBlocks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */; };
0F431738146BAC69007E3890 /* ListableHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F431736146BAC65007E3890 /* ListableHandler.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F46808214BA572D00BFE272 /* JITExceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F46808014BA572700BFE272 /* JITExceptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F46808314BA573100BFE272 /* JITExceptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F46807F14BA572700BFE272 /* JITExceptions.cpp */; };
- 0F4680A314BA7F8D00BFE272 /* LLIntExceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F46809E14BA7F8200BFE272 /* LLIntExceptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0F4680A414BA7F8D00BFE272 /* LLIntSlowPaths.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F46809F14BA7F8200BFE272 /* LLIntSlowPaths.cpp */; settings = {COMPILER_FLAGS = "-Wno-unused-parameter"; }; };
- 0F4680A514BA7F8D00BFE272 /* LLIntSlowPaths.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680A014BA7F8200BFE272 /* LLIntSlowPaths.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0F4680A714BA7FA100BFE272 /* LLIntOffsetsExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */; };
- 0F4680A814BA7FAB00BFE272 /* LLIntExceptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F46809D14BA7F8200BFE272 /* LLIntExceptions.cpp */; };
- 0F4680CA14BBB16C00BFE272 /* LLIntCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680C514BBB16900BFE272 /* LLIntCommon.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0F4680CB14BBB17200BFE272 /* LLIntOfflineAsmConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680C614BBB16900BFE272 /* LLIntOfflineAsmConfig.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0F4680CC14BBB17A00BFE272 /* LowLevelInterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680C714BBB16900BFE272 /* LowLevelInterpreter.cpp */; };
- 0F4680CD14BBB17D00BFE272 /* LowLevelInterpreter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680C814BBB16900BFE272 /* LowLevelInterpreter.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0F4680D214BBD16500BFE272 /* LLIntData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680CE14BBB3D100BFE272 /* LLIntData.cpp */; };
- 0F4680D314BBD16700BFE272 /* LLIntData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680CF14BBB3D100BFE272 /* LLIntData.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0F4680D414BBD24900BFE272 /* HostCallReturnValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */; };
- 0F4680D514BBD24B00BFE272 /* HostCallReturnValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F55F0F414D1063900AC7649 /* AbstractPC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F55F0F114D1063600AC7649 /* AbstractPC.cpp */; };
0F55F0F514D1063C00AC7649 /* AbstractPC.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F55F0F214D1063600AC7649 /* AbstractPC.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F5F08CF146C7633000472A9 /* UnconditionalFinalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */; settings = {ATTRIBUTES = (Private, ); }; };
86B99AE3117E578100DF5A90 /* StringBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86B99AE1117E578100DF5A90 /* StringBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
86BB09C0138E381B0056702F /* DFGRepatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86BB09BE138E381B0056702F /* DFGRepatch.cpp */; };
86BB09C1138E381B0056702F /* DFGRepatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 86BB09BF138E381B0056702F /* DFGRepatch.h */; };
- 86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */; };
86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86C568DD11A213EE0007F7F0 /* MacroAssemblerARM.cpp */; };
86C568E111A213EE0007F7F0 /* MacroAssemblerMIPS.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C568DE11A213EE0007F7F0 /* MacroAssemblerMIPS.h */; };
86C568E211A213EE0007F7F0 /* MIPSAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C568DF11A213EE0007F7F0 /* MIPSAssembler.h */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
- 0F4680B114BA811500BFE272 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 0F4680A914BA7FD900BFE272;
- remoteInfo = "LLInt Offsets";
- };
- 0F4680B314BA821400BFE272 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 0F46808E14BA7E5E00BFE272;
- remoteInfo = JSCLLIntOffsetsExtractor;
- };
141214BE0A49190E00480255 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
- 0F46808D14BA7E5E00BFE272 /* CopyFiles */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = /usr/share/man/man1/;
- dstSubfolderSpec = 0;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 1;
- };
5DBB1511131D0B130056AD36 /* Copy Support Script */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 12;
0BAC949E1338728400CF135B /* ThreadRestrictionVerifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadRestrictionVerifier.h; sourceTree = "<group>"; };
0BCD83541485841200EA2003 /* TemporaryChange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemporaryChange.h; sourceTree = "<group>"; };
0BF28A2811A33DC300638F84 /* SizeLimits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SizeLimits.cpp; sourceTree = "<group>"; };
- 0F0B839514BCF45A00885B4F /* LLIntEntrypoints.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntEntrypoints.cpp; path = llint/LLIntEntrypoints.cpp; sourceTree = "<group>"; };
- 0F0B839614BCF45A00885B4F /* LLIntEntrypoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntEntrypoints.h; path = llint/LLIntEntrypoints.h; sourceTree = "<group>"; };
- 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; };
- 0F0B839814BCF45A00885B4F /* LLIntThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntThunks.h; path = llint/LLIntThunks.h; sourceTree = "<group>"; };
0F0B83A514BCF50400885B4F /* CodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeType.h; sourceTree = "<group>"; };
0F0B83A814BCF55E00885B4F /* HandlerInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HandlerInfo.h; sourceTree = "<group>"; };
0F0B83AA14BCF5B900885B4F /* ExpressionRangeInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExpressionRangeInfo.h; sourceTree = "<group>"; };
0F0B83B314BCF85E00885B4F /* MethodCallLinkInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MethodCallLinkInfo.h; sourceTree = "<group>"; };
0F0B83B614BCF8DF00885B4F /* GlobalResolveInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GlobalResolveInfo.h; sourceTree = "<group>"; };
0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallReturnOffsetToBytecodeOffset.h; sourceTree = "<group>"; };
- 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLIntCallLinkInfo.h; sourceTree = "<group>"; };
0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonSlowPaths.h; sourceTree = "<group>"; };
0F16D724142C39A200CF784A /* BitVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BitVector.cpp; sourceTree = "<group>"; };
0F21C26614BE5F5E00ADC64B /* JITDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITDriver.h; sourceTree = "<group>"; };
- 0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeSpecializationKind.h; sourceTree = "<group>"; };
- 0F21C27A14BE727300ADC64B /* ExecutionHarness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutionHarness.h; sourceTree = "<group>"; };
- 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeConventions.h; sourceTree = "<group>"; };
0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakReferenceHarvester.h; sourceTree = "<group>"; };
0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DFGCodeBlocks.cpp; sourceTree = "<group>"; };
0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFGCodeBlocks.h; sourceTree = "<group>"; };
0F431736146BAC65007E3890 /* ListableHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ListableHandler.h; sourceTree = "<group>"; };
0F46807F14BA572700BFE272 /* JITExceptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITExceptions.cpp; sourceTree = "<group>"; };
0F46808014BA572700BFE272 /* JITExceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITExceptions.h; sourceTree = "<group>"; };
- 0F46808F14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; };
- 0F46809D14BA7F8200BFE272 /* LLIntExceptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntExceptions.cpp; path = llint/LLIntExceptions.cpp; sourceTree = "<group>"; };
- 0F46809E14BA7F8200BFE272 /* LLIntExceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntExceptions.h; path = llint/LLIntExceptions.h; sourceTree = "<group>"; };
- 0F46809F14BA7F8200BFE272 /* LLIntSlowPaths.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntSlowPaths.cpp; path = llint/LLIntSlowPaths.cpp; sourceTree = "<group>"; };
- 0F4680A014BA7F8200BFE272 /* LLIntSlowPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntSlowPaths.h; path = llint/LLIntSlowPaths.h; sourceTree = "<group>"; };
- 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntOffsetsExtractor.cpp; path = llint/LLIntOffsetsExtractor.cpp; sourceTree = "<group>"; };
- 0F4680C514BBB16900BFE272 /* LLIntCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntCommon.h; path = llint/LLIntCommon.h; sourceTree = "<group>"; };
- 0F4680C614BBB16900BFE272 /* LLIntOfflineAsmConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntOfflineAsmConfig.h; path = llint/LLIntOfflineAsmConfig.h; sourceTree = "<group>"; };
- 0F4680C714BBB16900BFE272 /* LowLevelInterpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LowLevelInterpreter.cpp; path = llint/LowLevelInterpreter.cpp; sourceTree = "<group>"; };
- 0F4680C814BBB16900BFE272 /* LowLevelInterpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LowLevelInterpreter.h; path = llint/LowLevelInterpreter.h; sourceTree = "<group>"; };
- 0F4680CE14BBB3D100BFE272 /* LLIntData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntData.cpp; path = llint/LLIntData.cpp; sourceTree = "<group>"; };
- 0F4680CF14BBB3D100BFE272 /* LLIntData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntData.h; path = llint/LLIntData.h; sourceTree = "<group>"; };
- 0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HostCallReturnValue.cpp; sourceTree = "<group>"; };
- 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HostCallReturnValue.h; sourceTree = "<group>"; };
0F55F0F114D1063600AC7649 /* AbstractPC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AbstractPC.cpp; sourceTree = "<group>"; };
0F55F0F214D1063600AC7649 /* AbstractPC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbstractPC.h; sourceTree = "<group>"; };
0F5F08CC146BE602000472A9 /* DFGByteCodeCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGByteCodeCache.h; path = dfg/DFGByteCodeCache.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
- 0F46808C14BA7E5E00BFE272 /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
1412111E0A48793C00480255 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
141211200A48793C00480255 /* minidom */,
14BD59BF0A3E8F9000BAF59C /* testapi */,
6511230514046A4C002B101D /* testRegExp */,
- 0F46808F14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */,
);
name = Products;
sourceTree = "<group>";
F5C290E60284F98E018635CA /* JavaScriptCorePrefix.h */,
45E12D8806A49B0F00E9DF84 /* jsc.cpp */,
F68EBB8C0255D4C601FF60F7 /* config.h */,
- 0F46809C14BA7F4D00BFE272 /* llint */,
1432EBD70A34CAD400717B9F /* API */,
9688CB120ED12B4E001D649F /* assembler */,
969A078F0ED1D3AE00F1F681 /* bytecode */,
tabWidth = 4;
usesTabs = 0;
};
- 0F46809C14BA7F4D00BFE272 /* llint */ = {
- isa = PBXGroup;
- children = (
- 0F0B839514BCF45A00885B4F /* LLIntEntrypoints.cpp */,
- 0F0B839614BCF45A00885B4F /* LLIntEntrypoints.h */,
- 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */,
- 0F0B839814BCF45A00885B4F /* LLIntThunks.h */,
- 0F4680CE14BBB3D100BFE272 /* LLIntData.cpp */,
- 0F4680CF14BBB3D100BFE272 /* LLIntData.h */,
- 0F4680C514BBB16900BFE272 /* LLIntCommon.h */,
- 0F4680C614BBB16900BFE272 /* LLIntOfflineAsmConfig.h */,
- 0F4680C714BBB16900BFE272 /* LowLevelInterpreter.cpp */,
- 0F4680C814BBB16900BFE272 /* LowLevelInterpreter.h */,
- 0F46809D14BA7F8200BFE272 /* LLIntExceptions.cpp */,
- 0F46809E14BA7F8200BFE272 /* LLIntExceptions.h */,
- 0F46809F14BA7F8200BFE272 /* LLIntSlowPaths.cpp */,
- 0F4680A014BA7F8200BFE272 /* LLIntSlowPaths.h */,
- 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */,
- );
- name = llint;
- sourceTree = "<group>";
- };
141211000A48772600480255 /* tests */ = {
isa = PBXGroup;
children = (
1429D92C0ED22D7000B89619 /* jit */ = {
isa = PBXGroup;
children = (
- 0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */,
- 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */,
0F46807F14BA572700BFE272 /* JITExceptions.cpp */,
0F46808014BA572700BFE272 /* JITExceptions.h */,
0FD82E37141AB14200179C94 /* CompactJITCodeMap.h */,
7EF6E0BB0EB7A1EC0079AFAF /* runtime */ = {
isa = PBXGroup;
children = (
- 0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */,
- 0F21C27A14BE727300ADC64B /* ExecutionHarness.h */,
0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */,
BCF605110E203EF800B9A64D /* ArgList.cpp */,
BCF605120E203EF800B9A64D /* ArgList.h */,
969A078F0ED1D3AE00F1F681 /* bytecode */ = {
isa = PBXGroup;
children = (
- 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */,
- 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */,
0F9FC8BF14E1B5FB00D52AE0 /* PolymorphicPutByIdList.cpp */,
0F9FC8C014E1B5FB00D52AE0 /* PolymorphicPutByIdList.h */,
0F9FC8C114E1B5FB00D52AE0 /* PutKind.h */,
86704B8A12DBA33700A9FE7B /* YarrPattern.h in Headers */,
86704B4312DB8A8100A9FE7B /* YarrSyntaxChecker.h in Headers */,
0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */,
- 0F4680A314BA7F8D00BFE272 /* LLIntExceptions.h in Headers */,
- 0F4680A514BA7F8D00BFE272 /* LLIntSlowPaths.h in Headers */,
0F46808214BA572D00BFE272 /* JITExceptions.h in Headers */,
- 0F4680CA14BBB16C00BFE272 /* LLIntCommon.h in Headers */,
- 0F4680CB14BBB17200BFE272 /* LLIntOfflineAsmConfig.h in Headers */,
- 0F4680CD14BBB17D00BFE272 /* LowLevelInterpreter.h in Headers */,
- 0F4680D314BBD16700BFE272 /* LLIntData.h in Headers */,
- 0F4680D514BBD24B00BFE272 /* HostCallReturnValue.h in Headers */,
- 0F0B839B14BCF46000885B4F /* LLIntEntrypoints.h in Headers */,
- 0F0B839D14BCF46600885B4F /* LLIntThunks.h in Headers */,
0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
0F0B83A914BCF56200885B4F /* HandlerInfo.h in Headers */,
0F0B83AB14BCF5BB00885B4F /* ExpressionRangeInfo.h in Headers */,
0F0B83B514BCF86200885B4F /* MethodCallLinkInfo.h in Headers */,
0F0B83B714BCF8E100885B4F /* GlobalResolveInfo.h in Headers */,
0F0B83B914BCF95F00885B4F /* CallReturnOffsetToBytecodeOffset.h in Headers */,
- 0F0FC45A14BD15F500B81154 /* LLIntCallLinkInfo.h in Headers */,
0F21C26814BE5F6800ADC64B /* JITDriver.h in Headers */,
- 0F21C27C14BE727600ADC64B /* ExecutionHarness.h in Headers */,
- 0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
- 0F21C27F14BEAA8200ADC64B /* BytecodeConventions.h in Headers */,
0F7B294A14C3CD29007C3DB1 /* DFGCCallHelpers.h in Headers */,
0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */,
0F7B294C14C3CD43007C3DB1 /* DFGByteCodeCache.h in Headers */,
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
- 0F46808E14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 0F46809A14BA7E5F00BFE272 /* Build configuration list for PBXNativeTarget "JSCLLIntOffsetsExtractor" */;
- buildPhases = (
- 0F46808B14BA7E5E00BFE272 /* Sources */,
- 0F46808C14BA7E5E00BFE272 /* Frameworks */,
- 0F46808D14BA7E5E00BFE272 /* CopyFiles */,
- );
- buildRules = (
- );
- dependencies = (
- 0F4680B214BA811500BFE272 /* PBXTargetDependency */,
- );
- name = JSCLLIntOffsetsExtractor;
- productName = JSCLLIntOffsetsExtractor;
- productReference = 0F46808F14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */;
- productType = "com.apple.product-type.tool";
- };
1412111F0A48793C00480255 /* minidom */ = {
isa = PBXNativeTarget;
buildConfigurationList = 141211390A48798400480255 /* Build configuration list for PBXNativeTarget "minidom" */;
14BD59BE0A3E8F9000BAF59C /* testapi */,
932F5BDA0822A1C700736975 /* jsc */,
651122F714046A4C002B101D /* testRegExp */,
- 0F46808E14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */,
- 0F4680A914BA7FD900BFE272 /* LLInt Offsets */,
);
};
/* End PBXProject section */
/* Begin PBXShellScriptBuildPhase section */
- 0F4680AA14BA7FD900BFE272 /* Generate Derived Sources */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- "$(SRCROOT)/llint/LowLevelAssembler.asm",
- );
- name = "Generate Derived Sources";
- outputPaths = (
- "$(BUILT_PRODUCTS_DIR)/LLIntOffsets/LLIntDesiredOffsets.h",
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "mkdir -p \"${BUILT_PRODUCTS_DIR}/LLIntOffsets/\"\n\n/usr/bin/env ruby \"${SRCROOT}/offlineasm/generate_offset_extractor.rb\" \"${SRCROOT}/llint/LowLevelInterpreter.asm\" \"${BUILT_PRODUCTS_DIR}/LLIntOffsets/LLIntDesiredOffsets.h\"\n";
- };
3713F014142905240036387F /* Check For Inappropriate Objective-C Class Names */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "mkdir -p \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore/docs\"\ncd \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore\"\n\n/bin/ln -sfh \"${SRCROOT}\" JavaScriptCore\nexport JavaScriptCore=\"JavaScriptCore\"\nexport BUILT_PRODUCTS_DIR=\"../..\"\n\nmake --no-builtin-rules -f \"JavaScriptCore/DerivedSources.make\" -j `/usr/sbin/sysctl -n hw.ncpu`\n\n/usr/bin/env ruby JavaScriptCore/offlineasm/asm.rb JavaScriptCore/llint/LowLevelInterpreter.asm ${BUILT_PRODUCTS_DIR}/JSCLLIntOffsetsExtractor LLIntAssembly.h\n";
+ shellScript = "mkdir -p \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore/docs\"\ncd \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore\"\n\n/bin/ln -sfh \"${SRCROOT}\" JavaScriptCore\nexport JavaScriptCore=\"JavaScriptCore\"\nexport BUILT_PRODUCTS_DIR=\"../..\"\n\nmake --no-builtin-rules -f \"JavaScriptCore/DerivedSources.make\" -j `/usr/sbin/sysctl -n hw.ncpu`\n";
};
9319586B09D9F91A00A56FD4 /* Check For Global Initializers */ = {
isa = PBXShellScriptBuildPhase;
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
- 0F46808B14BA7E5E00BFE272 /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 0F4680A714BA7FA100BFE272 /* LLIntOffsetsExtractor.cpp in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
1412111D0A48793C00480255 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
86704B8612DBA33700A9FE7B /* YarrJIT.cpp in Sources */,
86704B8912DBA33700A9FE7B /* YarrPattern.cpp in Sources */,
86704B4212DB8A8100A9FE7B /* YarrSyntaxChecker.cpp in Sources */,
- 0F4680A414BA7F8D00BFE272 /* LLIntSlowPaths.cpp in Sources */,
- 0F4680A814BA7FAB00BFE272 /* LLIntExceptions.cpp in Sources */,
0F46808314BA573100BFE272 /* JITExceptions.cpp in Sources */,
- 0F4680CC14BBB17A00BFE272 /* LowLevelInterpreter.cpp in Sources */,
- 0F4680D214BBD16500BFE272 /* LLIntData.cpp in Sources */,
- 0F4680D414BBD24900BFE272 /* HostCallReturnValue.cpp in Sources */,
- 0F0B839A14BCF45D00885B4F /* LLIntEntrypoints.cpp in Sources */,
- 0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */,
0F0B83B014BCF71600885B4F /* CallLinkInfo.cpp in Sources */,
0F0B83B414BCF86000885B4F /* MethodCallLinkInfo.cpp in Sources */,
F69E86C314C6E551002C2C62 /* NumberOfCores.cpp in Sources */,
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
- 0F4680B214BA811500BFE272 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 0F4680A914BA7FD900BFE272 /* LLInt Offsets */;
- targetProxy = 0F4680B114BA811500BFE272 /* PBXContainerItemProxy */;
- };
- 0F4680B414BA821400BFE272 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 0F46808E14BA7E5E00BFE272 /* JSCLLIntOffsetsExtractor */;
- targetProxy = 0F4680B314BA821400BFE272 /* PBXContainerItemProxy */;
- };
141214BF0A49190E00480255 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 1412111F0A48793C00480255 /* minidom */;
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
- 0F46809614BA7E5E00BFE272 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- ARCHS = "$(ARCHS_STANDARD_64_BIT)";
- COPY_PHASE_STRIP = NO;
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_DYNAMIC_NO_PIC = NO;
- GCC_ENABLE_OBJC_EXCEPTIONS = YES;
- GCC_OPTIMIZATION_LEVEL = 0;
- GCC_PREPROCESSOR_DEFINITIONS = (
- "DEBUG=1",
- "$(inherited)",
- );
- GCC_SYMBOLS_PRIVATE_EXTERN = NO;
- GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
- GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
- GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- "HEADER_SEARCH_PATHS[arch=*]" = (
- .,
- icu,
- "$(BUILT_PRODUCTS_DIR)/LLIntOffsets",
- "$(HEADER_SEARCH_PATHS)",
- );
- MACOSX_DEPLOYMENT_TARGET = 10.7;
- ONLY_ACTIVE_ARCH = NO;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SDKROOT = macosx;
- USER_HEADER_SEARCH_PATHS = ". icu $(BUILT_PRODUCTS_DIR)/LLIntOffsets $(HEADER_SEARCH_PATHS)";
- };
- name = Debug;
- };
- 0F46809714BA7E5E00BFE272 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- ARCHS = "$(ARCHS_STANDARD_64_BIT)";
- COPY_PHASE_STRIP = YES;
- DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_ENABLE_OBJC_EXCEPTIONS = YES;
- GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
- GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
- GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- "HEADER_SEARCH_PATHS[arch=*]" = (
- .,
- icu,
- "$(BUILT_PRODUCTS_DIR)/LLIntOffsets$(HEADER_SEARCH_PATHS)",
- );
- MACOSX_DEPLOYMENT_TARGET = 10.7;
- ONLY_ACTIVE_ARCH = NO;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SDKROOT = macosx;
- USER_HEADER_SEARCH_PATHS = ". icu $(BUILT_PRODUCTS_DIR)/LLIntOffsets $(HEADER_SEARCH_PATHS)";
- };
- name = Release;
- };
- 0F46809814BA7E5E00BFE272 /* Profiling */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- ARCHS = "$(ARCHS_STANDARD_64_BIT)";
- COPY_PHASE_STRIP = YES;
- DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_ENABLE_OBJC_EXCEPTIONS = YES;
- GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
- GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
- GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- "HEADER_SEARCH_PATHS[arch=*]" = (
- .,
- icu,
- "$(BUILT_PRODUCTS_DIR)/LLIntOffsets",
- "$(HEADER_SEARCH_PATHS)",
- );
- MACOSX_DEPLOYMENT_TARGET = 10.7;
- ONLY_ACTIVE_ARCH = NO;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SDKROOT = macosx;
- USER_HEADER_SEARCH_PATHS = ". icu $(BUILT_PRODUCTS_DIR)/LLIntOffsets $(HEADER_SEARCH_PATHS)";
- };
- name = Profiling;
- };
- 0F46809914BA7E5E00BFE272 /* Production */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- ARCHS = "$(ARCHS_STANDARD_64_BIT)";
- COPY_PHASE_STRIP = YES;
- DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_ENABLE_OBJC_EXCEPTIONS = YES;
- GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
- GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
- GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- "HEADER_SEARCH_PATHS[arch=*]" = (
- .,
- icu,
- "$(BUILT_PRODUCTS_DIR)/LLIntOffsets",
- "$(HEADER_SEARCH_PATHS)",
- );
- MACOSX_DEPLOYMENT_TARGET = 10.7;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SDKROOT = macosx;
- USER_HEADER_SEARCH_PATHS = ". icu $(BUILT_PRODUCTS_DIR)/LLIntOffsets $(HEADER_SEARCH_PATHS)";
- };
- name = Production;
- };
- 0F4680AD14BA7FD900BFE272 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- PRODUCT_NAME = "Derived Sources copy";
- };
- name = Debug;
- };
- 0F4680AE14BA7FD900BFE272 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- PRODUCT_NAME = "Derived Sources copy";
- };
- name = Release;
- };
- 0F4680AF14BA7FD900BFE272 /* Profiling */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- PRODUCT_NAME = "Derived Sources copy";
- };
- name = Profiling;
- };
- 0F4680B014BA7FD900BFE272 /* Production */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- PRODUCT_NAME = "Derived Sources copy";
- };
- name = Production;
- };
1412113A0A48798400480255 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
- 0F46809A14BA7E5F00BFE272 /* Build configuration list for PBXNativeTarget "JSCLLIntOffsetsExtractor" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 0F46809614BA7E5E00BFE272 /* Debug */,
- 0F46809714BA7E5E00BFE272 /* Release */,
- 0F46809814BA7E5E00BFE272 /* Profiling */,
- 0F46809914BA7E5E00BFE272 /* Production */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Production;
- };
- 0F4680AC14BA7FD900BFE272 /* Build configuration list for PBXAggregateTarget "LLInt Offsets" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 0F4680AD14BA7FD900BFE272 /* Debug */,
- 0F4680AE14BA7FD900BFE272 /* Release */,
- 0F4680AF14BA7FD900BFE272 /* Profiling */,
- 0F4680B014BA7FD900BFE272 /* Production */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Production;
- };
141211390A48798400480255 /* Build configuration list for PBXNativeTarget "minidom" */ = {
isa = XCConfigurationList;
buildConfigurations = (
interpreter/RegisterFile.cpp \
jit/ExecutableAllocatorFixedVMPool.cpp \
jit/ExecutableAllocator.cpp \
- jit/HostCallReturnValue.cpp \
jit/JITArithmetic.cpp \
jit/JITArithmetic32_64.cpp \
jit/JITCall.cpp \
#define GLOBAL_THUNK_ID reinterpret_cast<void*>(static_cast<intptr_t>(-1))
#define REGEXP_CODE_ID reinterpret_cast<void*>(static_cast<intptr_t>(-2))
-#include "MacroAssembler.h"
+#include <MacroAssembler.h>
#include <wtf/DataLog.h>
#include <wtf/Noncopyable.h>
#include "RefPtr.h"
#include "UnusedParam.h"
+#if ENABLE(ASSEMBLER)
+
// ASSERT_VALID_CODE_POINTER checks that ptr is a non-null pointer, and that it is a valid
// instruction address on the platform (for example, check any alignment requirements).
#if CPU(ARM_THUMB2)
{
ASSERT_VALID_CODE_POINTER(m_value);
}
-
- static MacroAssemblerCodePtr createFromExecutableAddress(void* value)
- {
- ASSERT_VALID_CODE_POINTER(value);
- MacroAssemblerCodePtr result;
- result.m_value = value;
- return result;
- }
explicit MacroAssemblerCodePtr(ReturnAddressPtr ra)
: m_value(ra.value())
} // namespace JSC
+#endif // ENABLE(ASSEMBLER)
+
#endif // MacroAssemblerCodeRef_h
+++ /dev/null
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef BytecodeConventions_h
-#define BytecodeConventions_h
-
-// Register numbers used in bytecode operations have different meaning according to their ranges:
-// 0x80000000-0xFFFFFFFF Negative indices from the CallFrame pointer are entries in the call frame, see RegisterFile.h.
-// 0x00000000-0x3FFFFFFF Forwards indices from the CallFrame pointer are local vars and temporaries with the function's callframe.
-// 0x40000000-0x7FFFFFFF Positive indices from 0x40000000 specify entries in the constant pool on the CodeBlock.
-static const int FirstConstantRegisterIndex = 0x40000000;
-
-#endif // BytecodeConventions_h
-
#include "CallLinkStatus.h"
#include "CodeBlock.h"
-#include "LLIntCallLinkInfo.h"
namespace JSC {
-CallLinkStatus CallLinkStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex)
-{
- UNUSED_PARAM(profiledBlock);
- UNUSED_PARAM(bytecodeIndex);
-#if ENABLE(LLINT)
- Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
- LLIntCallLinkInfo* callLinkInfo = instruction[4].u.callLinkInfo;
-
- return CallLinkStatus(callLinkInfo->lastSeenCallee.get(), false);
-#else
- return CallLinkStatus(0, false);
-#endif
-}
-
CallLinkStatus CallLinkStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex)
{
UNUSED_PARAM(profiledBlock);
UNUSED_PARAM(bytecodeIndex);
#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
- if (!profiledBlock->numberOfCallLinkInfos())
- return computeFromLLInt(profiledBlock, bytecodeIndex);
-
- if (profiledBlock->couldTakeSlowCase(bytecodeIndex))
- return CallLinkStatus(0, true);
-
- JSFunction* target = profiledBlock->getCallLinkInfo(bytecodeIndex).lastSeenCallee.get();
- if (!target)
- return computeFromLLInt(profiledBlock, bytecodeIndex);
-
- return CallLinkStatus(target, false);
+ return CallLinkStatus(
+ profiledBlock->getCallLinkInfo(bytecodeIndex).lastSeenCallee.get(),
+ profiledBlock->couldTakeSlowCase(bytecodeIndex));
#else
return CallLinkStatus(0, false);
#endif
static CallLinkStatus computeFor(CodeBlock*, unsigned bytecodeIndex);
- bool isSet() const { return !!m_callTarget || m_couldTakeSlowPath; }
+ bool isSet() const { return !!m_callTarget; }
- bool operator!() const { return !isSet(); }
+ bool operator!() const { return !m_callTarget; }
bool couldTakeSlowPath() const { return m_couldTakeSlowPath; }
JSFunction* callTarget() const { return m_callTarget; }
private:
- static CallLinkStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex);
-
JSFunction* m_callTarget;
bool m_couldTakeSlowPath;
};
#include "JSFunction.h"
#include "JSStaticScopeObject.h"
#include "JSValue.h"
-#include "LowLevelInterpreter.h"
#include "RepatchBuffer.h"
#include "UStringConcatenate.h"
#include <stdio.h>
for (size_t i = 0; i < instructions().size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(instructions()[i].u.opcode)])
++instructionCount;
- dataLog("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s); %d variable(s)\n\n",
+ dataLog("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n",
static_cast<unsigned long>(instructionCount),
static_cast<unsigned long>(instructions().size() * sizeof(Instruction)),
- this, m_numParameters, m_numCalleeRegisters, m_numVars);
+ this, m_numParameters, m_numCalleeRegisters);
Vector<Instruction>::const_iterator begin = instructions().begin();
Vector<Instruction>::const_iterator end = instructions().end();
printPutByIdOp(exec, location, it, "put_by_id_transition");
break;
}
- case op_put_by_id_transition_direct: {
- printPutByIdOp(exec, location, it, "put_by_id_transition_direct");
- break;
- }
- case op_put_by_id_transition_normal: {
- printPutByIdOp(exec, location, it, "put_by_id_transition_normal");
- break;
- }
case op_put_by_id_generic: {
printPutByIdOp(exec, location, it, "put_by_id_generic");
break;
{
setNumParameters(other.numParameters());
optimizeAfterWarmUp();
- jitAfterWarmUp();
if (other.m_rareData) {
createRareDataIfNecessary();
ASSERT(m_source);
optimizeAfterWarmUp();
- jitAfterWarmUp();
#if DUMP_CODE_BLOCK_STATISTICS
liveCodeBlockSet.add(this);
#if ENABLE(VERBOSE_VALUE_PROFILE)
dumpValueProfiles();
#endif
-
-#if ENABLE(LLINT)
- while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end())
- m_incomingLLIntCalls.begin()->remove();
-#endif // ENABLE(LLINT)
+
#if ENABLE(JIT)
// We may be destroyed before any CodeBlocks that refer to us are destroyed.
// Consider that two CodeBlocks become unreachable at the same time. There
#else
static const bool verboseUnlinking = false;
#endif
-#endif // ENABLE(JIT)
+#endif
-#if ENABLE(LLINT)
- Interpreter* interpreter = m_globalData->interpreter;
- // interpreter->classicEnabled() returns true if the old C++ interpreter is enabled. If that's enabled
- // then we're not using LLInt.
- if (!interpreter->classicEnabled()) {
- for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) {
- Instruction* curInstruction = &instructions()[m_propertyAccessInstructions[i]];
- switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) {
- case op_get_by_id:
- case op_put_by_id:
- if (!curInstruction[4].u.structure || Heap::isMarked(curInstruction[4].u.structure.get()))
- break;
- if (verboseUnlinking)
- dataLog("Clearing LLInt property access with structure %p.\n", curInstruction[4].u.structure.get());
- curInstruction[4].u.structure.clear();
- curInstruction[5].u.operand = 0;
- break;
- case op_put_by_id_transition_direct:
- case op_put_by_id_transition_normal:
- if (Heap::isMarked(curInstruction[4].u.structure.get())
- && Heap::isMarked(curInstruction[6].u.structure.get())
- && Heap::isMarked(curInstruction[7].u.structureChain.get()))
- break;
- if (verboseUnlinking) {
- dataLog("Clearing LLInt put transition with structures %p -> %p, chain %p.\n",
- curInstruction[4].u.structure.get(),
- curInstruction[6].u.structure.get(),
- curInstruction[7].u.structureChain.get());
- }
- curInstruction[4].u.structure.clear();
- curInstruction[6].u.structure.clear();
- curInstruction[7].u.structureChain.clear();
- curInstruction[0].u.opcode = interpreter->getOpcode(op_put_by_id);
- break;
- default:
- ASSERT_NOT_REACHED();
- }
- }
- for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i) {
- Instruction* curInstruction = &instructions()[m_globalResolveInstructions[i]];
- ASSERT(interpreter->getOpcodeID(curInstruction[0].u.opcode) == op_resolve_global
- || interpreter->getOpcodeID(curInstruction[0].u.opcode) == op_resolve_global_dynamic);
- if (!curInstruction[3].u.structure || Heap::isMarked(curInstruction[3].u.structure.get()))
- continue;
- if (verboseUnlinking)
- dataLog("Clearing LLInt global resolve cache with structure %p.\n", curInstruction[3].u.structure.get());
- curInstruction[3].u.structure.clear();
- curInstruction[4].u.operand = 0;
- }
- for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) {
- if (m_llintCallLinkInfos[i].isLinked() && !Heap::isMarked(m_llintCallLinkInfos[i].callee.get())) {
- if (verboseUnlinking)
- dataLog("Clearing LLInt call from %p.\n", this);
- m_llintCallLinkInfos[i].unlink();
- }
- if (!!m_llintCallLinkInfos[i].lastSeenCallee && !Heap::isMarked(m_llintCallLinkInfos[i].lastSeenCallee.get()))
- m_llintCallLinkInfos[i].lastSeenCallee.clear();
- }
- }
-#endif // ENABLE(LLINT)
-
#if ENABLE(DFG_JIT)
// Check if we're not live. If we are, then jettison.
if (!(shouldImmediatelyAssumeLivenessDuringScan() || m_dfgData->livenessHasBeenProved)) {
for (unsigned i = 0; i < numberOfCallLinkInfos(); ++i) {
if (callLinkInfo(i).isLinked() && !Heap::isMarked(callLinkInfo(i).callee.get())) {
if (verboseUnlinking)
- dataLog("Clearing call from %p to %p.\n", this, callLinkInfo(i).callee.get());
+ dataLog("Clearing call from %p.\n", this);
callLinkInfo(i).unlink(*m_globalData, repatchBuffer);
}
if (!!callLinkInfo(i).lastSeenCallee
for (size_t i = 0; i < m_functionDecls.size(); ++i)
visitor.append(&m_functionDecls[i]);
#if ENABLE(CLASSIC_INTERPRETER)
- if (m_globalData->interpreter->classicEnabled()) {
- for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i)
- visitStructures(visitor, &instructions()[m_propertyAccessInstructions[i]]);
- for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)
- visitStructures(visitor, &instructions()[m_globalResolveInstructions[i]]);
- }
+ for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i)
+ visitStructures(visitor, &instructions()[m_propertyAccessInstructions[i]]);
+ for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)
+ visitStructures(visitor, &instructions()[m_globalResolveInstructions[i]]);
#endif
#if ENABLE(DFG_JIT)
// Make sure that executables that we have inlined don't die.
// FIXME: If they would have otherwise died, we should probably trigger recompilation.
for (size_t i = 0; i < inlineCallFrames().size(); ++i) {
- InlineCallFrame& inlineCallFrame = inlineCallFrames()[i];
- visitor.append(&inlineCallFrame.executable);
- visitor.append(&inlineCallFrame.callee);
+ visitor.append(&inlineCallFrames()[i].executable);
+ visitor.append(&inlineCallFrames()[i].callee);
}
}
#endif
}
return addConstant(v);
}
-
+
#if ENABLE(JIT)
void CodeBlock::unlinkCalls()
{
if (!!m_alternative)
m_alternative->unlinkCalls();
-#if ENABLE(LLINT)
- for (size_t i = 0; i < m_llintCallLinkInfos.size(); ++i) {
- if (m_llintCallLinkInfos[i].isLinked())
- m_llintCallLinkInfos[i].unlink();
- }
-#endif
if (!(m_callLinkInfos.size() || m_methodCallLinkInfos.size()))
return;
if (!m_globalData->canUseJIT())
void CodeBlock::unlinkIncomingCalls()
{
-#if ENABLE(LLINT)
- while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end())
- m_incomingLLIntCalls.begin()->unlink();
-#endif
- if (m_incomingCalls.isEmpty())
- return;
RepatchBuffer repatchBuffer(this);
while (m_incomingCalls.begin() != m_incomingCalls.end())
m_incomingCalls.begin()->unlink(*m_globalData, repatchBuffer);
}
-
-unsigned CodeBlock::bytecodeOffset(ExecState* exec, ReturnAddressPtr returnAddress)
-{
-#if ENABLE(LLINT)
- if (returnAddress.value() >= bitwise_cast<void*>(&llint_begin)
- && returnAddress.value() <= bitwise_cast<void*>(&llint_end)) {
- ASSERT(exec->codeBlock());
- ASSERT(exec->codeBlock() == this);
- ASSERT(JITCode::isBaselineCode(getJITType()));
- Instruction* instruction = exec->currentVPC();
- ASSERT(instruction);
-
- // The LLInt stores the PC after the call instruction rather than the PC of
- // the call instruction. This requires some correcting. We rely on the fact
- // that the preceding instruction must be one of the call instructions, so
- // either it's a call_varargs or it's a call, construct, or eval.
- ASSERT(OPCODE_LENGTH(op_call_varargs) <= OPCODE_LENGTH(op_call));
- ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
- ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_eval));
- if (instruction[-OPCODE_LENGTH(op_call_varargs)].u.pointer == bitwise_cast<void*>(llint_op_call_varargs)) {
- // We know that the preceding instruction must be op_call_varargs because there is no way that
- // the pointer to the call_varargs could be an operand to the call.
- instruction -= OPCODE_LENGTH(op_call_varargs);
- ASSERT(instruction[-OPCODE_LENGTH(op_call)].u.pointer != bitwise_cast<void*>(llint_op_call)
- && instruction[-OPCODE_LENGTH(op_call)].u.pointer != bitwise_cast<void*>(llint_op_construct)
- && instruction[-OPCODE_LENGTH(op_call)].u.pointer != bitwise_cast<void*>(llint_op_call_eval));
- } else {
- // Must be that the last instruction was some op_call.
- ASSERT(instruction[-OPCODE_LENGTH(op_call)].u.pointer == bitwise_cast<void*>(llint_op_call)
- || instruction[-OPCODE_LENGTH(op_call)].u.pointer == bitwise_cast<void*>(llint_op_construct)
- || instruction[-OPCODE_LENGTH(op_call)].u.pointer == bitwise_cast<void*>(llint_op_call_eval));
- instruction -= OPCODE_LENGTH(op_call);
- }
-
- return bytecodeOffset(instruction);
- }
-#else
- UNUSED_PARAM(exec);
-#endif
- if (!m_rareData)
- return 1;
- Vector<CallReturnOffsetToBytecodeOffset>& callIndices = m_rareData->m_callReturnIndexVector;
- if (!callIndices.size())
- return 1;
- return binarySearch<CallReturnOffsetToBytecodeOffset, unsigned, getCallReturnOffset>(callIndices.begin(), callIndices.size(), getJITCode().offsetOf(returnAddress.value()))->bytecodeOffset;
-}
#endif
void CodeBlock::clearEvalCache()
void ProgramCodeBlock::jettison()
{
- ASSERT(JITCode::isOptimizingJIT(getJITType()));
+ ASSERT(getJITType() != JITCode::BaselineJIT);
ASSERT(this == replacement());
static_cast<ProgramExecutable*>(ownerExecutable())->jettisonOptimizedCode(*globalData());
}
void EvalCodeBlock::jettison()
{
- ASSERT(JITCode::isOptimizingJIT(getJITType()));
+ ASSERT(getJITType() != JITCode::BaselineJIT);
ASSERT(this == replacement());
static_cast<EvalExecutable*>(ownerExecutable())->jettisonOptimizedCode(*globalData());
}
void FunctionCodeBlock::jettison()
{
- ASSERT(JITCode::isOptimizingJIT(getJITType()));
+ ASSERT(getJITType() != JITCode::BaselineJIT);
ASSERT(this == replacement());
static_cast<FunctionExecutable*>(ownerExecutable())->jettisonOptimizedCodeFor(*globalData(), m_isConstructor ? CodeForConstruct : CodeForCall);
}
-
-void ProgramCodeBlock::jitCompileImpl(JSGlobalData& globalData)
-{
- ASSERT(getJITType() == JITCode::InterpreterThunk);
- ASSERT(this == replacement());
- return static_cast<ProgramExecutable*>(ownerExecutable())->jitCompile(globalData);
-}
-
-void EvalCodeBlock::jitCompileImpl(JSGlobalData& globalData)
-{
- ASSERT(getJITType() == JITCode::InterpreterThunk);
- ASSERT(this == replacement());
- return static_cast<EvalExecutable*>(ownerExecutable())->jitCompile(globalData);
-}
-
-void FunctionCodeBlock::jitCompileImpl(JSGlobalData& globalData)
-{
- ASSERT(getJITType() == JITCode::InterpreterThunk);
- ASSERT(this == replacement());
- return static_cast<FunctionExecutable*>(ownerExecutable())->jitCompileFor(globalData, m_isConstructor ? CodeForConstruct : CodeForCall);
-}
#endif
#if ENABLE(VALUE_PROFILER)
#ifndef CodeBlock_h
#define CodeBlock_h
-#include "BytecodeConventions.h"
#include "CallLinkInfo.h"
#include "CallReturnOffsetToBytecodeOffset.h"
#include "CodeOrigin.h"
#include "JITWriteBarrier.h"
#include "JSGlobalObject.h"
#include "JumpTable.h"
-#include "LLIntCallLinkInfo.h"
#include "LineInfo.h"
#include "Nodes.h"
#include "PredictionTracker.h"
#include <wtf/Vector.h>
#include "StructureStubInfo.h"
+// Register numbers used in bytecode operations have different meaning according to their ranges:
+// 0x80000000-0xFFFFFFFF Negative indices from the CallFrame pointer are entries in the call frame, see RegisterFile.h.
+// 0x00000000-0x3FFFFFFF Forwards indices from the CallFrame pointer are local vars and temporaries with the function's callframe.
+// 0x40000000-0x7FFFFFFF Positive indices from 0x40000000 specify entries in the constant pool on the CodeBlock.
+static const int FirstConstantRegisterIndex = 0x40000000;
+
namespace JSC {
- class DFGCodeBlocks;
class ExecState;
- class LLIntOffsetsExtractor;
+ class DFGCodeBlocks;
inline int unmodifiedArgumentsRegister(int argumentsRegister) { return argumentsRegister - 1; }
class CodeBlock : public UnconditionalFinalizer, public WeakReferenceHarvester {
WTF_MAKE_FAST_ALLOCATED;
friend class JIT;
- friend class LLIntOffsetsExtractor;
public:
enum CopyParsedBlockTag { CopyParsedBlock };
protected:
while (result->alternative())
result = result->alternative();
ASSERT(result);
- ASSERT(JITCode::isBaselineCode(result->getJITType()));
+ ASSERT(result->getJITType() == JITCode::BaselineJIT);
return result;
}
#endif
return *(binarySearch<MethodCallLinkInfo, unsigned, getMethodCallLinkInfoBytecodeIndex>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), bytecodeIndex));
}
- unsigned bytecodeOffset(ExecState*, ReturnAddressPtr);
+ unsigned bytecodeOffset(ReturnAddressPtr returnAddress)
+ {
+ if (!m_rareData)
+ return 1;
+ Vector<CallReturnOffsetToBytecodeOffset>& callIndices = m_rareData->m_callReturnIndexVector;
+ if (!callIndices.size())
+ return 1;
+ return binarySearch<CallReturnOffsetToBytecodeOffset, unsigned, getCallReturnOffset>(callIndices.begin(), callIndices.size(), getJITCode().offsetOf(returnAddress.value()))->bytecodeOffset;
+ }
unsigned bytecodeOffsetForCallAtIndex(unsigned index)
{
{
m_incomingCalls.push(incoming);
}
-#if ENABLE(LLINT)
- void linkIncomingCall(LLIntCallLinkInfo* incoming)
- {
- m_incomingLLIntCalls.push(incoming);
- }
-#endif // ENABLE(LLINT)
void unlinkIncomingCalls();
-#endif // ENABLE(JIT)
+#endif
-#if ENABLE(DFG_JIT) || ENABLE(LLINT)
+#if ENABLE(DFG_JIT)
void setJITCodeMap(PassOwnPtr<CompactJITCodeMap> jitCodeMap)
{
m_jitCodeMap = jitCodeMap;
{
return m_jitCodeMap.get();
}
-#endif
-#if ENABLE(DFG_JIT)
void createDFGDataIfNecessary()
{
if (!!m_dfgData)
}
#endif
+#if ENABLE(CLASSIC_INTERPRETER)
unsigned bytecodeOffset(Instruction* returnAddress)
{
- ASSERT(returnAddress >= instructions().begin() && returnAddress < instructions().end());
return static_cast<Instruction*>(returnAddress) - instructions().begin();
}
+#endif
void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; }
bool isNumericCompareFunction() { return m_isNumericCompareFunction; }
ExecutableMemoryHandle* executableMemory() { return getJITCode().getExecutableMemory(); }
virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*) = 0;
virtual void jettison() = 0;
- bool jitCompile(JSGlobalData& globalData)
- {
- if (getJITType() != JITCode::InterpreterThunk) {
- ASSERT(getJITType() == JITCode::BaselineJIT);
- return false;
- }
-#if ENABLE(JIT)
- jitCompileImpl(globalData);
- return true;
-#else
- UNUSED_PARAM(globalData);
- return false;
-#endif
- }
virtual CodeBlock* replacement() = 0;
enum CompileWithDFGState {
bool hasOptimizedReplacement()
{
- ASSERT(JITCode::isBaselineCode(getJITType()));
+ ASSERT(getJITType() == JITCode::BaselineJIT);
bool result = replacement()->getJITType() > getJITType();
#if !ASSERT_DISABLED
if (result)
ASSERT(replacement()->getJITType() == JITCode::DFGJIT);
else {
- ASSERT(JITCode::isBaselineCode(replacement()->getJITType()));
+ ASSERT(replacement()->getJITType() == JITCode::BaselineJIT);
ASSERT(replacement() == this);
}
#endif
void clearEvalCache();
+#if ENABLE(CLASSIC_INTERPRETER)
void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
{
- m_propertyAccessInstructions.append(propertyAccessInstruction);
+ if (!m_globalData->canUseJIT())
+ m_propertyAccessInstructions.append(propertyAccessInstruction);
}
void addGlobalResolveInstruction(unsigned globalResolveInstruction)
{
- m_globalResolveInstructions.append(globalResolveInstruction);
+ if (!m_globalData->canUseJIT())
+ m_globalResolveInstructions.append(globalResolveInstruction);
}
bool hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset);
-#if ENABLE(LLINT)
- LLIntCallLinkInfo* addLLIntCallLinkInfo()
- {
- m_llintCallLinkInfos.append(LLIntCallLinkInfo());
- return &m_llintCallLinkInfos.last();
- }
#endif
#if ENABLE(JIT)
void setNumberOfStructureStubInfos(size_t size) { m_structureStubInfos.grow(size); }
void addGlobalResolveInfo(unsigned globalResolveInstruction)
{
- m_globalResolveInfos.append(GlobalResolveInfo(globalResolveInstruction));
+ if (m_globalData->canUseJIT())
+ m_globalResolveInfos.append(GlobalResolveInfo(globalResolveInstruction));
}
GlobalResolveInfo& globalResolveInfo(int index) { return m_globalResolveInfos[index]; }
bool hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset);
void addMethodCallLinkInfos(unsigned n) { ASSERT(m_globalData->canUseJIT()); m_methodCallLinkInfos.grow(n); }
MethodCallLinkInfo& methodCallLinkInfo(int index) { return m_methodCallLinkInfos[index]; }
- size_t numberOfMethodCallLinkInfos() { return m_methodCallLinkInfos.size(); }
#endif
#if ENABLE(VALUE_PROFILER)
bytecodeOffset].u.opcode)) - 1].u.profile == result);
return result;
}
- PredictedType valueProfilePredictionForBytecodeOffset(int bytecodeOffset)
- {
- return valueProfileForBytecodeOffset(bytecodeOffset)->computeUpdatedPrediction();
- }
unsigned totalNumberOfValueProfiles()
{
bool likelyToTakeSlowCase(int bytecodeOffset)
{
- if (!numberOfRareCaseProfiles())
- return false;
unsigned value = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
return value >= Options::likelyToTakeSlowCaseMinimumCount && static_cast<double>(value) / m_executionEntryCount >= Options::likelyToTakeSlowCaseThreshold;
}
bool couldTakeSlowCase(int bytecodeOffset)
{
- if (!numberOfRareCaseProfiles())
- return false;
unsigned value = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
return value >= Options::couldTakeSlowCaseMinimumCount && static_cast<double>(value) / m_executionEntryCount >= Options::couldTakeSlowCaseThreshold;
}
bool likelyToTakeSpecialFastCase(int bytecodeOffset)
{
- if (!numberOfRareCaseProfiles())
- return false;
unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
return specialFastCaseCount >= Options::likelyToTakeSlowCaseMinimumCount && static_cast<double>(specialFastCaseCount) / m_executionEntryCount >= Options::likelyToTakeSlowCaseThreshold;
}
bool likelyToTakeDeepestSlowCase(int bytecodeOffset)
{
- if (!numberOfRareCaseProfiles())
- return false;
unsigned slowCaseCount = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
unsigned value = slowCaseCount - specialFastCaseCount;
bool likelyToTakeAnySlowCase(int bytecodeOffset)
{
- if (!numberOfRareCaseProfiles())
- return false;
unsigned slowCaseCount = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
unsigned value = slowCaseCount + specialFastCaseCount;
bool addFrequentExitSite(const DFG::FrequentExitSite& site)
{
- ASSERT(JITCode::isBaselineCode(getJITType()));
+ ASSERT(getJITType() == JITCode::BaselineJIT);
return m_exitProfile.add(site);
}
void copyPostParseDataFrom(CodeBlock* alternative);
void copyPostParseDataFromAlternative();
- // Functions for controlling when JITting kicks in, in a mixed mode
- // execution world.
-
- void dontJITAnytimeSoon()
- {
- m_llintExecuteCounter = Options::executionCounterValueForDontJITAnytimeSoon;
- }
-
- void jitAfterWarmUp()
- {
- m_llintExecuteCounter = Options::executionCounterValueForJITAfterWarmUp;
- }
-
- void jitSoon()
- {
- m_llintExecuteCounter = Options::executionCounterValueForJITSoon;
- }
-
- int32_t llintExecuteCounter() const
- {
- return m_llintExecuteCounter;
- }
-
// Functions for controlling when tiered compilation kicks in. This
// controls both when the optimizing compiler is invoked and when OSR
// entry happens. Two triggers exist: the loop trigger and the return
bool m_shouldDiscardBytecode;
protected:
-#if ENABLE(JIT)
- virtual void jitCompileImpl(JSGlobalData&) = 0;
-#endif
virtual void visitWeakReferences(SlotVisitor&);
virtual void finalizeUnconditionally();
RefPtr<SourceProvider> m_source;
unsigned m_sourceOffset;
+#if ENABLE(CLASSIC_INTERPRETER)
Vector<unsigned> m_propertyAccessInstructions;
Vector<unsigned> m_globalResolveInstructions;
-#if ENABLE(LLINT)
- SegmentedVector<LLIntCallLinkInfo, 8> m_llintCallLinkInfos;
- SentinelLinkedList<LLIntCallLinkInfo, BasicRawSentinelNode<LLIntCallLinkInfo> > m_incomingLLIntCalls;
#endif
#if ENABLE(JIT)
Vector<StructureStubInfo> m_structureStubInfos;
MacroAssemblerCodePtr m_jitCodeWithArityCheck;
SentinelLinkedList<CallLinkInfo, BasicRawSentinelNode<CallLinkInfo> > m_incomingCalls;
#endif
-#if ENABLE(DFG_JIT) || ENABLE(LLINT)
- OwnPtr<CompactJITCodeMap> m_jitCodeMap;
-#endif
#if ENABLE(DFG_JIT)
+ OwnPtr<CompactJITCodeMap> m_jitCodeMap;
+
struct WeakReferenceTransition {
WeakReferenceTransition() { }
OwnPtr<CodeBlock> m_alternative;
- int32_t m_llintExecuteCounter;
-
int32_t m_jitExecuteCounter;
uint32_t m_speculativeSuccessCounter;
uint32_t m_speculativeFailCounter;
uint8_t m_optimizationDelayCounter;
uint8_t m_reoptimizationRetryCounter;
-
+
struct RareData {
WTF_MAKE_FAST_ALLOCATED;
public:
protected:
virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
virtual void jettison();
- virtual void jitCompileImpl(JSGlobalData&);
virtual CodeBlock* replacement();
virtual bool canCompileWithDFGInternal();
#endif
protected:
virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
virtual void jettison();
- virtual void jitCompileImpl(JSGlobalData&);
virtual CodeBlock* replacement();
virtual bool canCompileWithDFGInternal();
#endif
protected:
virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
virtual void jettison();
- virtual void jitCompileImpl(JSGlobalData&);
virtual CodeBlock* replacement();
virtual bool canCompileWithDFGInternal();
#endif
#include "GetByIdStatus.h"
#include "CodeBlock.h"
-#include "LowLevelInterpreter.h"
namespace JSC {
-GetByIdStatus GetByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
-{
- UNUSED_PARAM(profiledBlock);
- UNUSED_PARAM(bytecodeIndex);
- UNUSED_PARAM(ident);
-#if ENABLE(LLINT)
- Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
-
- if (instruction[0].u.opcode == llint_op_method_check)
- instruction++;
-
- Structure* structure = instruction[4].u.structure.get();
- if (!structure)
- return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
-
- size_t offset = structure->get(*profiledBlock->globalData(), ident);
- if (offset == notFound)
- return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
-
- return GetByIdStatus(SimpleDirect, StructureSet(structure), offset, false);
-#else
- return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
-#endif
-}
-
GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
{
UNUSED_PARAM(profiledBlock);
UNUSED_PARAM(bytecodeIndex);
UNUSED_PARAM(ident);
#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
- if (!profiledBlock->numberOfStructureStubInfos())
- return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
-
// First check if it makes either calls, in which case we want to be super careful, or
// if it's not set at all, in which case we punt.
StructureStubInfo& stubInfo = profiledBlock->getStubInfo(bytecodeIndex);
if (!stubInfo.seen)
- return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
+ return GetByIdStatus(NoInformation, StructureSet(), notFound);
PolymorphicAccessStructureList* list;
int listSize;
}
for (int i = 0; i < listSize; ++i) {
if (!list->list[i].isDirect)
- return GetByIdStatus(MakesCalls, StructureSet(), notFound, true);
+ return GetByIdStatus(MakesCalls, StructureSet(), notFound);
}
// Next check if it takes slow case, in which case we want to be kind of careful.
if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex))
- return GetByIdStatus(TakesSlowPath, StructureSet(), notFound, true);
+ return GetByIdStatus(TakesSlowPath, StructureSet(), notFound);
// Finally figure out if we can derive an access strategy.
GetByIdStatus result;
- result.m_wasSeenInJIT = true;
switch (stubInfo.accessType) {
case access_unset:
- return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
+ return GetByIdStatus(NoInformation, StructureSet(), notFound);
case access_get_by_id_self: {
Structure* structure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
return result;
#else // ENABLE(JIT)
- return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
+ return GetByIdStatus(NoInformation, StructureSet(), notFound);
#endif // ENABLE(JIT)
}
{
}
- GetByIdStatus(State state, const StructureSet& structureSet, size_t offset, bool wasSeenInJIT)
+ GetByIdStatus(State state, const StructureSet& structureSet, size_t offset)
: m_state(state)
, m_structureSet(structureSet)
, m_offset(offset)
- , m_wasSeenInJIT(wasSeenInJIT)
{
ASSERT((state == SimpleDirect) == (offset != notFound));
}
const StructureSet& structureSet() const { return m_structureSet; }
size_t offset() const { return m_offset; }
- bool wasSeenInJIT() const { return m_wasSeenInJIT; }
-
private:
- static GetByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, Identifier&);
-
State m_state;
StructureSet m_structureSet;
size_t m_offset;
- bool m_wasSeenInJIT;
};
} // namespace JSC
class JSCell;
class Structure;
class StructureChain;
- struct LLIntCallLinkInfo;
struct ValueProfile;
#if ENABLE(JIT)
#endif
struct Instruction {
- Instruction()
- {
- u.jsCell.clear();
- }
-
Instruction(Opcode opcode)
{
#if !ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
Instruction(PropertySlot::GetValueFunc getterFunc) { u.getterFunc = getterFunc; }
- Instruction(LLIntCallLinkInfo* callLinkInfo) { u.callLinkInfo = callLinkInfo; }
-
Instruction(ValueProfile* profile) { u.profile = profile; }
union {
WriteBarrierBase<StructureChain> structureChain;
WriteBarrierBase<JSCell> jsCell;
PropertySlot::GetValueFunc getterFunc;
- LLIntCallLinkInfo* callLinkInfo;
ValueProfile* profile;
- void* pointer;
} u;
private:
+++ /dev/null
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef LLIntCallLinkInfo_h
-#define LLIntCallLinkInfo_h
-
-#include "JSFunction.h"
-#include "MacroAssemblerCodeRef.h"
-#include <wtf/SentinelLinkedList.h>
-
-namespace JSC {
-
-struct Instruction;
-
-struct LLIntCallLinkInfo : public BasicRawSentinelNode<LLIntCallLinkInfo> {
- LLIntCallLinkInfo()
- {
- }
-
- ~LLIntCallLinkInfo()
- {
- if (isOnList())
- remove();
- }
-
- bool isLinked() { return callee; }
-
- void unlink()
- {
- callee.clear();
- machineCodeTarget = MacroAssemblerCodePtr();
- if (isOnList())
- remove();
- }
-
- WriteBarrier<JSFunction> callee;
- WriteBarrier<JSFunction> lastSeenCallee;
- MacroAssemblerCodePtr machineCodeTarget;
-};
-
-} // namespace JSC
-
-#endif // LLIntCallLinkInfo_h
-
UNUSED_PARAM(profiledBlock);
UNUSED_PARAM(bytecodeIndex);
#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
- // NOTE: This does not have an LLInt fall-back because LLInt does not do any method
- // call link caching.
- if (!profiledBlock->numberOfMethodCallLinkInfos())
- return MethodCallLinkStatus();
-
MethodCallLinkInfo& methodCall = profiledBlock->getMethodCallLinkInfo(bytecodeIndex);
if (!methodCall.seen || !methodCall.cachedStructure)
namespace JSC {
+#if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING) || ENABLE(CODEBLOCK_SAMPLING) || ENABLE(OPCODE_STATS)
+
const char* const opcodeNames[] = {
#define OPCODE_NAME_ENTRY(opcode, size) #opcode,
FOR_EACH_OPCODE_ID(OPCODE_NAME_ENTRY)
#undef OPCODE_NAME_ENTRY
};
+#endif
+
#if ENABLE(OPCODE_STATS)
long long OpcodeStats::opcodeCounts[numOpcodeIDs];
macro(op_get_arguments_length, 4) \
macro(op_put_by_id, 9) \
macro(op_put_by_id_transition, 9) \
- macro(op_put_by_id_transition_direct, 9) \
- macro(op_put_by_id_transition_normal, 9) \
macro(op_put_by_id_replace, 9) \
macro(op_put_by_id_generic, 9) \
macro(op_del_by_id, 4) \
typedef enum { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) } OpcodeID;
#undef OPCODE_ID_ENUM
- const int maxOpcodeLength = 9;
const int numOpcodeIDs = op_end + 1;
#define OPCODE_ID_LENGTHS(id, length) const int id##_length = length;
FOR_EACH_OPCODE_ID(VERIFY_OPCODE_ID);
#undef VERIFY_OPCODE_ID
-#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)
+#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
#if COMPILER(RVCT) || COMPILER(INTEL)
typedef void* Opcode;
#else
typedef OpcodeID Opcode;
#endif
+#if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING) || ENABLE(CODEBLOCK_SAMPLING) || ENABLE(OPCODE_STATS)
+
#define PADDING_STRING " "
#define PADDING_STRING_LENGTH static_cast<unsigned>(strlen(PADDING_STRING))
#undef PADDING_STRING_LENGTH
#undef PADDING_STRING
+#endif
+
#if ENABLE(OPCODE_STATS)
struct OpcodeStats {
#include "PutByIdStatus.h"
#include "CodeBlock.h"
-#include "LowLevelInterpreter.h"
#include "Structure.h"
#include "StructureChain.h"
namespace JSC {
-PutByIdStatus PutByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
-{
- UNUSED_PARAM(profiledBlock);
- UNUSED_PARAM(bytecodeIndex);
- UNUSED_PARAM(ident);
-#if ENABLE(LLINT)
- Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
-
- Structure* structure = instruction[4].u.structure.get();
- if (!structure)
- return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
-
- if (instruction[0].u.opcode == llint_op_put_by_id) {
- size_t offset = structure->get(*profiledBlock->globalData(), ident);
- if (offset == notFound)
- return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
-
- return PutByIdStatus(SimpleReplace, structure, 0, 0, offset);
- }
-
- ASSERT(instruction[0].u.opcode == llint_op_put_by_id_transition_direct
- || instruction[0].u.opcode == llint_op_put_by_id_transition_normal);
-
- Structure* newStructure = instruction[6].u.structure.get();
- StructureChain* chain = instruction[7].u.structureChain.get();
- ASSERT(newStructure);
- ASSERT(chain);
-
- size_t offset = newStructure->get(*profiledBlock->globalData(), ident);
- if (offset == notFound)
- return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
-
- return PutByIdStatus(SimpleTransition, structure, newStructure, chain, offset);
-#else
- return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
-#endif
-}
-
PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
{
UNUSED_PARAM(profiledBlock);
UNUSED_PARAM(bytecodeIndex);
UNUSED_PARAM(ident);
#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
- if (!profiledBlock->numberOfStructureStubInfos())
- return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
-
if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex))
return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound);
StructureStubInfo& stubInfo = profiledBlock->getStubInfo(bytecodeIndex);
if (!stubInfo.seen)
- return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
+ return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
switch (stubInfo.accessType) {
case access_unset:
- return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
+ return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
case access_put_by_id_replace: {
size_t offset = stubInfo.u.putByIdReplace.baseObjectStructure->get(
size_t offset() const { return m_offset; }
private:
- static PutByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, Identifier&);
-
State m_state;
Structure* m_oldStructure;
Structure* m_newStructure;
#include "JSActivation.h"
#include "JSFunction.h"
#include "Interpreter.h"
-#include "LowLevelInterpreter.h"
#include "ScopeChain.h"
#include "StrongInlines.h"
#include "UString.h"
#if ENABLE(JIT)
m_codeBlock->addGlobalResolveInfo(instructions().size());
#endif
+#if ENABLE(CLASSIC_INTERPRETER)
m_codeBlock->addGlobalResolveInstruction(instructions().size());
+#endif
bool dynamic = resolveResult.isDynamic() && resolveResult.depth();
ValueProfile* profile = emitProfiledOpcode(dynamic ? op_resolve_global_dynamic : op_resolve_global);
instructions().append(dst->index());
return baseDst;
}
+
+
+
ValueProfile* profile = emitProfiledOpcode(op_resolve_with_base);
instructions().append(baseDst->index());
instructions().append(propDst->index());
RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
{
+#if ENABLE(CLASSIC_INTERPRETER)
m_codeBlock->addPropertyAccessInstruction(instructions().size());
+#endif
ValueProfile* profile = emitProfiledOpcode(op_get_by_id);
instructions().append(dst->index());
RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
{
+#if ENABLE(CLASSIC_INTERPRETER)
m_codeBlock->addPropertyAccessInstruction(instructions().size());
+#endif
emitOpcode(op_put_by_id);
instructions().append(base->index());
RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value)
{
+#if ENABLE(CLASSIC_INTERPRETER)
m_codeBlock->addPropertyAccessInstruction(instructions().size());
+#endif
emitOpcode(op_put_by_id);
instructions().append(base->index());
instructions().append(func->index()); // func
instructions().append(callArguments.argumentCountIncludingThis()); // argCount
instructions().append(callArguments.registerOffset()); // registerOffset
-#if ENABLE(LLINT)
- instructions().append(m_codeBlock->addLLIntCallLinkInfo());
-#else
instructions().append(0);
-#endif
instructions().append(0);
if (dst != ignoredResult()) {
ValueProfile* profile = emitProfiledOpcode(op_call_put_result);
instructions().append(func->index()); // func
instructions().append(callArguments.argumentCountIncludingThis()); // argCount
instructions().append(callArguments.registerOffset()); // registerOffset
-#if ENABLE(LLINT)
- instructions().append(m_codeBlock->addLLIntCallLinkInfo());
-#else
instructions().append(0);
-#endif
instructions().append(0);
if (dst != ignoredResult()) {
ValueProfile* profile = emitProfiledOpcode(op_call_put_result);
{
m_usesExceptions = true;
#if ENABLE(JIT)
-#if ENABLE(LLINT)
- HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(bitwise_cast<void*>(&llint_op_catch))) };
-#else
HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel() };
-#endif
#else
HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth };
#endif
{
UNUSED_PARAM(nodeIndex);
- PredictedType prediction = m_inlineStackTop->m_profiledBlock->valueProfilePredictionForBytecodeOffset(bytecodeIndex);
+ ValueProfile* profile = m_inlineStackTop->m_profiledBlock->valueProfileForBytecodeOffset(bytecodeIndex);
+ ASSERT(profile);
+ PredictedType prediction = profile->computeUpdatedPrediction();
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLog("Dynamic [@%u, bc#%u] prediction: %s\n", nodeIndex, bytecodeIndex, predictionToString(prediction));
#endif
// If we get here then it looks like we should definitely inline this code. Proceed
// with parsing the code to get bytecode, so that we can then parse the bytecode.
- // Note that if LLInt is enabled, the bytecode will always be available. Also note
- // that if LLInt is enabled, we may inline a code block that has never been JITted
- // before!
CodeBlock* codeBlock = m_codeBlockCache.get(CodeBlockKey(executable, kind), expectedFunction->scope());
if (!codeBlock)
return false;
m_inlineStackTop->m_profiledBlock, m_currentIndex);
if (methodCallStatus.isSet()
- && !getByIdStatus.wasSeenInJIT()
+ && !getByIdStatus.isSet()
&& !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
// It's monomorphic as far as we can tell, since the method_check was linked
// but the slow path (i.e. the normal get_by_id) never fired.
NEXT_OPCODE(op_get_by_id);
}
- case op_put_by_id:
- case op_put_by_id_transition_direct:
- case op_put_by_id_transition_normal: {
+ case op_put_by_id: {
NodeIndex value = get(currentInstruction[3].u.operand);
NodeIndex base = get(currentInstruction[1].u.operand);
unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
case op_put_scoped_var:
case op_get_by_id:
case op_put_by_id:
- case op_put_by_id_transition_direct:
- case op_put_by_id_transition_normal:
case op_get_global_var:
case op_put_global_var:
case op_jmp:
uint32_t exitIndex = globalData->osrExitIndex;
OSRExit& exit = codeBlock->osrExit(exitIndex);
- // Make sure all code on our inline stack is JIT compiled. This is necessary since
- // we may opt to inline a code block even before it had ever been compiled by the
- // JIT, but our OSR exit infrastructure currently only works if the target of the
- // OSR exit is JIT code. This could be changed since there is nothing particularly
- // hard about doing an OSR exit into the interpreter, but for now this seems to make
- // sense in that if we're OSR exiting from inlined code of a DFG code block, then
- // probably it's a good sign that the thing we're exiting into is hot. Even more
- // interestingly, since the code was inlined, it may never otherwise get JIT
- // compiled since the act of inlining it may ensure that it otherwise never runs.
- for (CodeOrigin codeOrigin = exit.m_codeOrigin; codeOrigin.inlineCallFrame; codeOrigin = codeOrigin.inlineCallFrame->caller) {
- static_cast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())
- ->baselineCodeBlockFor(codeOrigin.inlineCallFrame->isCall ? CodeForCall : CodeForConstruct)
- ->jitCompile(*globalData);
- }
-
SpeculationRecovery* recovery = 0;
if (exit.m_recoveryIndex)
recovery = &codeBlock->speculationRecovery(exit.m_recoveryIndex - 1);
#include "config.h"
#include "DFGOperations.h"
+#if ENABLE(DFG_JIT)
+
#include "CodeBlock.h"
#include "DFGOSRExit.h"
#include "DFGRepatch.h"
-#include "HostCallReturnValue.h"
#include "GetterSetter.h"
#include "InlineASM.h"
#include "Interpreter.h"
#include "JSGlobalData.h"
#include "Operations.h"
-#if ENABLE(DFG_JIT)
-
#if CPU(X86_64)
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, register) \
return JSValue::strictEqual(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
}
+EncodedJSValue DFG_OPERATION getHostCallReturnValue();
+EncodedJSValue DFG_OPERATION getHostCallReturnValueWithExecState(ExecState*);
+
+#if CPU(X86_64)
+asm (
+".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
+HIDE_SYMBOL(getHostCallReturnValue) "\n"
+SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
+ "mov -40(%r13), %r13\n"
+ "mov %r13, %rdi\n"
+ "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
+);
+#elif CPU(X86)
+asm (
+".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
+HIDE_SYMBOL(getHostCallReturnValue) "\n"
+SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
+ "mov -40(%edi), %edi\n"
+ "mov %edi, 4(%esp)\n"
+ "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
+);
+#elif CPU(ARM_THUMB2)
+asm (
+".text" "\n"
+".align 2" "\n"
+".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
+HIDE_SYMBOL(getHostCallReturnValue) "\n"
+".thumb" "\n"
+".thumb_func " THUMB_FUNC_PARAM(getHostCallReturnValue) "\n"
+SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
+ "ldr r5, [r5, #-40]" "\n"
+ "cpy r0, r5" "\n"
+ "b " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
+);
+#endif
+
+EncodedJSValue DFG_OPERATION getHostCallReturnValueWithExecState(ExecState* exec)
+{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
+ return JSValue::encode(exec->globalData().hostCallReturnValue);
+}
+
static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializationKind kind)
{
ExecState* exec = execCallee->callerFrame();
execCallee->setScopeChain(exec->scopeChain());
execCallee->setCodeBlock(0);
- execCallee->clearReturnPC();
if (kind == CodeForCall) {
CallData callData;
} } // namespace JSC::DFG
#endif
-
-#if COMPILER(GCC)
-
-namespace JSC {
-
-#if CPU(X86_64)
-asm (
-".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
-HIDE_SYMBOL(getHostCallReturnValue) "\n"
-SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
- "mov -40(%r13), %r13\n"
- "mov %r13, %rdi\n"
- "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
-);
-#elif CPU(X86)
-asm (
-".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
-HIDE_SYMBOL(getHostCallReturnValue) "\n"
-SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
- "mov -40(%edi), %edi\n"
- "mov %edi, 4(%esp)\n"
- "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
-);
-#elif CPU(ARM_THUMB2)
-asm (
-".text" "\n"
-".align 2" "\n"
-".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
-HIDE_SYMBOL(getHostCallReturnValue) "\n"
-".thumb" "\n"
-".thumb_func " THUMB_FUNC_PARAM(getHostCallReturnValue) "\n"
-SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
- "ldr r5, [r5, #-40]" "\n"
- "cpy r0, r5" "\n"
- "b " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
-);
-#endif
-
-extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWithExecState(ExecState* exec)
-{
- if (!exec)
- return JSValue::encode(JSValue());
- return JSValue::encode(exec->globalData().hostCallReturnValue);
-}
-
-} // namespace JSC
-
-#endif // COMPILER(GCC)
-
class JSGlobalData;
class JSValue;
class LiveObjectIterator;
- class LLIntOffsetsExtractor;
class MarkedArgumentBuffer;
class RegisterFile;
class UString;
// true if an allocation or collection is in progress
inline bool isBusy();
- MarkedAllocator& firstAllocatorWithoutDestructors() { return m_objectSpace.firstAllocator(); }
MarkedAllocator& allocatorForObjectWithoutDestructor(size_t bytes) { return m_objectSpace.allocatorFor(bytes); }
MarkedAllocator& allocatorForObjectWithDestructor(size_t bytes) { return m_objectSpace.destructorAllocatorFor(bytes); }
CheckedBoolean tryAllocateStorage(size_t, void**);
void getConservativeRegisterRoots(HashSet<JSCell*>& roots);
private:
- friend class CodeBlock;
- friend class LLIntOffsetsExtractor;
friend class MarkedSpace;
friend class MarkedAllocator;
friend class MarkedBlock;
friend class CopiedSpace;
friend class SlotVisitor;
+ friend class CodeBlock;
template<typename T> friend void* allocateCell(Heap&);
void* allocateWithDestructor(size_t);
#endif
ASSERT(Heap::isMarked(cell));
-
+
if (isJSString(cell)) {
JSString::visitChildren(const_cast<JSCell*>(cell), visitor);
return;
class Heap;
class MarkedSpace;
-class LLIntOffsetsExtractor;
namespace DFG {
class SpeculativeJIT;
void init(Heap*, MarkedSpace*, size_t cellSize, bool cellsNeedDestruction);
private:
- friend class LLIntOffsetsExtractor;
-
JS_EXPORT_PRIVATE void* allocateSlowCase();
void* tryAllocate();
void* tryAllocateHelper();
class Heap;
class JSCell;
class LiveObjectIterator;
-class LLIntOffsetsExtractor;
class WeakGCHandle;
class SlotVisitor;
MarkedSpace(Heap*);
- MarkedAllocator& firstAllocator();
MarkedAllocator& allocatorFor(size_t);
MarkedAllocator& allocatorFor(MarkedBlock*);
MarkedAllocator& destructorAllocatorFor(size_t);
void didConsumeFreeList(MarkedBlock*);
private:
- friend class LLIntOffsetsExtractor;
-
// [ 32... 256 ]
static const size_t preciseStep = MarkedBlock::atomSize;
static const size_t preciseCutoff = 256;
return forEachCell(functor);
}
-inline MarkedAllocator& MarkedSpace::firstAllocator()
-{
- return m_normalSpace.preciseAllocators[0];
-}
-
inline MarkedAllocator& MarkedSpace::allocatorFor(size_t bytes)
{
ASSERT(bytes && bytes <= maxCellSize);
#endif
-#if USE(JSVALUE32_64)
-unsigned CallFrame::bytecodeOffsetForNonDFGCode() const
-{
- ASSERT(codeBlock());
- return currentVPC() - codeBlock()->instructions().begin();
-}
-
-void CallFrame::setBytecodeOffsetForNonDFGCode(unsigned offset)
-{
- ASSERT(codeBlock());
- setCurrentVPC(codeBlock()->instructions().begin() + offset);
-}
-#else
-Instruction* CallFrame::currentVPC() const
-{
- return codeBlock()->instructions().begin() + bytecodeOffsetForNonDFGCode();
-}
-void CallFrame::setCurrentVPC(Instruction* vpc)
-{
- setBytecodeOffsetForNonDFGCode(vpc - codeBlock()->instructions().begin());
-}
-#endif
-
#if ENABLE(DFG_JIT)
bool CallFrame::isInlineCallFrameSlow()
{
// more frames above the true caller due to inlining.
// Am I an inline call frame? If so, we're done.
- if (isInlineCallFrame())
+ if (isInlineCallFrame() || !hasReturnPC())
return callerFrame()->removeHostCallFrameFlag();
// I am a machine call frame, so the question is: is my caller a machine call frame
ASSERT(!machineCaller->isInlineCallFrame());
// Figure out how we want to get the current code location.
- if (!hasReturnPC() || returnAddressIsInCtiTrampoline(returnPC()))
+ if (hasHostCallFrameFlag() || returnAddressIsInCtiTrampoline(returnPC()))
return machineCaller->trueCallFrameFromVMCode()->removeHostCallFrameFlag();
return machineCaller->trueCallFrame(returnPC())->removeHostCallFrameFlag();
CallFrame* callerFrame() const { return this[RegisterFile::CallerFrame].callFrame(); }
#if ENABLE(JIT)
+ bool hasReturnPC() const { return this[RegisterFile::ReturnPC].vPC(); }
ReturnAddressPtr returnPC() const { return ReturnAddressPtr(this[RegisterFile::ReturnPC].vPC()); }
- bool hasReturnPC() const { return !!this[RegisterFile::ReturnPC].vPC(); }
- void clearReturnPC() { registers()[RegisterFile::ReturnPC] = static_cast<Instruction*>(0); }
#endif
AbstractPC abstractReturnPC(JSGlobalData& globalData) { return AbstractPC(globalData, this); }
-#if USE(JSVALUE32_64)
- unsigned bytecodeOffsetForNonDFGCode() const;
- void setBytecodeOffsetForNonDFGCode(unsigned offset);
-#else
- unsigned bytecodeOffsetForNonDFGCode() const
+ unsigned bytecodeOffsetForNonDFGCode()
{
ASSERT(codeBlock());
return this[RegisterFile::ArgumentCount].tag();
ASSERT(codeBlock());
this[RegisterFile::ArgumentCount].tag() = static_cast<int32_t>(offset);
}
-#endif
#if ENABLE(DFG_JIT)
InlineCallFrame* inlineCallFrame() const { return this[RegisterFile::ReturnPC].asInlineCallFrame(); }
#if ENABLE(CLASSIC_INTERPRETER)
Instruction* returnVPC() const { return this[RegisterFile::ReturnPC].vPC(); }
#endif
-#if USE(JSVALUE32_64)
- Instruction* currentVPC() const
- {
- return bitwise_cast<Instruction*>(this[RegisterFile::ArgumentCount].tag());
- }
- void setCurrentVPC(Instruction* vpc)
- {
- this[RegisterFile::ArgumentCount].tag() = bitwise_cast<int32_t>(vpc);
- }
-#else
- Instruction* currentVPC() const;
- void setCurrentVPC(Instruction* vpc);
-#endif
void setCallerFrame(CallFrame* callerFrame) { static_cast<Register*>(this)[RegisterFile::CallerFrame] = callerFrame; }
void setScopeChain(ScopeChainNode* scopeChain) { static_cast<Register*>(this)[RegisterFile::ScopeChain] = scopeChain; }
#include "JIT.h"
#endif
-#define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND ((ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)) && !defined(__llvm__))
+#define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND (ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) && !defined(__llvm__))
using namespace std;
#if !ASSERT_DISABLED
, m_initialized(false)
#endif
- , m_classicEnabled(false)
+ , m_enabled(false)
{
}
-Interpreter::~Interpreter()
+void Interpreter::initialize(bool canUseJIT)
{
-#if ENABLE(LLINT)
- if (m_classicEnabled)
- delete[] m_opcodeTable;
-#endif
-}
-
-void Interpreter::initialize(LLInt::Data* llintData, bool canUseJIT)
-{
- UNUSED_PARAM(llintData);
- UNUSED_PARAM(canUseJIT);
-#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)
-#if !ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
- // Having LLInt enabled, but not being able to use the JIT, and not having
- // a computed goto interpreter, is not supported. Not because we cannot
- // support it, but because I decided to draw the line at the number of
- // permutations of execution engines that I wanted this code to grok.
- ASSERT(canUseJIT);
-#endif
+#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
if (canUseJIT) {
-#if ENABLE(LLINT)
- m_opcodeTable = llintData->opcodeMap();
- for (int i = 0; i < numOpcodeIDs; ++i)
- m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
-#else
// If the JIT is present, don't use jump destinations for opcodes.
for (int i = 0; i < numOpcodeIDs; ++i) {
Opcode opcode = bitwise_cast<void*>(static_cast<uintptr_t>(i));
m_opcodeTable[i] = opcode;
}
-#endif
} else {
-#if ENABLE(LLINT)
- m_opcodeTable = new Opcode[numOpcodeIDs];
-#endif
privateExecute(InitializeAndReturn, 0, 0);
for (int i = 0; i < numOpcodeIDs; ++i)
m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
- m_classicEnabled = true;
+ m_enabled = true;
}
#else
+ UNUSED_PARAM(canUseJIT);
#if ENABLE(CLASSIC_INTERPRETER)
- m_classicEnabled = true;
+ m_enabled = true;
#else
- m_classicEnabled = false;
+ m_enabled = false;
#endif
#endif // ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
#if !ASSERT_DISABLED
bool Interpreter::isOpcode(Opcode opcode)
{
-#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)
-#if !ENABLE(LLINT)
- if (!m_classicEnabled)
+#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
+ if (!m_enabled)
return opcode >= 0 && static_cast<OpcodeID>(bitwise_cast<uintptr_t>(opcode)) <= op_end;
-#endif
return opcode != HashTraits<Opcode>::emptyValue()
&& !HashTraits<Opcode>::isDeletedValue(opcode)
&& m_opcodeIDTable.contains(opcode);
// have to subtract 1.
#if ENABLE(JIT) && ENABLE(CLASSIC_INTERPRETER)
if (callerFrame->globalData().canUseJIT())
- bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
+ bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnPC());
else
bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1;
#elif ENABLE(JIT)
- bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
+ bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnPC());
#else
bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1;
#endif
}
} else
#endif
- bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
+ bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
#endif
}
}
ASSERT(m_initialized);
- ASSERT(m_classicEnabled);
+ ASSERT(m_enabled);
#if ENABLE(JIT)
#if ENABLE(CLASSIC_INTERPRETER)
#if USE(GCC_COMPUTED_GOTO_WORKAROUND)
skip_put_by_id:
#endif
- DEFINE_OPCODE(op_put_by_id_transition_direct)
- DEFINE_OPCODE(op_put_by_id_transition_normal)
DEFINE_OPCODE(op_put_by_id_transition) {
/* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n) direct(b)
bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnVPC());
#if ENABLE(JIT)
else
- bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
+ bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
#endif
#else
- bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
+ bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
#endif
lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
sourceID = callerCodeBlock->ownerExecutable()->sourceID();
#include "JSFunction.h"
#include "JSValue.h"
#include "JSObject.h"
-#include "LLIntData.h"
#include "Opcode.h"
#include "RegisterFile.h"
class ExecutableBase;
class FunctionExecutable;
class JSGlobalObject;
- class LLIntOffsetsExtractor;
class ProgramExecutable;
class Register;
class ScopeChainNode;
class Interpreter {
WTF_MAKE_FAST_ALLOCATED;
- friend class CachedCall;
- friend class LLIntOffsetsExtractor;
friend class JIT;
+ friend class CachedCall;
public:
Interpreter();
- ~Interpreter();
- void initialize(LLInt::Data*, bool canUseJIT);
+ void initialize(bool canUseJIT);
RegisterFile& registerFile() { return m_registerFile; }
Opcode getOpcode(OpcodeID id)
{
ASSERT(m_initialized);
-#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)
+#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
return m_opcodeTable[id];
#else
return id;
OpcodeID getOpcodeID(Opcode opcode)
{
ASSERT(m_initialized);
-#if ENABLE(LLINT)
- ASSERT(isOpcode(opcode));
- return m_opcodeIDTable.get(opcode);
-#elif ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
+#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
ASSERT(isOpcode(opcode));
- if (!m_classicEnabled)
+ if (!m_enabled)
return static_cast<OpcodeID>(bitwise_cast<uintptr_t>(opcode));
return m_opcodeIDTable.get(opcode);
return opcode;
#endif
}
-
- bool classicEnabled()
- {
- return m_classicEnabled;
- }
bool isOpcode(Opcode);
RegisterFile m_registerFile;
-#if ENABLE(LLINT)
- Opcode* m_opcodeTable; // Maps OpcodeID => Opcode for compiling
- HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
-#elif ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
+#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
Opcode m_opcodeTable[numOpcodeIDs]; // Maps OpcodeID => Opcode for compiling
HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
#endif
#if !ASSERT_DISABLED
bool m_initialized;
#endif
- bool m_classicEnabled;
+ bool m_enabled;
};
// This value must not be an object that would require this conversion (WebCore's global object).
class ConservativeRoots;
class DFGCodeBlocks;
- class LLIntOffsetsExtractor;
class RegisterFile {
WTF_MAKE_NONCOPYABLE(RegisterFile);
}
private:
- friend class LLIntOffsetsExtractor;
-
bool growSlowCase(Register*);
void releaseExcessCapacity();
void addToCommittedByteCount(long);
}
+#if ENABLE(JIT) && ENABLE(ASSEMBLER)
+
namespace JSC {
typedef WTF::MetaAllocatorHandle ExecutableMemoryHandle;
-#if ENABLE(JIT) && ENABLE(ASSEMBLER)
-
class ExecutableAllocator {
enum ProtectionSetting { Writable, Executable };
#endif
};
-#endif // ENABLE(JIT) && ENABLE(ASSEMBLER)
-
} // namespace JSC
+#endif // ENABLE(JIT) && ENABLE(ASSEMBLER)
+
#endif // !defined(ExecutableAllocator)
+++ /dev/null
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "HostCallReturnValue.h"
-
-#include "CallFrame.h"
-#include "InlineASM.h"
-#include "JSObject.h"
-#include "JSValueInlineMethods.h"
-#include "ScopeChain.h"
-
-namespace JSC {
-
-// Nothing to see here.
-
-} // namespace JSC
-
+++ /dev/null
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef HostCallReturnValue_h
-#define HostCallReturnValue_h
-
-#include "JSValue.h"
-#include "MacroAssemblerCodeRef.h"
-#include <wtf/Platform.h>
-
-// Unfortunately this only works on GCC-like compilers. And it's currently only used
-// by LLInt and DFG, which also are restricted to GCC-like compilers. We should
-// probably fix that at some point.
-#if COMPILER(GCC)
-
-#if CALLING_CONVENTION_IS_STDCALL
-#define HOST_CALL_RETURN_VALUE_OPTION CDECL
-#else
-#define HOST_CALL_RETURN_VALUE_OPTION
-#endif
-
-namespace JSC {
-
-extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValue();
-
-// This is a public declaration only to convince CLANG not to elide it.
-extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWithExecState(ExecState*);
-
-inline void initializeHostCallReturnValue()
-{
- getHostCallReturnValueWithExecState(0);
-}
-
-}
-
-#else // COMPILER(GCC)
-
-namespace JSC {
-inline void initializeHostCallReturnValue() { }
-}
-
-#endif // COMPILER(GCC)
-
-#endif // HostCallReturnValue_h
-
DEFINE_OP(op_profile_will_call)
DEFINE_OP(op_push_new_scope)
DEFINE_OP(op_push_scope)
- case op_put_by_id_transition_direct:
- case op_put_by_id_transition_normal:
DEFINE_OP(op_put_by_id)
DEFINE_OP(op_put_by_index)
DEFINE_OP(op_put_by_val)
DEFINE_SLOWCASE_OP(op_post_inc)
DEFINE_SLOWCASE_OP(op_pre_dec)
DEFINE_SLOWCASE_OP(op_pre_inc)
- case op_put_by_id_transition_direct:
- case op_put_by_id_transition_normal:
DEFINE_SLOWCASE_OP(op_put_by_id)
DEFINE_SLOWCASE_OP(op_put_by_val)
DEFINE_SLOWCASE_OP(op_resolve_global)
JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck)
{
-#if ENABLE(JIT_VERBOSE_OSR)
- printf("Compiling JIT code!\n");
-#endif
-
#if ENABLE(VALUE_PROFILER)
m_canBeOptimized = m_codeBlock->canCompileWithDFG();
#endif
info.callReturnLocation = m_codeBlock->structureStubInfo(m_methodCallCompilationInfo[i].propertyAccessIndex).callReturnLocation;
}
-#if ENABLE(DFG_JIT) || ENABLE(LLINT)
- if (m_canBeOptimized
-#if ENABLE(LLINT)
- || true
-#endif
- ) {
+#if ENABLE(DFG_JIT)
+ if (m_canBeOptimized) {
CompactJITCodeMap::Encoder jitCodeMapEncoder;
for (unsigned bytecodeOffset = 0; bytecodeOffset < m_labels.size(); ++bytecodeOffset) {
if (m_labels[bytecodeOffset].isSet())
JITCode() { }
#endif
public:
- enum JITType { None, HostCallThunk, InterpreterThunk, BaselineJIT, DFGJIT };
+ enum JITType { HostCallThunk, BaselineJIT, DFGJIT };
static JITType bottomTierJIT()
{
return DFGJIT;
}
- static bool isOptimizingJIT(JITType jitType)
- {
- return jitType == DFGJIT;
- }
-
- static bool isBaselineCode(JITType jitType)
- {
- return jitType == InterpreterThunk || jitType == BaselineJIT;
- }
-
#if ENABLE(JIT)
JITCode()
- : m_jitType(None)
{
}
: m_ref(ref)
, m_jitType(jitType)
{
- ASSERT(jitType != None);
}
bool operator !() const
#include "BytecodeGenerator.h"
#include "DFGDriver.h"
#include "JIT.h"
-#include "LLIntEntrypoints.h"
namespace JSC {
template<typename CodeBlockType>
inline bool jitCompileIfAppropriate(JSGlobalData& globalData, OwnPtr<CodeBlockType>& codeBlock, JITCode& jitCode, JITCode::JITType jitType)
{
- if (jitType == codeBlock->getJITType())
- return true;
-
if (!globalData.canUseJIT())
return true;
- codeBlock->unlinkIncomingCalls();
-
bool dfgCompiled = false;
if (jitType == JITCode::DFGJIT)
dfgCompiled = DFG::tryCompile(globalData, codeBlock.get(), jitCode);
inline bool jitCompileFunctionIfAppropriate(JSGlobalData& globalData, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType)
{
- if (jitType == codeBlock->getJITType())
- return true;
-
if (!globalData.canUseJIT())
return true;
- codeBlock->unlinkIncomingCalls();
-
bool dfgCompiled = false;
if (jitType == JITCode::DFGJIT)
dfgCompiled = DFG::tryCompileFunction(globalData, codeBlock.get(), jitCode, jitCodeWithArityCheck);
}
jitCode = JIT::compile(&globalData, codeBlock.get(), &jitCodeWithArityCheck);
}
+
codeBlock->setJITCode(jitCode, jitCodeWithArityCheck);
return true;
ExceptionHandler jitThrow(JSGlobalData* globalData, ExecState* callFrame, JSValue exceptionValue, ReturnAddressPtr faultLocation)
{
- return genericThrow(globalData, callFrame, exceptionValue, callFrame->codeBlock()->bytecodeOffset(callFrame, faultLocation));
+ return genericThrow(globalData, callFrame, exceptionValue, callFrame->codeBlock()->bytecodeOffset(faultLocation));
}
}
ALWAYS_INLINE void JIT::updateTopCallFrame()
{
ASSERT(static_cast<int>(m_bytecodeOffset) >= 0);
- if (m_bytecodeOffset) {
-#if USE(JSVALUE32_64)
- storePtr(TrustedImmPtr(m_codeBlock->instructions().begin() + m_bytecodeOffset + 1), intTagFor(RegisterFile::ArgumentCount));
-#else
+ if (m_bytecodeOffset)
store32(Imm32(m_bytecodeOffset + 1), intTagFor(RegisterFile::ArgumentCount));
-#endif
- }
storePtr(callFrameRegister, &m_globalData->topCallFrame);
}
PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
JSValue baseValue = stackFrame.args[0].jsValue();
ASSERT(baseValue.isObject());
-
asObject(baseValue)->putDirect(callFrame->globalData(), ident, stackFrame.args[2].jsValue(), slot);
CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
unsigned bytecodeIndex = stackFrame.args[0].int32();
#if ENABLE(JIT_VERBOSE_OSR)
- dataLog("%p: Entered optimize_from_loop with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock, codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
+ dataLog("Entered optimize_from_loop with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
#endif
if (codeBlock->hasOptimizedReplacement()) {
return result;
}
+inline CallFrame* arityCheckFor(CallFrame* callFrame, RegisterFile* registerFile, CodeSpecializationKind kind)
+{
+ JSFunction* callee = asFunction(callFrame->callee());
+ ASSERT(!callee->isHostFunction());
+ CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecodeFor(kind);
+ int argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
+
+ // This ensures enough space for the worst case scenario of zero arguments passed by the caller.
+ if (!registerFile->grow(callFrame->registers() + newCodeBlock->numParameters() + newCodeBlock->m_numCalleeRegisters))
+ return 0;
+
+ ASSERT(argumentCountIncludingThis < newCodeBlock->numParameters());
+
+ // Too few arguments -- copy call frame and arguments, then fill in missing arguments with undefined.
+ size_t delta = newCodeBlock->numParameters() - argumentCountIncludingThis;
+ Register* src = callFrame->registers();
+ Register* dst = callFrame->registers() + delta;
+
+ int i;
+ int end = -CallFrame::offsetFor(argumentCountIncludingThis);
+ for (i = -1; i >= end; --i)
+ dst[i] = src[i];
+
+ end -= delta;
+ for ( ; i >= end; --i)
+ dst[i] = jsUndefined();
+
+ CallFrame* newCallFrame = CallFrame::create(dst);
+ ASSERT((void*)newCallFrame <= registerFile->end());
+ return newCallFrame;
+}
+
DEFINE_STUB_FUNCTION(void*, op_call_arityCheck)
{
STUB_INIT_STACK_FRAME(stackFrame);
CallFrame* callFrame = stackFrame.callFrame;
- CallFrame* newCallFrame = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.registerFile, CodeForCall);
+ CallFrame* newCallFrame = arityCheckFor(callFrame, stackFrame.registerFile, CodeForCall);
if (!newCallFrame)
return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createStackOverflowError(callFrame->callerFrame()));
CallFrame* callFrame = stackFrame.callFrame;
- CallFrame* newCallFrame = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.registerFile, CodeForConstruct);
+ CallFrame* newCallFrame = arityCheckFor(callFrame, stackFrame.registerFile, CodeForConstruct);
if (!newCallFrame)
return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createStackOverflowError(callFrame->callerFrame()));
STUB_INIT_STACK_FRAME(stackFrame);
CallFrame* callFrame = stackFrame.callFrame;
-
JSValue callee = callFrame->calleeAsValue();
CallData callData;
#include "ThunkGenerators.h"
#include <wtf/HashMap.h>
+#if ENABLE(JIT)
+
namespace JSC {
struct StructureStubInfo;
#define JITSTACKFRAME_ARGS_INDEX (OBJECT_OFFSETOF(JITStackFrame, args) / sizeof(void*))
-#if ENABLE(JIT)
-
#define STUB_ARGS_DECLARATION void** args
#define STUB_ARGS (args)
void* JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION);
} // extern "C"
-#endif // ENABLE(JIT)
-
} // namespace JSC
+#endif // ENABLE(JIT)
+
#endif // JITStubs_h
#ifndef JSInterfaceJIT_h
#define JSInterfaceJIT_h
-#include "BytecodeConventions.h"
#include "JITCode.h"
#include "JITStubs.h"
-#include "JSString.h"
#include "JSValue.h"
#include "MacroAssembler.h"
#include "RegisterFile.h"
+++ /dev/null
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef LLIntCommon_h
-#define LLIntCommon_h
-
-// Print every instruction executed.
-#define LLINT_EXECUTION_TRACING 0
-
-// Print some information for some of the more subtle slow paths.
-#define LLINT_SLOW_PATH_TRACING 0
-
-// Disable inline allocation in the interpreter. This is great if you're changing
-// how the GC allocates.
-#define LLINT_ALWAYS_ALLOCATE_SLOW 0
-
-// Enable OSR into the JIT. Disabling this while the LLInt is enabled effectively
-// turns off all JIT'ing, since in LLInt's parlance, OSR subsumes any form of JIT
-// invocation.
-#if ENABLE(JIT)
-#define LLINT_OSR_TO_JIT 1
-#else
-#define LLINT_OSR_TO_JIT 0
-#endif
-
-#endif // LLIntCommon_h
-
+++ /dev/null
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "LLIntData.h"
-
-#if ENABLE(LLINT)
-
-#include "BytecodeConventions.h"
-#include "CodeType.h"
-#include "Instruction.h"
-#include "LowLevelInterpreter.h"
-#include "Opcode.h"
-
-namespace JSC { namespace LLInt {
-
-Data::Data()
- : m_exceptionInstructions(new Instruction[maxOpcodeLength + 1])
- , m_opcodeMap(new Opcode[numOpcodeIDs])
-{
- for (int i = 0; i < maxOpcodeLength + 1; ++i)
- m_exceptionInstructions[i].u.pointer = bitwise_cast<void*>(&llint_throw_from_slow_path_trampoline);
-#define OPCODE_ENTRY(opcode, length) m_opcodeMap[opcode] = bitwise_cast<void*>(&llint_##opcode);
- FOR_EACH_OPCODE_ID(OPCODE_ENTRY);
-#undef OPCODE_ENTRY
-}
-
-#if COMPILER(CLANG)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wmissing-noreturn"
-#endif
-void Data::performAssertions(JSGlobalData& globalData)
-{
- UNUSED_PARAM(globalData);
-
- // Assertions to match LowLevelInterpreter.asm. If you change any of this code, be
- // prepared to change LowLevelInterpreter.asm as well!!
- ASSERT(RegisterFile::CallFrameHeaderSize * 8 == 48);
- ASSERT(RegisterFile::ArgumentCount * 8 == -48);
- ASSERT(RegisterFile::CallerFrame * 8 == -40);
- ASSERT(RegisterFile::Callee * 8 == -32);
- ASSERT(RegisterFile::ScopeChain * 8 == -24);
- ASSERT(RegisterFile::ReturnPC * 8 == -16);
- ASSERT(RegisterFile::CodeBlock * 8 == -8);
- ASSERT(CallFrame::argumentOffsetIncludingThis(0) == -RegisterFile::CallFrameHeaderSize - 1);
-#if CPU(BIG_ENDIAN)
- ASSERT(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag) == 0);
- ASSERT(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload) == 4);
-#else
- ASSERT(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag) == 4);
- ASSERT(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload) == 0);
-#endif
- ASSERT(JSValue::Int32Tag == -1);
- ASSERT(JSValue::BooleanTag == -2);
- ASSERT(JSValue::NullTag == -3);
- ASSERT(JSValue::UndefinedTag == -4);
- ASSERT(JSValue::CellTag == -5);
- ASSERT(JSValue::EmptyValueTag == -6);
- ASSERT(JSValue::DeletedValueTag == -7);
- ASSERT(JSValue::LowestTag == -7);
- ASSERT(StringType == 5);
- ASSERT(ObjectType == 13);
- ASSERT(MasqueradesAsUndefined == 1);
- ASSERT(ImplementsHasInstance == 2);
- ASSERT(ImplementsDefaultHasInstance == 8);
- ASSERT(&globalData.heap.allocatorForObjectWithoutDestructor(sizeof(JSFinalObject)) - &globalData.heap.firstAllocatorWithoutDestructors() == 3);
- ASSERT(FirstConstantRegisterIndex == 0x40000000);
- ASSERT(GlobalCode == 0);
- ASSERT(EvalCode == 1);
- ASSERT(FunctionCode == 2);
-
- // FIXME: make these assertions less horrible.
-#if !ASSERT_DISABLED
- Vector<int> testVector;
- testVector.resize(42);
- ASSERT(bitwise_cast<size_t*>(&testVector)[0] == 42);
- ASSERT(bitwise_cast<int**>(&testVector)[1] == testVector.begin());
-#endif
-
- ASSERT(StringImpl::s_hashFlag8BitBuffer == 64);
-}
-#if COMPILER(CLANG)
-#pragma clang diagnostic pop
-#endif
-
-Data::~Data()
-{
- delete[] m_exceptionInstructions;
- delete[] m_opcodeMap;
-}
-
-} } // namespace JSC::LLInt
-
-#endif // ENABLE(LLINT)
+++ /dev/null
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef LLIntData_h
-#define LLIntData_h
-
-#include "Opcode.h"
-#include <wtf/Platform.h>
-
-namespace JSC {
-
-class JSGlobalData;
-struct Instruction;
-
-namespace LLInt {
-
-#if ENABLE(LLINT)
-class Data {
-public:
- Data();
- ~Data();
-
- void performAssertions(JSGlobalData&);
-
- Instruction* exceptionInstructions()
- {
- return m_exceptionInstructions;
- }
-
- Opcode* opcodeMap()
- {
- return m_opcodeMap;
- }
-private:
- Instruction* m_exceptionInstructions;
- Opcode* m_opcodeMap;
-};
-#else // ENABLE(LLINT)
-
-#if COMPILER(CLANG)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wmissing-noreturn"
-#endif
-
-class Data {
-public:
- void performAssertions(JSGlobalData&) { }
-
- Instruction* exceptionInstructions()
- {
- ASSERT_NOT_REACHED();
- return 0;
- }
-
- Opcode* opcodeMap()
- {
- ASSERT_NOT_REACHED();
- return 0;
- }
-};
-
-#if COMPILER(CLANG)
-#pragma clang diagnostic pop
-#endif
-
-#endif // ENABLE(LLINT)
-
-} } // namespace JSC::LLInt
-
-#endif // LLIntData_h
-
+++ /dev/null
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "LLIntEntrypoints.h"
-
-#if ENABLE(LLINT)
-
-#include "JITCode.h"
-#include "JSGlobalData.h"
-#include "LLIntThunks.h"
-#include "LowLevelInterpreter.h"
-
-namespace JSC { namespace LLInt {
-
-void getFunctionEntrypoint(JSGlobalData& globalData, CodeSpecializationKind kind, JITCode& jitCode, MacroAssemblerCodePtr& arityCheck)
-{
- if (!globalData.canUseJIT()) {
- if (kind == CodeForCall) {
- jitCode = JITCode::HostFunction(MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_function_for_call_prologue))));
- arityCheck = MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_function_for_call_arity_check));
- return;
- }
-
- ASSERT(kind == CodeForConstruct);
- jitCode = JITCode::HostFunction(MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_function_for_construct_prologue))));
- arityCheck = MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_function_for_construct_arity_check));
- return;
- }
-
- if (kind == CodeForCall) {
- jitCode = JITCode(globalData.getCTIStub(functionForCallEntryThunkGenerator), JITCode::InterpreterThunk);
- arityCheck = globalData.getCTIStub(functionForCallArityCheckThunkGenerator).code();
- return;
- }
-
- ASSERT(kind == CodeForConstruct);
- jitCode = JITCode(globalData.getCTIStub(functionForConstructEntryThunkGenerator), JITCode::InterpreterThunk);
- arityCheck = globalData.getCTIStub(functionForConstructArityCheckThunkGenerator).code();
-}
-
-void getEvalEntrypoint(JSGlobalData& globalData, JITCode& jitCode)
-{
- if (!globalData.canUseJIT()) {
- jitCode = JITCode::HostFunction(MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_eval_prologue))));
- return;
- }
-
- jitCode = JITCode(globalData.getCTIStub(evalEntryThunkGenerator), JITCode::InterpreterThunk);
-}
-
-void getProgramEntrypoint(JSGlobalData& globalData, JITCode& jitCode)
-{
- if (!globalData.canUseJIT()) {
- jitCode = JITCode::HostFunction(MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_program_prologue))));
- return;
- }
-
- jitCode = JITCode(globalData.getCTIStub(programEntryThunkGenerator), JITCode::InterpreterThunk);
-}
-
-} } // namespace JSC::LLInt
-
-#endif // ENABLE(LLINT)
+++ /dev/null
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef LLIntEntrypoints_h
-#define LLIntEntrypoints_h
-
-#include <wtf/Platform.h>
-
-#if ENABLE(LLINT)
-
-#include "CodeSpecializationKind.h"
-
-namespace JSC {
-
-class EvalCodeBlock;
-class JITCode;
-class JSGlobalData;
-class MacroAssemblerCodePtr;
-class MacroAssemblerCodeRef;
-class ProgramCodeBlock;
-
-namespace LLInt {
-
-void getFunctionEntrypoint(JSGlobalData&, CodeSpecializationKind, JITCode&, MacroAssemblerCodePtr& arityCheck);
-void getEvalEntrypoint(JSGlobalData&, JITCode&);
-void getProgramEntrypoint(JSGlobalData&, JITCode&);
-
-inline void getEntrypoint(JSGlobalData& globalData, EvalCodeBlock*, JITCode& jitCode)
-{
- getEvalEntrypoint(globalData, jitCode);
-}
-
-inline void getEntrypoint(JSGlobalData& globalData, ProgramCodeBlock*, JITCode& jitCode)
-{
- getProgramEntrypoint(globalData, jitCode);
-}
-
-} } // namespace JSC::LLInt
-
-#endif // ENABLE(LLINT)
-
-#endif // LLIntEntrypoints_h
+++ /dev/null
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "LLIntExceptions.h"
-
-#if ENABLE(LLINT)
-
-#include "CallFrame.h"
-#include "CodeBlock.h"
-#include "Instruction.h"
-#include "JITExceptions.h"
-#include "LLIntCommon.h"
-#include "LowLevelInterpreter.h"
-
-namespace JSC { namespace LLInt {
-
-void interpreterThrowInCaller(ExecState* exec, ReturnAddressPtr pc)
-{
- JSGlobalData* globalData = &exec->globalData();
-#if LLINT_SLOW_PATH_TRACING
- dataLog("Throwing exception %s.\n", globalData->exception.description());
-#endif
- genericThrow(
- globalData, exec, globalData->exception,
- exec->codeBlock()->bytecodeOffset(exec, pc));
-}
-
-Instruction* returnToThrowForThrownException(ExecState* exec)
-{
- return exec->globalData().llintData.exceptionInstructions();
-}
-
-Instruction* returnToThrow(ExecState* exec, Instruction* pc)
-{
- JSGlobalData* globalData = &exec->globalData();
-#if LLINT_SLOW_PATH_TRACING
- dataLog("Throwing exception %s (returnToThrow).\n", globalData->exception.description());
-#endif
- genericThrow(globalData, exec, globalData->exception, pc - exec->codeBlock()->instructions().begin());
-
- return globalData->llintData.exceptionInstructions();
-}
-
-void* callToThrow(ExecState* exec, Instruction* pc)
-{
- JSGlobalData* globalData = &exec->globalData();
-#if LLINT_SLOW_PATH_TRACING
- dataLog("Throwing exception %s (callToThrow).\n", globalData->exception.description());
-#endif
- genericThrow(globalData, exec, globalData->exception, pc - exec->codeBlock()->instructions().begin());
-
- return bitwise_cast<void*>(&llint_throw_during_call_trampoline);
-}
-
-} } // namespace JSC::LLInt
-
-#endif // ENABLE(LLINT)
+++ /dev/null
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef LLIntExceptions_h
-#define LLIntExceptions_h
-
-#include <wtf/Platform.h>
-#include <wtf/StdLibExtras.h>
-
-#if ENABLE(LLINT)
-
-#include "MacroAssemblerCodeRef.h"
-
-namespace JSC {
-
-class ExecState;
-struct Instruction;
-
-namespace LLInt {
-
-// Throw the currently active exception in the context of the caller's call frame.
-void interpreterThrowInCaller(ExecState* callerFrame, ReturnAddressPtr);
-
-// Tells you where to jump to if you want to return-to-throw, after you've already
-// set up all information needed to throw the exception.
-Instruction* returnToThrowForThrownException(ExecState*);
-
-// Saves the current PC in the global data for safe-keeping, and gives you a PC
-// that you can tell the interpreter to go to, which when advanced between 1
-// and 9 slots will give you an "instruction" that threads to the interpreter's
-// exception handler. Note that if you give it the PC for exception handling,
-// it's smart enough to just return that PC without doing anything else; this
-// lets you thread exception handling through common helper functions used by
-// other helpers.
-Instruction* returnToThrow(ExecState*, Instruction*);
-
-// Use this when you're throwing to a call thunk.
-void* callToThrow(ExecState*, Instruction*);
-
-} } // namespace JSC::LLInt
-
-#endif // ENABLE(LLINT)
-
-#endif // LLIntExceptions_h
+++ /dev/null
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef LLIntOfflineAsmConfig_h
-#define LLIntOfflineAsmConfig_h
-
-#include "LLIntCommon.h"
-#include <wtf/Assertions.h>
-#include <wtf/InlineAsm.h>
-#include <wtf/Platform.h>
-
-#if CPU(X86)
-#define OFFLINE_ASM_X86 1
-#else
-#define OFFLINE_ASM_X86 0
-#endif
-
-#if CPU(ARM_THUMB2)
-#define OFFLINE_ASM_ARMv7 1
-#else
-#define OFFLINE_ASM_ARMv7 0
-#endif
-
-#if !ASSERT_DISABLED
-#define OFFLINE_ASM_ASSERT_ENABLED 1
-#else
-#define OFFLINE_ASM_ASSERT_ENABLED 0
-#endif
-
-#if CPU(BIG_ENDIAN)
-#define OFFLINE_ASM_BIG_ENDIAN 1
-#else
-#define OFFLINE_ASM_BIG_ENDIAN 0
-#endif
-
-#if LLINT_OSR_TO_JIT
-#define OFFLINE_ASM_JIT_ENABLED 1
-#else
-#define OFFLINE_ASM_JIT_ENABLED 0
-#endif
-
-#if LLINT_EXECUTION_TRACING
-#define OFFLINE_ASM_EXECUTION_TRACING 1
-#else
-#define OFFLINE_ASM_EXECUTION_TRACING 0
-#endif
-
-#if LLINT_ALWAYS_ALLOCATE_SLOW
-#define OFFLINE_ASM_ALWAYS_ALLOCATE_SLOW 1
-#else
-#define OFFLINE_ASM_ALWAYS_ALLOCATE_SLOW 0
-#endif
-
-#if CPU(ARM_THUMB2)
-#define OFFLINE_ASM_GLOBAL_LABEL(label) \
- ".globl " SYMBOL_STRING(label) "\n" \
- HIDE_SYMBOL(name) "\n" \
- ".thumb\n" \
- ".thumb_func " THUMB_FUNC_PARAM(label) "\n" \
- SYMBOL_STRING(label) ":\n"
-#else
-#define OFFLINE_ASM_GLOBAL_LABEL(label) \
- ".globl " SYMBOL_STRING(label) "\n" \
- HIDE_SYMBOL(name) "\n" \
- SYMBOL_STRING(label) ":\n"
-#endif
-
-#endif // LLIntOfflineAsmConfig_h
+++ /dev/null
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include "CodeBlock.h"
-#include "Executable.h"
-#include "Heap.h"
-#include "Interpreter.h"
-#include "JITStubs.h"
-#include "JSArray.h"
-#include "JSCell.h"
-#include "JSFunction.h"
-#include "JSGlobalData.h"
-#include "JSGlobalObject.h"
-#include "JSObject.h"
-#include "JSPropertyNameIterator.h"
-#include "JSString.h"
-#include "JSTypeInfo.h"
-#include "JSVariableObject.h"
-#include "JumpTable.h"
-#include "LLIntOfflineAsmConfig.h"
-#include "MarkedSpace.h"
-#include "RegisterFile.h"
-#include "ScopeChain.h"
-#include "Structure.h"
-#include "StructureChain.h"
-#include "ValueProfile.h"
-#include <wtf/text/StringImpl.h>
-
-namespace JSC {
-
-#define OFFLINE_ASM_OFFSETOF(clazz, field) OBJECT_OFFSETOF(clazz, field)
-
-class LLIntOffsetsExtractor {
-public:
- static const unsigned* dummy();
-};
-
-const unsigned* LLIntOffsetsExtractor::dummy()
-{
-// This is a file generated by offlineasm/generate_offsets_extractor.rb, and contains code
-// to create a table of offsets, sizes, and a header identifying what combination of
-// Platform.h macros we have set. We include it inside of a method on LLIntOffsetsExtractor
-// because the fields whose offsets we're extracting are mostly private. So we make their
-// classes friends with LLIntOffsetsExtractor, and include the header here, to get the C++
-// compiler to kindly step aside and yield to our best intentions.
-#include "LLIntDesiredOffsets.h"
- return extractorTable;
-}
-
-} // namespace JSC
-
-int main(int, char**)
-{
- // Out of an abundance of caution, make sure that LLIntOffsetsExtractor::dummy() is live,
- // and the extractorTable is live, too.
- printf("%p\n", JSC::LLIntOffsetsExtractor::dummy());
- return 0;
-}
+++ /dev/null
-/*
- * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "LLIntSlowPaths.h"
-
-#if ENABLE(LLINT)
-
-#include "Arguments.h"
-#include "CallFrame.h"
-#include "CommonSlowPaths.h"
-#include "GetterSetter.h"
-#include "HostCallReturnValue.h"
-#include "Interpreter.h"
-#include "JIT.h"
-#include "JITDriver.h"
-#include "JSActivation.h"
-#include "JSByteArray.h"
-#include "JSGlobalObjectFunctions.h"
-#include "JSPropertyNameIterator.h"
-#include "JSStaticScopeObject.h"
-#include "JSString.h"
-#include "JSValue.h"
-#include "LLIntCommon.h"
-#include "LLIntExceptions.h"
-#include "LowLevelInterpreter.h"
-#include "Operations.h"
-
-namespace JSC { namespace LLInt {
-
-#define LLINT_BEGIN_NO_SET_PC() \
- JSGlobalData& globalData = exec->globalData(); \
- NativeCallFrameTracer tracer(&globalData, exec)
-
-#define LLINT_SET_PC_FOR_STUBS() \
- exec->setCurrentVPC(pc + 1)
-
-#define LLINT_BEGIN() \
- LLINT_BEGIN_NO_SET_PC(); \
- LLINT_SET_PC_FOR_STUBS()
-
-#define LLINT_OP(index) (exec->uncheckedR(pc[index].u.operand))
-#define LLINT_OP_C(index) (exec->r(pc[index].u.operand))
-
-#define LLINT_RETURN_TWO(first, second) do { \
- union { \
- struct { \
- void* a; \
- void* b; \
- } pair; \
- int64_t i; \
- } __rt_u; \
- __rt_u.pair.a = first; \
- __rt_u.pair.b = second; \
- return __rt_u.i; \
- } while (false)
-
-#define LLINT_END_IMPL() LLINT_RETURN_TWO(pc, exec)
-
-#define LLINT_THROW(exceptionToThrow) do { \
- globalData.exception = (exceptionToThrow); \
- pc = returnToThrow(exec, pc); \
- LLINT_END_IMPL(); \
- } while (false)
-
-#define LLINT_CHECK_EXCEPTION() do { \
- if (UNLIKELY(globalData.exception)) { \
- pc = returnToThrow(exec, pc); \
- LLINT_END_IMPL(); \
- } \
- } while (false)
-
-#define LLINT_END() do { \
- LLINT_CHECK_EXCEPTION(); \
- LLINT_END_IMPL(); \
- } while (false)
-
-#define LLINT_BRANCH(opcode, condition) do { \
- bool __b_condition = (condition); \
- LLINT_CHECK_EXCEPTION(); \
- if (__b_condition) \
- pc += pc[OPCODE_LENGTH(opcode) - 1].u.operand; \
- else \
- pc += OPCODE_LENGTH(opcode); \
- LLINT_END_IMPL(); \
- } while (false)
-
-#define LLINT_RETURN(value) do { \
- JSValue __r_returnValue = (value); \
- LLINT_CHECK_EXCEPTION(); \
- LLINT_OP(1) = __r_returnValue; \
- LLINT_END_IMPL(); \
- } while (false)
-
-#define LLINT_RETURN_PROFILED(opcode, value) do { \
- JSValue __rp_returnValue = (value); \
- LLINT_CHECK_EXCEPTION(); \
- LLINT_OP(1) = __rp_returnValue; \
- pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \
- JSValue::encode(__rp_returnValue); \
- LLINT_END_IMPL(); \
- } while (false)
-
-#define LLINT_CALL_END_IMPL(exec, callTarget) LLINT_RETURN_TWO((callTarget), (exec))
-
-#define LLINT_CALL_THROW(exec, pc, exceptionToThrow) do { \
- ExecState* __ct_exec = (exec); \
- Instruction* __ct_pc = (pc); \
- globalData.exception = (exceptionToThrow); \
- LLINT_CALL_END_IMPL(__ct_exec, callToThrow(__ct_exec, __ct_pc)); \
- } while (false)
-
-#define LLINT_CALL_CHECK_EXCEPTION(exec, pc) do { \
- ExecState* __cce_exec = (exec); \
- Instruction* __cce_pc = (pc); \
- if (UNLIKELY(globalData.exception)) \
- LLINT_CALL_END_IMPL(__cce_exec, callToThrow(__cce_exec, __cce_pc)); \
- } while (false)
-
-#define LLINT_CALL_RETURN(exec, pc, callTarget) do { \
- ExecState* __cr_exec = (exec); \
- Instruction* __cr_pc = (pc); \
- void* __cr_callTarget = (callTarget); \
- LLINT_CALL_CHECK_EXCEPTION(__cr_exec->callerFrame(), __cr_pc); \
- LLINT_CALL_END_IMPL(__cr_exec, __cr_callTarget); \
- } while (false)
-
-extern "C" SlowPathReturnType llint_trace_operand(ExecState* exec, Instruction* pc, int fromWhere, int operand)
-{
- LLINT_BEGIN();
- dataLog("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d\n",
- exec->codeBlock(),
- exec,
- static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
- exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode),
- fromWhere,
- operand,
- pc[operand].u.operand);
- LLINT_END();
-}
-
-extern "C" SlowPathReturnType llint_trace_value(ExecState* exec, Instruction* pc, int fromWhere, int operand)
-{
- LLINT_BEGIN();
- JSValue value = LLINT_OP_C(operand).jsValue();
- union {
- struct {
- uint32_t tag;
- uint32_t payload;
- } bits;
- EncodedJSValue asValue;
- } u;
- u.asValue = JSValue::encode(value);
- dataLog("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d: %08x:%08x: %s\n",
- exec->codeBlock(),
- exec,
- static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
- exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode),
- fromWhere,
- operand,
- pc[operand].u.operand,
- u.bits.tag,
- u.bits.payload,
- value.description());
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(trace_prologue)
-{
- LLINT_BEGIN();
- dataLog("%p / %p: in prologue.\n", exec->codeBlock(), exec);
- LLINT_END();
-}
-
-static void traceFunctionPrologue(ExecState* exec, const char* comment, CodeSpecializationKind kind)
-{
- JSFunction* callee = asFunction(exec->callee());
- FunctionExecutable* executable = callee->jsExecutable();
- CodeBlock* codeBlock = &executable->generatedBytecodeFor(kind);
- dataLog("%p / %p: in %s of function %p, executable %p; numVars = %u, numParameters = %u, numCalleeRegisters = %u, caller = %p.\n",
- codeBlock, exec, comment, callee, executable,
- codeBlock->m_numVars, codeBlock->numParameters(), codeBlock->m_numCalleeRegisters,
- exec->callerFrame());
-}
-
-LLINT_SLOW_PATH_DECL(trace_prologue_function_for_call)
-{
- LLINT_BEGIN();
- traceFunctionPrologue(exec, "call prologue", CodeForCall);
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(trace_prologue_function_for_construct)
-{
- LLINT_BEGIN();
- traceFunctionPrologue(exec, "construct prologue", CodeForConstruct);
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(trace_arityCheck_for_call)
-{
- LLINT_BEGIN();
- traceFunctionPrologue(exec, "call arity check", CodeForCall);
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(trace_arityCheck_for_construct)
-{
- LLINT_BEGIN();
- traceFunctionPrologue(exec, "construct arity check", CodeForConstruct);
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(trace)
-{
- LLINT_BEGIN();
- dataLog("%p / %p: executing bc#%zu, %s, scope %p\n",
- exec->codeBlock(),
- exec,
- static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
- opcodeNames[exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode)],
- exec->scopeChain());
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(special_trace)
-{
- LLINT_BEGIN();
- dataLog("%p / %p: executing special case bc#%zu, op#%u, return PC is %p\n",
- exec->codeBlock(),
- exec,
- static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
- exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode),
- exec->returnPC().value());
- LLINT_END();
-}
-
-inline bool shouldJIT(ExecState* exec)
-{
- // You can modify this to turn off JITting without rebuilding the world.
- return exec->globalData().canUseJIT();
-}
-
-enum EntryKind { Prologue, ArityCheck };
-static SlowPathReturnType entryOSR(ExecState* exec, Instruction* pc, CodeBlock* codeBlock, const char *name, EntryKind kind)
-{
-#if ENABLE(JIT_VERBOSE_OSR)
- dataLog("%p: Entered %s with executeCounter = %d\n", codeBlock, name, codeBlock->llintExecuteCounter());
-#endif
-
- if (!shouldJIT(exec)) {
- codeBlock->dontJITAnytimeSoon();
- LLINT_RETURN_TWO(0, exec);
- }
- if (!codeBlock->jitCompile(exec->globalData())) {
-#if ENABLE(JIT_VERBOSE_OSR)
- dataLog(" Code was already compiled.\n");
-#endif
- }
- codeBlock->jitSoon();
- if (kind == Prologue)
- LLINT_RETURN_TWO(codeBlock->getJITCode().executableAddressAtOffset(0), exec);
- ASSERT(kind == ArityCheck);
- LLINT_RETURN_TWO(codeBlock->getJITCodeWithArityCheck().executableAddress(), exec);
-}
-
-LLINT_SLOW_PATH_DECL(entry_osr)
-{
- return entryOSR(exec, pc, exec->codeBlock(), "entry_osr", Prologue);
-}
-
-LLINT_SLOW_PATH_DECL(entry_osr_function_for_call)
-{
- return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall), "entry_osr_function_for_call", Prologue);
-}
-
-LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct)
-{
- return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct), "entry_osr_function_for_construct", Prologue);
-}
-
-LLINT_SLOW_PATH_DECL(entry_osr_function_for_call_arityCheck)
-{
- return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall), "entry_osr_function_for_call_arityCheck", ArityCheck);
-}
-
-LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct_arityCheck)
-{
- return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct), "entry_osr_function_for_construct_arityCheck", ArityCheck);
-}
-
-LLINT_SLOW_PATH_DECL(loop_osr)
-{
- CodeBlock* codeBlock = exec->codeBlock();
-
-#if ENABLE(JIT_VERBOSE_OSR)
- dataLog("%p: Entered loop_osr with executeCounter = %d\n", codeBlock, codeBlock->llintExecuteCounter());
-#endif
-
- if (!shouldJIT(exec)) {
- codeBlock->dontJITAnytimeSoon();
- LLINT_RETURN_TWO(0, exec);
- }
-
- if (!codeBlock->jitCompile(exec->globalData())) {
-#if ENABLE(JIT_VERBOSE_OSR)
- dataLog(" Code was already compiled.\n");
-#endif
- }
- codeBlock->jitSoon();
-
- ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT);
-
- Vector<BytecodeAndMachineOffset> map;
- codeBlock->jitCodeMap()->decode(map);
- BytecodeAndMachineOffset* mapping = binarySearch<BytecodeAndMachineOffset, unsigned, BytecodeAndMachineOffset::getBytecodeIndex>(map.begin(), map.size(), pc - codeBlock->instructions().begin());
- ASSERT(mapping);
- ASSERT(mapping->m_bytecodeIndex == static_cast<unsigned>(pc - codeBlock->instructions().begin()));
-
- void* jumpTarget = codeBlock->getJITCode().executableAddressAtOffset(mapping->m_machineCodeOffset);
- ASSERT(jumpTarget);
-
- LLINT_RETURN_TWO(jumpTarget, exec);
-}
-
-LLINT_SLOW_PATH_DECL(replace)
-{
- CodeBlock* codeBlock = exec->codeBlock();
-
-#if ENABLE(JIT_VERBOSE_OSR)
- dataLog("%p: Entered replace with executeCounter = %d\n", codeBlock, codeBlock->llintExecuteCounter());
-#endif
-
- if (shouldJIT(exec)) {
- if (!codeBlock->jitCompile(exec->globalData())) {
-#if ENABLE(JIT_VERBOSE_OSR)
- dataLog(" Code was already compiled.\n");
-#endif
- }
- codeBlock->jitSoon();
- } else
- codeBlock->dontJITAnytimeSoon();
- LLINT_END_IMPL();
-}
-
-LLINT_SLOW_PATH_DECL(register_file_check)
-{
- LLINT_BEGIN();
-#if LLINT_SLOW_PATH_TRACING
- dataLog("Checking stack height with exec = %p.\n", exec);
- dataLog("CodeBlock = %p.\n", exec->codeBlock());
- dataLog("Num callee registers = %u.\n", exec->codeBlock()->m_numCalleeRegisters);
- dataLog("Num vars = %u.\n", exec->codeBlock()->m_numVars);
- dataLog("Current end is at %p.\n", exec->globalData().interpreter->registerFile().end());
-#endif
- ASSERT(&exec->registers()[exec->codeBlock()->m_numCalleeRegisters] > exec->globalData().interpreter->registerFile().end());
- if (UNLIKELY(!globalData.interpreter->registerFile().grow(&exec->registers()[exec->codeBlock()->m_numCalleeRegisters]))) {
- ReturnAddressPtr returnPC = exec->returnPC();
- exec = exec->callerFrame();
- globalData.exception = createStackOverflowError(exec);
- interpreterThrowInCaller(exec, returnPC);
- pc = returnToThrowForThrownException(exec);
- }
- LLINT_END_IMPL();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_call_arityCheck)
-{
- LLINT_BEGIN();
- ExecState* newExec = CommonSlowPaths::arityCheckFor(exec, &globalData.interpreter->registerFile(), CodeForCall);
- if (!newExec) {
- ReturnAddressPtr returnPC = exec->returnPC();
- exec = exec->callerFrame();
- globalData.exception = createStackOverflowError(exec);
- interpreterThrowInCaller(exec, returnPC);
- LLINT_RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
- }
- LLINT_RETURN_TWO(0, newExec);
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_construct_arityCheck)
-{
- LLINT_BEGIN();
- ExecState* newExec = CommonSlowPaths::arityCheckFor(exec, &globalData.interpreter->registerFile(), CodeForConstruct);
- if (!newExec) {
- ReturnAddressPtr returnPC = exec->returnPC();
- exec = exec->callerFrame();
- globalData.exception = createStackOverflowError(exec);
- interpreterThrowInCaller(exec, returnPC);
- LLINT_RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
- }
- LLINT_RETURN_TWO(0, newExec);
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_create_activation)
-{
- LLINT_BEGIN();
-#if LLINT_SLOW_PATH_TRACING
- dataLog("Creating an activation, exec = %p!\n", exec);
-#endif
- JSActivation* activation = JSActivation::create(globalData, exec, static_cast<FunctionExecutable*>(exec->codeBlock()->ownerExecutable()));
- exec->setScopeChain(exec->scopeChain()->push(activation));
- LLINT_RETURN(JSValue(activation));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_create_arguments)
-{
- LLINT_BEGIN();
- JSValue arguments = JSValue(Arguments::create(globalData, exec));
- LLINT_CHECK_EXCEPTION();
- exec->uncheckedR(pc[1].u.operand) = arguments;
- exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)) = arguments;
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_create_this)
-{
- LLINT_BEGIN();
- JSFunction* constructor = asFunction(exec->callee());
-
-#if !ASSERT_DISABLED
- ConstructData constructData;
- ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
-#endif
-
- Structure* structure;
- JSValue proto = LLINT_OP(2).jsValue();
- if (proto.isObject())
- structure = asObject(proto)->inheritorID(globalData);
- else
- structure = constructor->scope()->globalObject->emptyObjectStructure();
-
- LLINT_RETURN(constructEmptyObject(exec, structure));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_convert_this)
-{
- LLINT_BEGIN();
- JSValue v1 = LLINT_OP(1).jsValue();
- ASSERT(v1.isPrimitive());
- LLINT_RETURN(v1.toThisObject(exec));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_new_object)
-{
- LLINT_BEGIN();
- LLINT_RETURN(constructEmptyObject(exec));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_new_array)
-{
- LLINT_BEGIN();
- LLINT_RETURN(constructArray(exec, bitwise_cast<JSValue*>(&LLINT_OP(2)), pc[3].u.operand));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_new_array_buffer)
-{
- LLINT_BEGIN();
- LLINT_RETURN(constructArray(exec, exec->codeBlock()->constantBuffer(pc[2].u.operand), pc[3].u.operand));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_new_regexp)
-{
- LLINT_BEGIN();
- RegExp* regExp = exec->codeBlock()->regexp(pc[2].u.operand);
- if (!regExp->isValid())
- LLINT_THROW(createSyntaxError(exec, "Invalid flag supplied to RegExp constructor."));
- LLINT_RETURN(RegExpObject::create(globalData, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regExp));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_not)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsBoolean(!LLINT_OP_C(2).jsValue().toBoolean(exec)));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_eq)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsBoolean(JSValue::equal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_neq)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsBoolean(!JSValue::equal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_stricteq)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsBoolean(JSValue::strictEqual(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_nstricteq)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsBoolean(!JSValue::strictEqual(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_less)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsBoolean(jsLess<true>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_lesseq)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsBoolean(jsLessEq<true>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_greater)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsBoolean(jsLess<false>(exec, LLINT_OP_C(3).jsValue(), LLINT_OP_C(2).jsValue())));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_greatereq)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsBoolean(jsLessEq<false>(exec, LLINT_OP_C(3).jsValue(), LLINT_OP_C(2).jsValue())));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_pre_inc)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP(1).jsValue().toNumber(exec) + 1));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_pre_dec)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP(1).jsValue().toNumber(exec) - 1));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_post_inc)
-{
- LLINT_BEGIN();
- double result = LLINT_OP(2).jsValue().toNumber(exec);
- LLINT_OP(2) = jsNumber(result + 1);
- LLINT_RETURN(jsNumber(result));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_post_dec)
-{
- LLINT_BEGIN();
- double result = LLINT_OP(2).jsValue().toNumber(exec);
- LLINT_OP(2) = jsNumber(result - 1);
- LLINT_RETURN(jsNumber(result));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_to_jsnumber)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec)));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_negate)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsNumber(-LLINT_OP_C(2).jsValue().toNumber(exec)));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_add)
-{
- LLINT_BEGIN();
- JSValue v1 = LLINT_OP_C(2).jsValue();
- JSValue v2 = LLINT_OP_C(3).jsValue();
-
-#if LLINT_SLOW_PATH_TRACING
- dataLog("Trying to add %s", v1.description());
- dataLog(" to %s.\n", v2.description());
-#endif
-
- if (v1.isString() && !v2.isObject())
- LLINT_RETURN(jsString(exec, asString(v1), v2.toString(exec)));
-
- if (v1.isNumber() && v2.isNumber())
- LLINT_RETURN(jsNumber(v1.asNumber() + v2.asNumber()));
-
- LLINT_RETURN(jsAddSlowCase(exec, v1, v2));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_mul)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) * LLINT_OP_C(3).jsValue().toNumber(exec)));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_sub)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) - LLINT_OP_C(3).jsValue().toNumber(exec)));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_div)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) / LLINT_OP_C(3).jsValue().toNumber(exec)));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_mod)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsNumber(fmod(LLINT_OP_C(2).jsValue().toNumber(exec), LLINT_OP_C(3).jsValue().toNumber(exec))));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_lshift)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) << (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_rshift)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) >> (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_urshift)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toUInt32(exec) >> (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_bitand)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) & LLINT_OP_C(3).jsValue().toInt32(exec)));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_bitor)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) | LLINT_OP_C(3).jsValue().toInt32(exec)));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_bitxor)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) ^ LLINT_OP_C(3).jsValue().toInt32(exec)));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_bitnot)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsNumber(~LLINT_OP_C(2).jsValue().toInt32(exec)));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_check_has_instance)
-{
- LLINT_BEGIN();
- JSValue baseVal = LLINT_OP_C(1).jsValue();
-#ifndef NDEBUG
- TypeInfo typeInfo(UnspecifiedType);
- ASSERT(!baseVal.isObject()
- || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance());
-#endif
- LLINT_THROW(createInvalidParamError(exec, "instanceof", baseVal));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_instanceof)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsBoolean(CommonSlowPaths::opInstanceOfSlow(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue())));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_typeof)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsTypeStringForValue(exec, LLINT_OP_C(2).jsValue()));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_is_undefined)
-{
- LLINT_BEGIN();
- JSValue v = LLINT_OP_C(2).jsValue();
- LLINT_RETURN(jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined()));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_is_boolean)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsBoolean(LLINT_OP_C(2).jsValue().isBoolean()));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_is_number)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsBoolean(LLINT_OP_C(2).jsValue().isNumber()));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_is_string)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsBoolean(isJSString(LLINT_OP_C(2).jsValue())));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_is_object)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsBoolean(jsIsObjectType(LLINT_OP_C(2).jsValue())));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_is_function)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsBoolean(jsIsFunctionType(LLINT_OP_C(2).jsValue())));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_in)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsBoolean(CommonSlowPaths::opIn(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_resolve)
-{
- LLINT_BEGIN();
- LLINT_RETURN_PROFILED(op_resolve, CommonSlowPaths::opResolve(exec, exec->codeBlock()->identifier(pc[2].u.operand)));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_resolve_skip)
-{
- LLINT_BEGIN();
- LLINT_RETURN_PROFILED(
- op_resolve_skip,
- CommonSlowPaths::opResolveSkip(
- exec,
- exec->codeBlock()->identifier(pc[2].u.operand),
- pc[3].u.operand));
-}
-
-static JSValue resolveGlobal(ExecState* exec, Instruction* pc)
-{
- CodeBlock* codeBlock = exec->codeBlock();
- JSGlobalObject* globalObject = codeBlock->globalObject();
- ASSERT(globalObject->isGlobalObject());
- int property = pc[2].u.operand;
- Structure* structure = pc[3].u.structure.get();
-
- ASSERT_UNUSED(structure, structure != globalObject->structure());
-
- Identifier& ident = codeBlock->identifier(property);
- PropertySlot slot(globalObject);
-
- if (globalObject->getPropertySlot(exec, ident, slot)) {
- JSValue result = slot.getValue(exec, ident);
- if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary()
- && slot.slotBase() == globalObject) {
- pc[3].u.structure.set(
- exec->globalData(), codeBlock->ownerExecutable(), globalObject->structure());
- pc[4] = slot.cachedOffset();
- }
-
- return result;
- }
-
- exec->globalData().exception = createUndefinedVariableError(exec, ident);
- return JSValue();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_resolve_global)
-{
- LLINT_BEGIN();
- LLINT_RETURN_PROFILED(op_resolve_global, resolveGlobal(exec, pc));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_resolve_global_dynamic)
-{
- LLINT_BEGIN();
- LLINT_RETURN_PROFILED(op_resolve_global_dynamic, resolveGlobal(exec, pc));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_resolve_for_resolve_global_dynamic)
-{
- LLINT_BEGIN();
- LLINT_RETURN_PROFILED(op_resolve_global_dynamic, CommonSlowPaths::opResolve(exec, exec->codeBlock()->identifier(pc[2].u.operand)));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_resolve_base)
-{
- LLINT_BEGIN();
- Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
- if (pc[3].u.operand) {
- JSValue base = JSC::resolveBase(exec, ident, exec->scopeChain(), true);
- if (!base)
- LLINT_THROW(createErrorForInvalidGlobalAssignment(exec, ident.ustring()));
- LLINT_RETURN(base);
- }
-
- LLINT_RETURN_PROFILED(op_resolve_base, JSC::resolveBase(exec, ident, exec->scopeChain(), false));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_ensure_property_exists)
-{
- LLINT_BEGIN();
- JSObject* object = asObject(LLINT_OP(1).jsValue());
- PropertySlot slot(object);
- Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
- if (!object->getPropertySlot(exec, ident, slot))
- LLINT_THROW(createErrorForInvalidGlobalAssignment(exec, ident.ustring()));
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_resolve_with_base)
-{
- LLINT_BEGIN();
- JSValue result = CommonSlowPaths::opResolveWithBase(exec, exec->codeBlock()->identifier(pc[3].u.operand), LLINT_OP(1));
- LLINT_CHECK_EXCEPTION();
- LLINT_OP(2) = result;
- // FIXME: technically should have profiling, but we don't do it because the DFG won't use it.
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_resolve_with_this)
-{
- LLINT_BEGIN();
- JSValue result = CommonSlowPaths::opResolveWithThis(exec, exec->codeBlock()->identifier(pc[3].u.operand), LLINT_OP(1));
- LLINT_CHECK_EXCEPTION();
- LLINT_OP(2) = result;
- // FIXME: technically should have profiling, but we don't do it because the DFG won't use it.
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_get_by_id)
-{
- LLINT_BEGIN();
- CodeBlock* codeBlock = exec->codeBlock();
- Identifier& ident = codeBlock->identifier(pc[3].u.operand);
- JSValue baseValue = LLINT_OP_C(2).jsValue();
- PropertySlot slot(baseValue);
-
- JSValue result = baseValue.get(exec, ident, slot);
- LLINT_CHECK_EXCEPTION();
- LLINT_OP(1) = result;
-
- if (baseValue.isCell()
- && slot.isCacheable()
- && slot.slotBase() == baseValue
- && slot.cachedPropertyType() == PropertySlot::Value) {
-
- JSCell* baseCell = baseValue.asCell();
- Structure* structure = baseCell->structure();
-
- if (!structure->isUncacheableDictionary()
- && !structure->typeInfo().prohibitsPropertyCaching()) {
- pc[4].u.structure.set(
- globalData, codeBlock->ownerExecutable(), structure);
- pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue);
- }
- }
-
- pc[OPCODE_LENGTH(op_get_by_id) - 1].u.profile->m_buckets[0] = JSValue::encode(result);
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_get_arguments_length)
-{
- LLINT_BEGIN();
- CodeBlock* codeBlock = exec->codeBlock();
- Identifier& ident = codeBlock->identifier(pc[3].u.operand);
- JSValue baseValue = LLINT_OP(2).jsValue();
- PropertySlot slot(baseValue);
- LLINT_RETURN(baseValue.get(exec, ident, slot));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_put_by_id)
-{
- LLINT_BEGIN();
- CodeBlock* codeBlock = exec->codeBlock();
- Identifier& ident = codeBlock->identifier(pc[2].u.operand);
-
- JSValue baseValue = LLINT_OP_C(1).jsValue();
- PutPropertySlot slot(codeBlock->isStrictMode());
- if (pc[8].u.operand)
- asObject(baseValue)->putDirect(globalData, ident, LLINT_OP_C(3).jsValue(), slot);
- else
- baseValue.put(exec, ident, LLINT_OP_C(3).jsValue(), slot);
- LLINT_CHECK_EXCEPTION();
-
- if (baseValue.isCell()
- && slot.isCacheable()) {
-
- JSCell* baseCell = baseValue.asCell();
- Structure* structure = baseCell->structure();
-
- if (!structure->isUncacheableDictionary()
- && !structure->typeInfo().prohibitsPropertyCaching()
- && baseCell == slot.base()) {
-
- if (slot.type() == PutPropertySlot::NewProperty) {
- if (!structure->isDictionary() && structure->previousID()->propertyStorageCapacity() == structure->propertyStorageCapacity()) {
- // This is needed because some of the methods we call
- // below may GC.
- pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id);
-
- normalizePrototypeChain(exec, baseCell);
-
- ASSERT(structure->previousID()->isObject());
- pc[4].u.structure.set(
- globalData, codeBlock->ownerExecutable(), structure->previousID());
- pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue);
- pc[6].u.structure.set(
- globalData, codeBlock->ownerExecutable(), structure);
- StructureChain* chain = structure->prototypeChain(exec);
- ASSERT(chain);
- pc[7].u.structureChain.set(
- globalData, codeBlock->ownerExecutable(), chain);
-
- if (pc[8].u.operand)
- pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id_transition_direct);
- else
- pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id_transition_normal);
- }
- } else {
- pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id);
- pc[4].u.structure.set(
- globalData, codeBlock->ownerExecutable(), structure);
- pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue);
- }
- }
- }
-
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_del_by_id)
-{
- LLINT_BEGIN();
- CodeBlock* codeBlock = exec->codeBlock();
- JSObject* baseObject = LLINT_OP_C(2).jsValue().toObject(exec);
- bool couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, codeBlock->identifier(pc[3].u.operand));
- LLINT_CHECK_EXCEPTION();
- if (!couldDelete && codeBlock->isStrictMode())
- LLINT_THROW(createTypeError(exec, "Unable to delete property."));
- LLINT_RETURN(jsBoolean(couldDelete));
-}
-
-inline JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript)
-{
- if (LIKELY(baseValue.isCell() && subscript.isString())) {
- if (JSValue result = baseValue.asCell()->fastGetOwnProperty(exec, asString(subscript)->value(exec)))
- return result;
- }
-
- if (subscript.isUInt32()) {
- uint32_t i = subscript.asUInt32();
- if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
- return asString(baseValue)->getIndex(exec, i);
-
- if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i))
- return asByteArray(baseValue)->getIndex(exec, i);
-
- return baseValue.get(exec, i);
- }
-
- Identifier property(exec, subscript.toString(exec)->value(exec));
- return baseValue.get(exec, property);
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_get_by_val)
-{
- LLINT_BEGIN();
- LLINT_RETURN_PROFILED(op_get_by_val, getByVal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue()));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_get_argument_by_val)
-{
- LLINT_BEGIN();
- JSValue arguments = LLINT_OP(2).jsValue();
- if (!arguments) {
- arguments = Arguments::create(globalData, exec);
- LLINT_CHECK_EXCEPTION();
- LLINT_OP(2) = arguments;
- exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)) = arguments;
- }
-
- LLINT_RETURN(getByVal(exec, arguments, LLINT_OP_C(3).jsValue()));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_get_by_pname)
-{
- LLINT_BEGIN();
- LLINT_RETURN(getByVal(exec, LLINT_OP(2).jsValue(), LLINT_OP(3).jsValue()));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_put_by_val)
-{
- LLINT_BEGIN();
-
- JSValue baseValue = LLINT_OP_C(1).jsValue();
- JSValue subscript = LLINT_OP_C(2).jsValue();
- JSValue value = LLINT_OP_C(3).jsValue();
-
- if (LIKELY(subscript.isUInt32())) {
- uint32_t i = subscript.asUInt32();
- if (isJSArray(baseValue)) {
- JSArray* jsArray = asArray(baseValue);
- if (jsArray->canSetIndex(i))
- jsArray->setIndex(globalData, i, value);
- else
- JSArray::putByIndex(jsArray, exec, i, value);
- LLINT_END();
- }
- if (isJSByteArray(baseValue)
- && asByteArray(baseValue)->canAccessIndex(i)) {
- JSByteArray* jsByteArray = asByteArray(baseValue);
- if (value.isInt32()) {
- jsByteArray->setIndex(i, value.asInt32());
- LLINT_END();
- }
- if (value.isNumber()) {
- jsByteArray->setIndex(i, value.asNumber());
- LLINT_END();
- }
- }
- baseValue.put(exec, i, value);
- LLINT_END();
- }
-
- Identifier property(exec, subscript.toString(exec)->value(exec));
- LLINT_CHECK_EXCEPTION();
- PutPropertySlot slot(exec->codeBlock()->isStrictMode());
- baseValue.put(exec, property, value, slot);
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_del_by_val)
-{
- LLINT_BEGIN();
- JSValue baseValue = LLINT_OP_C(2).jsValue();
- JSObject* baseObject = baseValue.toObject(exec);
-
- JSValue subscript = LLINT_OP_C(3).jsValue();
-
- bool couldDelete;
-
- uint32_t i;
- if (subscript.getUInt32(i))
- couldDelete = baseObject->methodTable()->deletePropertyByIndex(baseObject, exec, i);
- else {
- LLINT_CHECK_EXCEPTION();
- Identifier property(exec, subscript.toString(exec)->value(exec));
- LLINT_CHECK_EXCEPTION();
- couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, property);
- }
-
- if (!couldDelete && exec->codeBlock()->isStrictMode())
- LLINT_THROW(createTypeError(exec, "Unable to delete property."));
-
- LLINT_RETURN(jsBoolean(couldDelete));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_put_by_index)
-{
- LLINT_BEGIN();
- LLINT_OP_C(1).jsValue().put(exec, pc[2].u.operand, LLINT_OP_C(3).jsValue());
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_put_getter_setter)
-{
- LLINT_BEGIN();
- ASSERT(LLINT_OP(1).jsValue().isObject());
- JSObject* baseObj = asObject(LLINT_OP(1).jsValue());
-
- GetterSetter* accessor = GetterSetter::create(exec);
- LLINT_CHECK_EXCEPTION();
-
- JSValue getter = LLINT_OP(3).jsValue();
- JSValue setter = LLINT_OP(4).jsValue();
- ASSERT(getter.isObject() || getter.isUndefined());
- ASSERT(setter.isObject() || setter.isUndefined());
- ASSERT(getter.isObject() || setter.isObject());
-
- if (!getter.isUndefined())
- accessor->setGetter(globalData, asObject(getter));
- if (!setter.isUndefined())
- accessor->setSetter(globalData, asObject(setter));
- baseObj->putDirectAccessor(
- globalData,
- exec->codeBlock()->identifier(pc[2].u.operand),
- accessor, Accessor);
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_jmp_scopes)
-{
- LLINT_BEGIN();
- unsigned count = pc[1].u.operand;
- ScopeChainNode* tmp = exec->scopeChain();
- while (count--)
- tmp = tmp->pop();
- exec->setScopeChain(tmp);
- pc += pc[2].u.operand;
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_jtrue)
-{
- LLINT_BEGIN();
- LLINT_BRANCH(op_jtrue, LLINT_OP_C(1).jsValue().toBoolean(exec));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_jfalse)
-{
- LLINT_BEGIN();
- LLINT_BRANCH(op_jfalse, !LLINT_OP_C(1).jsValue().toBoolean(exec));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_jless)
-{
- LLINT_BEGIN();
- LLINT_BRANCH(op_jless, jsLess<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_jnless)
-{
- LLINT_BEGIN();
- LLINT_BRANCH(op_jnless, !jsLess<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_jgreater)
-{
- LLINT_BEGIN();
- LLINT_BRANCH(op_jgreater, jsLess<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_jngreater)
-{
- LLINT_BEGIN();
- LLINT_BRANCH(op_jngreater, !jsLess<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_jlesseq)
-{
- LLINT_BEGIN();
- LLINT_BRANCH(op_jlesseq, jsLessEq<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_jnlesseq)
-{
- LLINT_BEGIN();
- LLINT_BRANCH(op_jnlesseq, !jsLessEq<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_jgreatereq)
-{
- LLINT_BEGIN();
- LLINT_BRANCH(op_jgreatereq, jsLessEq<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_jngreatereq)
-{
- LLINT_BEGIN();
- LLINT_BRANCH(op_jngreatereq, !jsLessEq<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_switch_imm)
-{
- LLINT_BEGIN();
- JSValue scrutinee = LLINT_OP_C(3).jsValue();
- ASSERT(scrutinee.isDouble());
- double value = scrutinee.asDouble();
- int32_t intValue = static_cast<int32_t>(value);
- int defaultOffset = pc[2].u.operand;
- if (value == intValue) {
- CodeBlock* codeBlock = exec->codeBlock();
- pc += codeBlock->immediateSwitchJumpTable(pc[1].u.operand).offsetForValue(intValue, defaultOffset);
- } else
- pc += defaultOffset;
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_switch_string)
-{
- LLINT_BEGIN();
- JSValue scrutinee = LLINT_OP_C(3).jsValue();
- int defaultOffset = pc[2].u.operand;
- if (!scrutinee.isString())
- pc += defaultOffset;
- else {
- CodeBlock* codeBlock = exec->codeBlock();
- pc += codeBlock->stringSwitchJumpTable(pc[1].u.operand).offsetForValue(asString(scrutinee)->value(exec).impl(), defaultOffset);
- }
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_new_func)
-{
- LLINT_BEGIN();
- CodeBlock* codeBlock = exec->codeBlock();
- ASSERT(codeBlock->codeType() != FunctionCode
- || !codeBlock->needsFullScopeChain()
- || exec->uncheckedR(codeBlock->activationRegister()).jsValue());
-#if LLINT_SLOW_PATH_TRACING
- dataLog("Creating function!\n");
-#endif
- LLINT_RETURN(codeBlock->functionDecl(pc[2].u.operand)->make(exec, exec->scopeChain()));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_new_func_exp)
-{
- LLINT_BEGIN();
- CodeBlock* codeBlock = exec->codeBlock();
- FunctionExecutable* function = codeBlock->functionExpr(pc[2].u.operand);
- JSFunction* func = function->make(exec, exec->scopeChain());
-
- if (!function->name().isNull()) {
- JSStaticScopeObject* functionScopeObject = JSStaticScopeObject::create(exec, function->name(), func, ReadOnly | DontDelete);
- func->setScope(globalData, func->scope()->push(functionScopeObject));
- }
-
- LLINT_RETURN(func);
-}
-
-static SlowPathReturnType handleHostCall(ExecState* execCallee, Instruction* pc, JSValue callee, CodeSpecializationKind kind)
-{
- ExecState* exec = execCallee->callerFrame();
- JSGlobalData& globalData = exec->globalData();
-
- execCallee->setScopeChain(exec->scopeChain());
- execCallee->setCodeBlock(0);
- execCallee->clearReturnPC();
-
- if (kind == CodeForCall) {
- CallData callData;
- CallType callType = getCallData(callee, callData);
-
- ASSERT(callType != CallTypeJS);
-
- if (callType == CallTypeHost) {
- globalData.hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
-
- LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
- }
-
-#if LLINT_SLOW_PATH_TRACING
- dataLog("Call callee is not a function: %s\n", callee.description());
-#endif
-
- ASSERT(callType == CallTypeNone);
- LLINT_CALL_THROW(exec, pc, createNotAFunctionError(exec, callee));
- }
-
- ASSERT(kind == CodeForConstruct);
-
- ConstructData constructData;
- ConstructType constructType = getConstructData(callee, constructData);
-
- ASSERT(constructType != ConstructTypeJS);
-
- if (constructType == ConstructTypeHost) {
- globalData.hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
-
- LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
- }
-
-#if LLINT_SLOW_PATH_TRACING
- dataLog("Constructor callee is not a function: %s\n", callee.description());
-#endif
-
- ASSERT(constructType == ConstructTypeNone);
- LLINT_CALL_THROW(exec, pc, createNotAConstructorError(exec, callee));
-}
-
-inline SlowPathReturnType setUpCall(ExecState* execCallee, Instruction* pc, CodeSpecializationKind kind, JSValue calleeAsValue, LLIntCallLinkInfo* callLinkInfo = 0)
-{
-#if LLINT_SLOW_PATH_TRACING
- dataLog("Performing call with recorded PC = %p\n", execCallee->callerFrame()->currentVPC());
-#endif
-
- JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
- if (!calleeAsFunctionCell)
- return handleHostCall(execCallee, pc, calleeAsValue, kind);
-
- JSFunction* callee = asFunction(calleeAsFunctionCell);
- ScopeChainNode* scope = callee->scopeUnchecked();
- JSGlobalData& globalData = *scope->globalData;
- execCallee->setScopeChain(scope);
- ExecutableBase* executable = callee->executable();
-
- MacroAssemblerCodePtr codePtr;
- CodeBlock* codeBlock = 0;
- if (executable->isHostFunction())
- codePtr = executable->generatedJITCodeFor(kind).addressForCall();
- else {
- FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
- JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind);
- if (error)
- LLINT_CALL_THROW(execCallee->callerFrame(), pc, error);
- codeBlock = &functionExecutable->generatedBytecodeFor(kind);
- ASSERT(codeBlock);
- if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
- codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
- else
- codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
- }
-
- if (callLinkInfo) {
- if (callLinkInfo->isOnList())
- callLinkInfo->remove();
- ExecState* execCaller = execCallee->callerFrame();
- callLinkInfo->callee.set(globalData, execCaller->codeBlock()->ownerExecutable(), callee);
- callLinkInfo->lastSeenCallee.set(globalData, execCaller->codeBlock()->ownerExecutable(), callee);
- callLinkInfo->machineCodeTarget = codePtr;
- if (codeBlock)
- codeBlock->linkIncomingCall(callLinkInfo);
- }
-
- LLINT_CALL_RETURN(execCallee, pc, codePtr.executableAddress());
-}
-
-inline SlowPathReturnType genericCall(ExecState* exec, Instruction* pc, CodeSpecializationKind kind)
-{
- // This needs to:
- // - Set up a call frame.
- // - Figure out what to call and compile it if necessary.
- // - If possible, link the call's inline cache.
- // - Return a tuple of machine code address to call and the new call frame.
-
- JSValue calleeAsValue = LLINT_OP_C(1).jsValue();
-
- ExecState* execCallee = exec + pc[3].u.operand;
-
- execCallee->setArgumentCountIncludingThis(pc[2].u.operand);
- execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue;
- execCallee->setCallerFrame(exec);
-
- ASSERT(pc[4].u.callLinkInfo);
- return setUpCall(execCallee, pc, kind, calleeAsValue, pc[4].u.callLinkInfo);
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_call)
-{
- LLINT_BEGIN_NO_SET_PC();
- return genericCall(exec, pc, CodeForCall);
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_construct)
-{
- LLINT_BEGIN_NO_SET_PC();
- return genericCall(exec, pc, CodeForConstruct);
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_call_varargs)
-{
- LLINT_BEGIN();
- // This needs to:
- // - Set up a call frame while respecting the variable arguments.
- // - Figure out what to call and compile it if necessary.
- // - Return a tuple of machine code address to call and the new call frame.
-
- JSValue calleeAsValue = LLINT_OP_C(1).jsValue();
-
- ExecState* execCallee = loadVarargs(
- exec, &globalData.interpreter->registerFile(),
- LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue(), pc[4].u.operand);
- LLINT_CALL_CHECK_EXCEPTION(exec, pc);
-
- execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue;
- execCallee->setCallerFrame(exec);
- exec->uncheckedR(RegisterFile::ArgumentCount).tag() = bitwise_cast<int32_t>(pc + OPCODE_LENGTH(op_call_varargs));
-
- return setUpCall(execCallee, pc, CodeForCall, calleeAsValue);
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_call_eval)
-{
- LLINT_BEGIN_NO_SET_PC();
- JSValue calleeAsValue = LLINT_OP(1).jsValue();
-
- ExecState* execCallee = exec + pc[3].u.operand;
-
- execCallee->setArgumentCountIncludingThis(pc[2].u.operand);
- execCallee->setCallerFrame(exec);
- execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue;
- execCallee->setScopeChain(exec->scopeChain());
- execCallee->setReturnPC(bitwise_cast<Instruction*>(&llint_generic_return_point));
- execCallee->setCodeBlock(0);
- exec->uncheckedR(RegisterFile::ArgumentCount).tag() = bitwise_cast<int32_t>(pc + OPCODE_LENGTH(op_call_eval));
-
- if (!isHostFunction(calleeAsValue, globalFuncEval))
- return setUpCall(execCallee, pc, CodeForCall, calleeAsValue);
-
- globalData.hostCallReturnValue = eval(execCallee);
- LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_tear_off_activation)
-{
- LLINT_BEGIN();
- ASSERT(exec->codeBlock()->needsFullScopeChain());
- JSValue activationValue = LLINT_OP(1).jsValue();
- if (!activationValue) {
- if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)).jsValue()) {
- if (!exec->codeBlock()->isStrictMode())
- asArguments(v)->tearOff(exec);
- }
- LLINT_END();
- }
- JSActivation* activation = asActivation(activationValue);
- activation->tearOff(globalData);
- if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)).jsValue())
- asArguments(v)->didTearOffActivation(globalData, activation);
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_tear_off_arguments)
-{
- LLINT_BEGIN();
- ASSERT(exec->codeBlock()->usesArguments() && !exec->codeBlock()->needsFullScopeChain());
- asArguments(exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)).jsValue())->tearOff(exec);
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_strcat)
-{
- LLINT_BEGIN();
- LLINT_RETURN(jsString(exec, &LLINT_OP(2), pc[3].u.operand));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_to_primitive)
-{
- LLINT_BEGIN();
- LLINT_RETURN(LLINT_OP_C(2).jsValue().toPrimitive(exec));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_get_pnames)
-{
- LLINT_BEGIN();
- JSValue v = LLINT_OP(2).jsValue();
- if (v.isUndefinedOrNull()) {
- pc += pc[5].u.operand;
- LLINT_END();
- }
-
- JSObject* o = v.toObject(exec);
- Structure* structure = o->structure();
- JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
- if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(exec))
- jsPropertyNameIterator = JSPropertyNameIterator::create(exec, o);
-
- LLINT_OP(1) = JSValue(jsPropertyNameIterator);
- LLINT_OP(2) = JSValue(o);
- LLINT_OP(3) = Register::withInt(0);
- LLINT_OP(4) = Register::withInt(jsPropertyNameIterator->size());
-
- pc += OPCODE_LENGTH(op_get_pnames);
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_next_pname)
-{
- LLINT_BEGIN();
- JSObject* base = asObject(LLINT_OP(2).jsValue());
- JSString* property = asString(LLINT_OP(1).jsValue());
- if (base->hasProperty(exec, Identifier(exec, property->value(exec)))) {
- // Go to target.
- pc += pc[6].u.operand;
- } // Else, don't change the PC, so the interpreter will reloop.
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_push_scope)
-{
- LLINT_BEGIN();
- JSValue v = LLINT_OP(1).jsValue();
- JSObject* o = v.toObject(exec);
- LLINT_CHECK_EXCEPTION();
-
- LLINT_OP(1) = o;
- exec->setScopeChain(exec->scopeChain()->push(o));
-
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_pop_scope)
-{
- LLINT_BEGIN();
- exec->setScopeChain(exec->scopeChain()->pop());
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_push_new_scope)
-{
- LLINT_BEGIN();
- CodeBlock* codeBlock = exec->codeBlock();
- JSObject* scope = JSStaticScopeObject::create(exec, codeBlock->identifier(pc[2].u.operand), LLINT_OP(3).jsValue(), DontDelete);
- exec->setScopeChain(exec->scopeChain()->push(scope));
- LLINT_RETURN(scope);
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_throw)
-{
- LLINT_BEGIN();
- LLINT_THROW(LLINT_OP_C(1).jsValue());
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_throw_reference_error)
-{
- LLINT_BEGIN();
- LLINT_THROW(createReferenceError(exec, LLINT_OP_C(1).jsValue().toString(exec)->value(exec)));
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_debug)
-{
- LLINT_BEGIN();
- int debugHookID = pc[1].u.operand;
- int firstLine = pc[2].u.operand;
- int lastLine = pc[3].u.operand;
-
- globalData.interpreter->debug(exec, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
-
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_profile_will_call)
-{
- LLINT_BEGIN();
- (*Profiler::enabledProfilerReference())->willExecute(exec, LLINT_OP(1).jsValue());
- LLINT_END();
-}
-
-LLINT_SLOW_PATH_DECL(slow_path_profile_did_call)
-{
- LLINT_BEGIN();
- (*Profiler::enabledProfilerReference())->didExecute(exec, LLINT_OP(1).jsValue());
- LLINT_END();
-}
-
-} } // namespace JSC::LLInt
-
-#endif // ENABLE(LLINT)
+++ /dev/null
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef LLIntSlowPaths_h
-#define LLIntSlowPaths_h
-
-#include <wtf/Platform.h>
-#include <wtf/StdLibExtras.h>
-
-#if ENABLE(LLINT)
-
-namespace JSC {
-
-class ExecState;
-struct Instruction;
-
-namespace LLInt {
-
-typedef int64_t SlowPathReturnType;
-
-extern "C" SlowPathReturnType llint_trace_operand(ExecState*, Instruction*, int fromWhere, int operand);
-extern "C" SlowPathReturnType llint_trace_value(ExecState*, Instruction*, int fromWhere, int operand);
-
-#define LLINT_SLOW_PATH_DECL(name) \
- extern "C" SlowPathReturnType llint_##name(ExecState* exec, Instruction* pc)
-
-LLINT_SLOW_PATH_DECL(trace_prologue);
-LLINT_SLOW_PATH_DECL(trace_prologue_function_for_call);
-LLINT_SLOW_PATH_DECL(trace_prologue_function_for_construct);
-LLINT_SLOW_PATH_DECL(trace_arityCheck_for_call);
-LLINT_SLOW_PATH_DECL(trace_arityCheck_for_construct);
-LLINT_SLOW_PATH_DECL(trace);
-LLINT_SLOW_PATH_DECL(special_trace);
-LLINT_SLOW_PATH_DECL(entry_osr);
-LLINT_SLOW_PATH_DECL(entry_osr_function_for_call);
-LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct);
-LLINT_SLOW_PATH_DECL(entry_osr_function_for_call_arityCheck);
-LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct_arityCheck);
-LLINT_SLOW_PATH_DECL(loop_osr);
-LLINT_SLOW_PATH_DECL(replace);
-LLINT_SLOW_PATH_DECL(register_file_check);
-LLINT_SLOW_PATH_DECL(slow_path_call_arityCheck);
-LLINT_SLOW_PATH_DECL(slow_path_construct_arityCheck);
-LLINT_SLOW_PATH_DECL(slow_path_create_activation);
-LLINT_SLOW_PATH_DECL(slow_path_create_arguments);
-LLINT_SLOW_PATH_DECL(slow_path_create_this);
-LLINT_SLOW_PATH_DECL(slow_path_convert_this);
-LLINT_SLOW_PATH_DECL(slow_path_new_object);
-LLINT_SLOW_PATH_DECL(slow_path_new_array);
-LLINT_SLOW_PATH_DECL(slow_path_new_array_buffer);
-LLINT_SLOW_PATH_DECL(slow_path_new_regexp);
-LLINT_SLOW_PATH_DECL(slow_path_not);
-LLINT_SLOW_PATH_DECL(slow_path_eq);
-LLINT_SLOW_PATH_DECL(slow_path_neq);
-LLINT_SLOW_PATH_DECL(slow_path_stricteq);
-LLINT_SLOW_PATH_DECL(slow_path_nstricteq);
-LLINT_SLOW_PATH_DECL(slow_path_less);
-LLINT_SLOW_PATH_DECL(slow_path_lesseq);
-LLINT_SLOW_PATH_DECL(slow_path_greater);
-LLINT_SLOW_PATH_DECL(slow_path_greatereq);
-LLINT_SLOW_PATH_DECL(slow_path_pre_inc);
-LLINT_SLOW_PATH_DECL(slow_path_pre_dec);
-LLINT_SLOW_PATH_DECL(slow_path_post_inc);
-LLINT_SLOW_PATH_DECL(slow_path_post_dec);
-LLINT_SLOW_PATH_DECL(slow_path_to_jsnumber);
-LLINT_SLOW_PATH_DECL(slow_path_negate);
-LLINT_SLOW_PATH_DECL(slow_path_add);
-LLINT_SLOW_PATH_DECL(slow_path_mul);
-LLINT_SLOW_PATH_DECL(slow_path_sub);
-LLINT_SLOW_PATH_DECL(slow_path_div);
-LLINT_SLOW_PATH_DECL(slow_path_mod);
-LLINT_SLOW_PATH_DECL(slow_path_lshift);
-LLINT_SLOW_PATH_DECL(slow_path_rshift);
-LLINT_SLOW_PATH_DECL(slow_path_urshift);
-LLINT_SLOW_PATH_DECL(slow_path_bitand);
-LLINT_SLOW_PATH_DECL(slow_path_bitor);
-LLINT_SLOW_PATH_DECL(slow_path_bitxor);
-LLINT_SLOW_PATH_DECL(slow_path_bitnot);
-LLINT_SLOW_PATH_DECL(slow_path_check_has_instance);
-LLINT_SLOW_PATH_DECL(slow_path_instanceof);
-LLINT_SLOW_PATH_DECL(slow_path_typeof);
-LLINT_SLOW_PATH_DECL(slow_path_is_undefined);
-LLINT_SLOW_PATH_DECL(slow_path_is_boolean);
-LLINT_SLOW_PATH_DECL(slow_path_is_number);
-LLINT_SLOW_PATH_DECL(slow_path_is_string);
-LLINT_SLOW_PATH_DECL(slow_path_is_object);
-LLINT_SLOW_PATH_DECL(slow_path_is_function);
-LLINT_SLOW_PATH_DECL(slow_path_in);
-LLINT_SLOW_PATH_DECL(slow_path_resolve);
-LLINT_SLOW_PATH_DECL(slow_path_resolve_skip);
-LLINT_SLOW_PATH_DECL(slow_path_resolve_global);
-LLINT_SLOW_PATH_DECL(slow_path_resolve_global_dynamic);
-LLINT_SLOW_PATH_DECL(slow_path_resolve_for_resolve_global_dynamic);
-LLINT_SLOW_PATH_DECL(slow_path_resolve_base);
-LLINT_SLOW_PATH_DECL(slow_path_ensure_property_exists);
-LLINT_SLOW_PATH_DECL(slow_path_resolve_with_base);
-LLINT_SLOW_PATH_DECL(slow_path_resolve_with_this);
-LLINT_SLOW_PATH_DECL(slow_path_get_by_id);
-LLINT_SLOW_PATH_DECL(slow_path_get_arguments_length);
-LLINT_SLOW_PATH_DECL(slow_path_put_by_id);
-LLINT_SLOW_PATH_DECL(slow_path_del_by_id);
-LLINT_SLOW_PATH_DECL(slow_path_get_by_val);
-LLINT_SLOW_PATH_DECL(slow_path_get_argument_by_val);
-LLINT_SLOW_PATH_DECL(slow_path_get_by_pname);
-LLINT_SLOW_PATH_DECL(slow_path_put_by_val);
-LLINT_SLOW_PATH_DECL(slow_path_del_by_val);
-LLINT_SLOW_PATH_DECL(slow_path_put_by_index);
-LLINT_SLOW_PATH_DECL(slow_path_put_getter_setter);
-LLINT_SLOW_PATH_DECL(slow_path_jmp_scopes);
-LLINT_SLOW_PATH_DECL(slow_path_jtrue);
-LLINT_SLOW_PATH_DECL(slow_path_jfalse);
-LLINT_SLOW_PATH_DECL(slow_path_jless);
-LLINT_SLOW_PATH_DECL(slow_path_jnless);
-LLINT_SLOW_PATH_DECL(slow_path_jgreater);
-LLINT_SLOW_PATH_DECL(slow_path_jngreater);
-LLINT_SLOW_PATH_DECL(slow_path_jlesseq);
-LLINT_SLOW_PATH_DECL(slow_path_jnlesseq);
-LLINT_SLOW_PATH_DECL(slow_path_jgreatereq);
-LLINT_SLOW_PATH_DECL(slow_path_jngreatereq);
-LLINT_SLOW_PATH_DECL(slow_path_switch_imm);
-LLINT_SLOW_PATH_DECL(slow_path_switch_char);
-LLINT_SLOW_PATH_DECL(slow_path_switch_string);
-LLINT_SLOW_PATH_DECL(slow_path_new_func);
-LLINT_SLOW_PATH_DECL(slow_path_new_func_exp);
-LLINT_SLOW_PATH_DECL(slow_path_call);
-LLINT_SLOW_PATH_DECL(slow_path_construct);
-LLINT_SLOW_PATH_DECL(slow_path_call_varargs);
-LLINT_SLOW_PATH_DECL(slow_path_call_eval);
-LLINT_SLOW_PATH_DECL(slow_path_tear_off_activation);
-LLINT_SLOW_PATH_DECL(slow_path_tear_off_arguments);
-LLINT_SLOW_PATH_DECL(slow_path_strcat);
-LLINT_SLOW_PATH_DECL(slow_path_to_primitive);
-LLINT_SLOW_PATH_DECL(slow_path_get_pnames);
-LLINT_SLOW_PATH_DECL(slow_path_next_pname);
-LLINT_SLOW_PATH_DECL(slow_path_push_scope);
-LLINT_SLOW_PATH_DECL(slow_path_pop_scope);
-LLINT_SLOW_PATH_DECL(slow_path_push_new_scope);
-LLINT_SLOW_PATH_DECL(slow_path_throw);
-LLINT_SLOW_PATH_DECL(slow_path_throw_reference_error);
-LLINT_SLOW_PATH_DECL(slow_path_debug);
-LLINT_SLOW_PATH_DECL(slow_path_profile_will_call);
-LLINT_SLOW_PATH_DECL(slow_path_profile_did_call);
-
-} } // namespace JSC::LLInt
-
-#endif // ENABLE(LLINT)
-
-#endif // LLIntSlowPaths_h
-
+++ /dev/null
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "LLIntThunks.h"
-
-#if ENABLE(LLINT)
-
-#include "JSInterfaceJIT.h"
-#include "LinkBuffer.h"
-#include "LowLevelInterpreter.h"
-
-namespace JSC { namespace LLInt {
-
-static MacroAssemblerCodeRef generateThunkWithJumpTo(JSGlobalData* globalData, void (*target)())
-{
- JSInterfaceJIT jit;
-
- // FIXME: there's probably a better way to do it on X86, but I'm not sure I care.
- jit.move(JSInterfaceJIT::TrustedImmPtr(bitwise_cast<void*>(target)), JSInterfaceJIT::regT0);
- jit.jump(JSInterfaceJIT::regT0);
-
- LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
- return patchBuffer.finalizeCode();
-}
-
-MacroAssemblerCodeRef functionForCallEntryThunkGenerator(JSGlobalData* globalData)
-{
- return generateThunkWithJumpTo(globalData, llint_function_for_call_prologue);
-}
-
-MacroAssemblerCodeRef functionForConstructEntryThunkGenerator(JSGlobalData* globalData)
-{
- return generateThunkWithJumpTo(globalData, llint_function_for_construct_prologue);
-}
-
-MacroAssemblerCodeRef functionForCallArityCheckThunkGenerator(JSGlobalData* globalData)
-{
- return generateThunkWithJumpTo(globalData, llint_function_for_call_arity_check);
-}
-
-MacroAssemblerCodeRef functionForConstructArityCheckThunkGenerator(JSGlobalData* globalData)
-{
- return generateThunkWithJumpTo(globalData, llint_function_for_construct_arity_check);
-}
-
-MacroAssemblerCodeRef evalEntryThunkGenerator(JSGlobalData* globalData)
-{
- return generateThunkWithJumpTo(globalData, llint_eval_prologue);
-}
-
-MacroAssemblerCodeRef programEntryThunkGenerator(JSGlobalData* globalData)
-{
- return generateThunkWithJumpTo(globalData, llint_program_prologue);
-}
-
-} } // namespace JSC::LLInt
-
-#endif // ENABLE(LLINT)
+++ /dev/null
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef LLIntThunks_h
-#define LLIntThunks_h
-
-#include <wtf/Platform.h>
-
-#if ENABLE(LLINT)
-
-#include "MacroAssemblerCodeRef.h"
-
-namespace JSC {
-
-class JSGlobalData;
-
-namespace LLInt {
-
-MacroAssemblerCodeRef functionForCallEntryThunkGenerator(JSGlobalData*);
-MacroAssemblerCodeRef functionForConstructEntryThunkGenerator(JSGlobalData*);
-MacroAssemblerCodeRef functionForCallArityCheckThunkGenerator(JSGlobalData*);
-MacroAssemblerCodeRef functionForConstructArityCheckThunkGenerator(JSGlobalData*);
-MacroAssemblerCodeRef evalEntryThunkGenerator(JSGlobalData*);
-MacroAssemblerCodeRef programEntryThunkGenerator(JSGlobalData*);
-
-} } // namespace JSC::LLInt
-
-#endif // ENABLE(LLINT)
-
-#endif // LLIntThunks_h
+++ /dev/null
-# Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
-# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-# THE POSSIBILITY OF SUCH DAMAGE.
-
-
-# Crash course on the language that this is written in (which I just call
-# "assembly" even though it's more than that):
-#
-# - Mostly gas-style operand ordering. The last operand tends to be the
-# destination. So "a := b" is written as "mov b, a". But unlike gas,
-# comparisons are in-order, so "if (a < b)" is written as
-# "bilt a, b, ...".
-#
-# - "b" = byte, "h" = 16-bit word, "i" = 32-bit word, "p" = pointer.
-# Currently this is just 32-bit so "i" and "p" are interchangeable
-# except when an op supports one but not the other.
-#
-# - In general, valid operands for macro invocations and instructions are
-# registers (eg "t0"), addresses (eg "4[t0]"), base-index addresses
-# (eg "7[t0, t1, 2]"), absolute addresses (eg "0xa0000000[]"), or labels
-# (eg "_foo" or ".foo"). Macro invocations can also take anonymous
-# macros as operands. Instructions cannot take anonymous macros.
-#
-# - Labels must have names that begin with either "_" or ".". A "." label
-# is local and gets renamed before code gen to minimize namespace
-# pollution. A "_" label is an extern symbol (i.e. ".globl"). The "_"
-# may or may not be removed during code gen depending on whether the asm
-# conventions for C name mangling on the target platform mandate a "_"
-# prefix.
-#
-# - A "macro" is a lambda expression, which may be either anonymous or
-# named. But this has caveats. "macro" can take zero or more arguments,
-# which may be macros or any valid operands, but it can only return
-# code. But you can do Turing-complete things via continuation passing
-# style: "macro foo (a, b) b(a) end foo(foo, foo)". Actually, don't do
-# that, since you'll just crash the assembler.
-#
-# - An "if" is a conditional on settings. Any identifier supplied in the
-# predicate of an "if" is assumed to be a #define that is available
-# during code gen. So you can't use "if" for computation in a macro, but
-# you can use it to select different pieces of code for different
-# platforms.
-#
-# - Arguments to macros follow lexical scoping rather than dynamic scoping.
-# Const's also follow lexical scoping and may override (hide) arguments
-# or other consts. All variables (arguments and constants) can be bound
-# to operands. Additionally, arguments (but not constants) can be bound
-# to macros.
-
-
-# Below we have a bunch of constant declarations. Each constant must have
-# a corresponding ASSERT() in LLIntData.cpp.
-
-# These declarations must match interpreter/RegisterFile.h.
-const CallFrameHeaderSize = 48
-const ArgumentCount = -48
-const CallerFrame = -40
-const Callee = -32
-const ScopeChain = -24
-const ReturnPC = -16
-const CodeBlock = -8
-
-const ThisArgumentOffset = -CallFrameHeaderSize - 8
-
-# Declare some aliases for the registers we will use.
-const PC = t4
-
-# Offsets needed for reasoning about value representation.
-if BIG_ENDIAN
- const TagOffset = 0
- const PayloadOffset = 4
-else
- const TagOffset = 4
- const PayloadOffset = 0
-end
-
-# Value representation constants.
-const Int32Tag = -1
-const BooleanTag = -2
-const NullTag = -3
-const UndefinedTag = -4
-const CellTag = -5
-const EmptyValueTag = -6
-const DeletedValueTag = -7
-const LowestTag = DeletedValueTag
-
-# Type constants.
-const StringType = 5
-const ObjectType = 13
-
-# Type flags constants.
-const MasqueradesAsUndefined = 1
-const ImplementsHasInstance = 2
-const ImplementsDefaultHasInstance = 8
-
-# Heap allocation constants.
-const JSFinalObjectSizeClassIndex = 3
-
-# Bytecode operand constants.
-const FirstConstantRegisterIndex = 0x40000000
-
-# Code type constants.
-const GlobalCode = 0
-const EvalCode = 1
-const FunctionCode = 2
-
-# The interpreter steals the tag word of the argument count.
-const LLIntReturnPC = ArgumentCount + TagOffset
-
-# This must match wtf/Vector.h.
-const VectorSizeOffset = 0
-const VectorBufferOffset = 4
-
-# String flags.
-const HashFlags8BitBuffer = 64
-
-# Utilities
-macro crash()
- storei 0, 0xbbadbeef[]
- move 0, t0
- call t0
-end
-
-macro assert(assertion)
- if ASSERT_ENABLED
- assertion(.ok)
- crash()
- .ok:
- end
-end
-
-macro preserveReturnAddressAfterCall(destinationRegister)
- if ARMv7
- move lr, destinationRegister
- elsif X86
- pop destinationRegister
- else
- error
- end
-end
-
-macro restoreReturnAddressBeforeReturn(sourceRegister)
- if ARMv7
- move sourceRegister, lr
- elsif X86
- push sourceRegister
- else
- error
- end
-end
-
-macro dispatch(advance)
- addp advance * 4, PC
- jmp [PC]
-end
-
-macro dispatchBranchWithOffset(pcOffset)
- lshifti 2, pcOffset
- addp pcOffset, PC
- jmp [PC]
-end
-
-macro dispatchBranch(pcOffset)
- loadi pcOffset, t0
- dispatchBranchWithOffset(t0)
-end
-
-macro dispatchAfterCall()
- loadi ArgumentCount + TagOffset[cfr], PC
- jmp [PC]
-end
-
-macro cCall2(function, arg1, arg2)
- if ARMv7
- move arg1, t0
- move arg2, t1
- elsif X86
- poke arg1, 0
- poke arg2, 1
- else
- error
- end
- call function
-end
-
-# This barely works. arg3 and arg4 should probably be immediates.
-macro cCall4(function, arg1, arg2, arg3, arg4)
- if ARMv7
- move arg1, t0
- move arg2, t1
- move arg3, t2
- move arg4, t3
- elsif X86
- poke arg1, 0
- poke arg2, 1
- poke arg3, 2
- poke arg4, 3
- else
- error
- end
- call function
-end
-
-macro callSlowPath(slow_path)
- cCall2(slow_path, cfr, PC)
- move t0, PC
- move t1, cfr
-end
-
-# Debugging operation if you'd like to print an operand in the instruction stream. fromWhere
-# should be an immediate integer - any integer you like; use it to identify the place you're
-# debugging from. operand should likewise be an immediate, and should identify the operand
-# in the instruction stream you'd like to print out.
-macro traceOperand(fromWhere, operand)
- cCall4(_llint_trace_operand, cfr, PC, fromWhere, operand)
- move t0, PC
- move t1, cfr
-end
-
-# Debugging operation if you'd like to print the value of an operand in the instruction
-# stream. Same as traceOperand(), but assumes that the operand is a register, and prints its
-# value.
-macro traceValue(fromWhere, operand)
- cCall4(_llint_trace_value, cfr, PC, fromWhere, operand)
- move t0, PC
- move t1, cfr
-end
-
-macro traceExecution()
- if EXECUTION_TRACING
- callSlowPath(_llint_trace)
- end
-end
-
-# Call a slow_path for call opcodes.
-macro callCallSlowPath(advance, slow_path, action)
- addp advance * 4, PC, t0
- storep t0, ArgumentCount + TagOffset[cfr]
- cCall2(slow_path, cfr, PC)
- move t1, cfr
- action(t0)
-end
-
-macro slowPathForCall(advance, slow_path)
- callCallSlowPath(
- advance,
- slow_path,
- macro (callee)
- call callee
- dispatchAfterCall()
- end)
-end
-
-macro checkSwitchToJIT(increment, action)
- if JIT_ENABLED
- loadp CodeBlock[cfr], t0
- baddis increment, CodeBlock::m_llintExecuteCounter[t0], .continue
- action()
- .continue:
- end
-end
-
-macro checkSwitchToJITForLoop()
- checkSwitchToJIT(
- 1,
- macro ()
- storei PC, ArgumentCount + TagOffset[cfr]
- cCall2(_llint_loop_osr, cfr, PC)
- move t1, cfr
- btpz t0, .recover
- jmp t0
- .recover:
- loadi ArgumentCount + TagOffset[cfr], PC
- end)
-end
-
-macro checkSwitchToJITForEpilogue()
- checkSwitchToJIT(
- 10,
- macro ()
- callSlowPath(_llint_replace)
- end)
-end
-
-macro assertNotConstant(index)
- assert(macro (ok) bilt index, FirstConstantRegisterIndex, ok end)
-end
-
-# Index, tag, and payload must be different registers. Index is not
-# changed.
-macro loadConstantOrVariable(index, tag, payload)
- bigteq index, FirstConstantRegisterIndex, .constant
- loadi TagOffset[cfr, index, 8], tag
- loadi PayloadOffset[cfr, index, 8], payload
- jmp .done
-.constant:
- loadp CodeBlock[cfr], payload
- loadp CodeBlock::m_constantRegisters + VectorBufferOffset[payload], payload
- # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex,
- # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3.
- loadp TagOffset[payload, index, 8], tag
- loadp PayloadOffset[payload, index, 8], payload
-.done:
-end
-
-# Index and payload may be the same register. Index may be clobbered.
-macro loadConstantOrVariable2Reg(index, tag, payload)
- bigteq index, FirstConstantRegisterIndex, .constant
- loadi TagOffset[cfr, index, 8], tag
- loadi PayloadOffset[cfr, index, 8], payload
- jmp .done
-.constant:
- loadp CodeBlock[cfr], tag
- loadp CodeBlock::m_constantRegisters + VectorBufferOffset[tag], tag
- # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex,
- # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3.
- lshifti 3, index
- addp index, tag
- loadp PayloadOffset[tag], payload
- loadp TagOffset[tag], tag
-.done:
-end
-
-macro loadConstantOrVariablePayloadTagCustom(index, tagCheck, payload)
- bigteq index, FirstConstantRegisterIndex, .constant
- tagCheck(TagOffset[cfr, index, 8])
- loadi PayloadOffset[cfr, index, 8], payload
- jmp .done
-.constant:
- loadp CodeBlock[cfr], payload
- loadp CodeBlock::m_constantRegisters + VectorBufferOffset[payload], payload
- # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex,
- # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3.
- tagCheck(TagOffset[payload, index, 8])
- loadp PayloadOffset[payload, index, 8], payload
-.done:
-end
-
-# Index and payload must be different registers. Index is not mutated. Use
-# this if you know what the tag of the variable should be. Doing the tag
-# test as part of loading the variable reduces register use, but may not
-# be faster than doing loadConstantOrVariable followed by a branch on the
-# tag.
-macro loadConstantOrVariablePayload(index, expectedTag, payload, slow)
- loadConstantOrVariablePayloadTagCustom(
- index,
- macro (actualTag) bineq actualTag, expectedTag, slow end,
- payload)
-end
-
-macro loadConstantOrVariablePayloadUnchecked(index, payload)
- loadConstantOrVariablePayloadTagCustom(
- index,
- macro (actualTag) end,
- payload)
-end
-
-macro writeBarrier(tag, payload)
- # Nothing to do, since we don't have a generational or incremental collector.
-end
-
-macro valueProfile(tag, payload, profile)
- if JIT_ENABLED
- storei tag, ValueProfile::m_buckets + TagOffset[profile]
- storei payload, ValueProfile::m_buckets + PayloadOffset[profile]
- end
-end
-
-
-# Indicate the beginning of LLInt.
-_llint_begin:
- crash()
-
-
-# Entrypoints into the interpreter
-
-macro functionForCallCodeBlockGetter(targetRegister)
- loadp Callee[cfr], targetRegister
- loadp JSFunction::m_executable[targetRegister], targetRegister
- loadp FunctionExecutable::m_codeBlockForCall[targetRegister], targetRegister
-end
-
-macro functionForConstructCodeBlockGetter(targetRegister)
- loadp Callee[cfr], targetRegister
- loadp JSFunction::m_executable[targetRegister], targetRegister
- loadp FunctionExecutable::m_codeBlockForConstruct[targetRegister], targetRegister
-end
-
-macro notFunctionCodeBlockGetter(targetRegister)
- loadp CodeBlock[cfr], targetRegister
-end
-
-macro functionCodeBlockSetter(sourceRegister)
- storep sourceRegister, CodeBlock[cfr]
-end
-
-macro notFunctionCodeBlockSetter(sourceRegister)
- # Nothing to do!
-end
-
-# Do the bare minimum required to execute code. Sets up the PC, leave the CodeBlock*
-# in t1. May also trigger prologue entry OSR.
-macro prologue(codeBlockGetter, codeBlockSetter, osrSlowPath, traceSlowPath)
- preserveReturnAddressAfterCall(t2)
-
- # Set up the call frame and check if we should OSR.
- storep t2, ReturnPC[cfr]
- if EXECUTION_TRACING
- callSlowPath(traceSlowPath)
- end
- codeBlockGetter(t1)
- if JIT_ENABLED
- baddis 5, CodeBlock::m_llintExecuteCounter[t1], .continue
- cCall2(osrSlowPath, cfr, PC)
- move t1, cfr
- btpz t0, .recover
- loadp ReturnPC[cfr], t2
- restoreReturnAddressBeforeReturn(t2)
- jmp t0
- .recover:
- codeBlockGetter(t1)
- .continue:
- end
- codeBlockSetter(t1)
-
- # Set up the PC.
- loadp CodeBlock::m_instructions[t1], t0
- loadp CodeBlock::Instructions::m_instructions + VectorBufferOffset[t0], PC
-end
-
-# Expects that CodeBlock is in t1, which is what prologue() leaves behind.
-# Must call dispatch(0) after calling this.
-macro functionInitialization(profileArgSkip)
- if JIT_ENABLED
- # Profile the arguments. Unfortunately, we have no choice but to do this. This
- # code is pretty horrendous because of the difference in ordering between
- # arguments and value profiles, the desire to have a simple loop-down-to-zero
- # loop, and the desire to use only three registers so as to preserve the PC and
- # the code block. It is likely that this code should be rewritten in a more
- # optimal way for architectures that have more than five registers available
- # for arbitrary use in the interpreter.
- loadi CodeBlock::m_numParameters[t1], t0
- addi -profileArgSkip, t0 # Use addi because that's what has the peephole
- assert(macro (ok) bigteq t0, 0, ok end)
- btiz t0, .argumentProfileDone
- loadp CodeBlock::m_argumentValueProfiles + VectorBufferOffset[t1], t3
- muli sizeof ValueProfile, t0, t2 # Aaaaahhhh! Need strength reduction!
- negi t0
- lshifti 3, t0
- addp t2, t3
- .argumentProfileLoop:
- loadi ThisArgumentOffset + TagOffset + 8 - profileArgSkip * 8[cfr, t0], t2
- subp sizeof ValueProfile, t3
- storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + TagOffset[t3]
- loadi ThisArgumentOffset + PayloadOffset + 8 - profileArgSkip * 8[cfr, t0], t2
- storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + PayloadOffset[t3]
- baddinz 8, t0, .argumentProfileLoop
- .argumentProfileDone:
- end
-
- # Check stack height.
- loadi CodeBlock::m_numCalleeRegisters[t1], t0
- loadp CodeBlock::m_globalData[t1], t2
- loadp JSGlobalData::interpreter[t2], t2 # FIXME: Can get to the RegisterFile from the JITStackFrame
- lshifti 3, t0
- addp t0, cfr, t0
- bpaeq Interpreter::m_registerFile + RegisterFile::m_end[t2], t0, .stackHeightOK
-
- # Stack height check failed - need to call a slow_path.
- callSlowPath(_llint_register_file_check)
-.stackHeightOK:
-end
-
-# Expects that CodeBlock is in t1, which is what prologue() leaves behind.
-macro functionArityCheck(doneLabel, slow_path)
- loadi PayloadOffset + ArgumentCount[cfr], t0
- biaeq t0, CodeBlock::m_numParameters[t1], doneLabel
- cCall2(slow_path, cfr, PC) # This slow_path has a simple protocol: t0 = 0 => no error, t0 != 0 => error
- move t1, cfr
- btiz t0, .continue
- loadp JITStackFrame::globalData[sp], t1
- loadp JSGlobalData::callFrameForThrow[t1], t0
- jmp JSGlobalData::targetMachinePCForThrow[t1]
-.continue:
- # Reload CodeBlock and PC, since the slow_path clobbered it.
- loadp CodeBlock[cfr], t1
- loadp CodeBlock::m_instructions[t1], t0
- loadp CodeBlock::Instructions::m_instructions + VectorBufferOffset[t0], PC
- jmp doneLabel
-end
-
-_llint_program_prologue:
- prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
- dispatch(0)
-
-
-_llint_eval_prologue:
- prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
- dispatch(0)
-
-
-_llint_function_for_call_prologue:
- prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call, _llint_trace_prologue_function_for_call)
-.functionForCallBegin:
- functionInitialization(0)
- dispatch(0)
-
-
-_llint_function_for_construct_prologue:
- prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct, _llint_trace_prologue_function_for_construct)
-.functionForConstructBegin:
- functionInitialization(1)
- dispatch(0)
-
-
-_llint_function_for_call_arity_check:
- prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call_arityCheck, _llint_trace_arityCheck_for_call)
- functionArityCheck(.functionForCallBegin, _llint_slow_path_call_arityCheck)
-
-
-_llint_function_for_construct_arity_check:
- prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct_arityCheck, _llint_trace_arityCheck_for_construct)
- functionArityCheck(.functionForConstructBegin, _llint_slow_path_construct_arityCheck)
-
-# Instruction implementations
-
-_llint_op_enter:
- traceExecution()
- loadp CodeBlock[cfr], t2
- loadi CodeBlock::m_numVars[t2], t2
- btiz t2, .opEnterDone
- move UndefinedTag, t0
- move 0, t1
-.opEnterLoop:
- subi 1, t2
- storei t0, TagOffset[cfr, t2, 8]
- storei t1, PayloadOffset[cfr, t2, 8]
- btinz t2, .opEnterLoop
-.opEnterDone:
- dispatch(1)
-
-
-_llint_op_create_activation:
- traceExecution()
- loadi 4[PC], t0
- bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opCreateActivationDone
- callSlowPath(_llint_slow_path_create_activation)
-.opCreateActivationDone:
- dispatch(2)
-
-
-_llint_op_init_lazy_reg:
- traceExecution()
- loadi 4[PC], t0
- storei EmptyValueTag, TagOffset[cfr, t0, 8]
- storei 0, PayloadOffset[cfr, t0, 8]
- dispatch(2)
-
-
-_llint_op_create_arguments:
- traceExecution()
- loadi 4[PC], t0
- bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opCreateArgumentsDone
- callSlowPath(_llint_slow_path_create_arguments)
-.opCreateArgumentsDone:
- dispatch(2)
-
-
-macro allocateBasicJSObject(sizeClassIndex, classInfoOffset, structure, result, scratch1, scratch2, slowCase)
- if ALWAYS_ALLOCATE_SLOW
- jmp slowCase
- else
- const offsetOfMySizeClass =
- JSGlobalData::heap +
- Heap::m_objectSpace +
- MarkedSpace::m_normalSpace +
- MarkedSpace::Subspace::preciseAllocators +
- sizeClassIndex * sizeof MarkedAllocator
-
- # FIXME: we can get the global data in one load from the stack.
- loadp CodeBlock[cfr], scratch1
- loadp CodeBlock::m_globalData[scratch1], scratch1
-
- # Get the object from the free list.
- loadp offsetOfMySizeClass + MarkedAllocator::m_firstFreeCell[scratch1], result
- btpz result, slowCase
-
- # Remove the object from the free list.
- loadp [result], scratch2
- storep scratch2, offsetOfMySizeClass + MarkedAllocator::m_firstFreeCell[scratch1]
-
- # Initialize the object.
- loadp classInfoOffset[scratch1], scratch2
- storep scratch2, [result]
- storep structure, JSCell::m_structure[result]
- storep 0, JSObject::m_inheritorID[result]
- addp sizeof JSObject, result, scratch1
- storep scratch1, JSObject::m_propertyStorage[result]
- end
-end
-
-_llint_op_create_this:
- traceExecution()
- loadi 8[PC], t0
- assertNotConstant(t0)
- bineq TagOffset[cfr, t0, 8], CellTag, .opCreateThisSlow
- loadi PayloadOffset[cfr, t0, 8], t0
- loadp JSCell::m_structure[t0], t1
- bbb Structure::m_typeInfo + TypeInfo::m_type[t1], ObjectType, .opCreateThisSlow
- loadp JSObject::m_inheritorID[t0], t2
- btpz t2, .opCreateThisSlow
- allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t2, t0, t1, t3, .opCreateThisSlow)
- loadi 4[PC], t1
- storei CellTag, TagOffset[cfr, t1, 8]
- storei t0, PayloadOffset[cfr, t1, 8]
- dispatch(3)
-
-.opCreateThisSlow:
- callSlowPath(_llint_slow_path_create_this)
- dispatch(3)
-
-
-_llint_op_get_callee:
- traceExecution()
- loadi 4[PC], t0
- loadp PayloadOffset + Callee[cfr], t1
- storei CellTag, TagOffset[cfr, t0, 8]
- storei t1, PayloadOffset[cfr, t0, 8]
- dispatch(2)
-
-
-_llint_op_convert_this:
- traceExecution()
- loadi 4[PC], t0
- bineq TagOffset[cfr, t0, 8], CellTag, .opConvertThisSlow
- loadi PayloadOffset[cfr, t0, 8], t0
- loadp JSCell::m_structure[t0], t0
- bbb Structure::m_typeInfo + TypeInfo::m_type[t0], ObjectType, .opConvertThisSlow
- dispatch(2)
-
-.opConvertThisSlow:
- callSlowPath(_llint_slow_path_convert_this)
- dispatch(2)
-
-
-_llint_op_new_object:
- traceExecution()
- loadp CodeBlock[cfr], t0
- loadp CodeBlock::m_globalObject[t0], t0
- loadp JSGlobalObject::m_emptyObjectStructure[t0], t1
- allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t1, t0, t2, t3, .opNewObjectSlow)
- loadi 4[PC], t1
- storei CellTag, TagOffset[cfr, t1, 8]
- storei t0, PayloadOffset[cfr, t1, 8]
- dispatch(2)
-
-.opNewObjectSlow:
- callSlowPath(_llint_slow_path_new_object)
- dispatch(2)
-
-
-_llint_op_new_array:
- traceExecution()
- callSlowPath(_llint_slow_path_new_array)
- dispatch(4)
-
-
-_llint_op_new_array_buffer:
- traceExecution()
- callSlowPath(_llint_slow_path_new_array_buffer)
- dispatch(4)
-
-
-_llint_op_new_regexp:
- traceExecution()
- callSlowPath(_llint_slow_path_new_regexp)
- dispatch(3)
-
-
-_llint_op_mov:
- traceExecution()
- loadi 8[PC], t1
- loadi 4[PC], t0
- loadConstantOrVariable(t1, t2, t3)
- storei t2, TagOffset[cfr, t0, 8]
- storei t3, PayloadOffset[cfr, t0, 8]
- dispatch(3)
-
-
-_llint_op_not:
- traceExecution()
- loadi 8[PC], t0
- loadi 4[PC], t1
- loadConstantOrVariable(t0, t2, t3)
- bineq t2, BooleanTag, .opNotSlow
- xori 1, t3
- storei t2, TagOffset[cfr, t1, 8]
- storei t3, PayloadOffset[cfr, t1, 8]
- dispatch(3)
-
-.opNotSlow:
- callSlowPath(_llint_slow_path_not)
- dispatch(3)
-
-
-_llint_op_eq:
- traceExecution()
- loadi 12[PC], t2
- loadi 8[PC], t0
- loadConstantOrVariable(t2, t3, t1)
- loadConstantOrVariable2Reg(t0, t2, t0)
- bineq t2, t3, .opEqSlow
- bieq t2, CellTag, .opEqSlow
- bib t2, LowestTag, .opEqSlow
- loadi 4[PC], t2
- cieq t0, t1, t0
- storei BooleanTag, TagOffset[cfr, t2, 8]
- storei t0, PayloadOffset[cfr, t2, 8]
- dispatch(4)
-
-.opEqSlow:
- callSlowPath(_llint_slow_path_eq)
- dispatch(4)
-
-
-_llint_op_eq_null:
- traceExecution()
- loadi 8[PC], t0
- loadi 4[PC], t3
- assertNotConstant(t0)
- loadi TagOffset[cfr, t0, 8], t1
- loadi PayloadOffset[cfr, t0, 8], t0
- bineq t1, CellTag, .opEqNullImmediate
- loadp JSCell::m_structure[t0], t1
- tbnz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1
- jmp .opEqNullNotImmediate
-.opEqNullImmediate:
- cieq t1, NullTag, t2
- cieq t1, UndefinedTag, t1
- ori t2, t1
-.opEqNullNotImmediate:
- storei BooleanTag, TagOffset[cfr, t3, 8]
- storei t1, PayloadOffset[cfr, t3, 8]
- dispatch(3)
-
-
-_llint_op_neq:
- traceExecution()
- loadi 12[PC], t2
- loadi 8[PC], t0
- loadConstantOrVariable(t2, t3, t1)
- loadConstantOrVariable2Reg(t0, t2, t0)
- bineq t2, t3, .opNeqSlow
- bieq t2, CellTag, .opNeqSlow
- bib t2, LowestTag, .opNeqSlow
- loadi 4[PC], t2
- cineq t0, t1, t0
- storei BooleanTag, TagOffset[cfr, t2, 8]
- storei t0, PayloadOffset[cfr, t2, 8]
- dispatch(4)
-
-.opNeqSlow:
- callSlowPath(_llint_slow_path_neq)
- dispatch(4)
-
-
-_llint_op_neq_null:
- traceExecution()
- loadi 8[PC], t0
- loadi 4[PC], t3
- assertNotConstant(t0)
- loadi TagOffset[cfr, t0, 8], t1
- loadi PayloadOffset[cfr, t0, 8], t0
- bineq t1, CellTag, .opNeqNullImmediate
- loadp JSCell::m_structure[t0], t1
- tbz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1
- jmp .opNeqNullNotImmediate
-.opNeqNullImmediate:
- cineq t1, NullTag, t2
- cineq t1, UndefinedTag, t1
- andi t2, t1
-.opNeqNullNotImmediate:
- storei BooleanTag, TagOffset[cfr, t3, 8]
- storei t1, PayloadOffset[cfr, t3, 8]
- dispatch(3)
-
-
-macro strictEq(equalityOperation, slow_path)
- loadi 12[PC], t2
- loadi 8[PC], t0
- loadConstantOrVariable(t2, t3, t1)
- loadConstantOrVariable2Reg(t0, t2, t0)
- bineq t2, t3, .slow
- bib t2, LowestTag, .slow
- bineq t2, CellTag, .notString
- loadp JSCell::m_structure[t0], t2
- loadp JSCell::m_structure[t1], t3
- bbneq Structure::m_typeInfo + TypeInfo::m_type[t2], StringType, .notString
- bbeq Structure::m_typeInfo + TypeInfo::m_type[t3], StringType, .slow
-.notString:
- loadi 4[PC], t2
- equalityOperation(t0, t1, t0)
- storei BooleanTag, TagOffset[cfr, t2, 8]
- storei t0, PayloadOffset[cfr, t2, 8]
- dispatch(4)
-
-.slow:
- callSlowPath(slow_path)
- dispatch(4)
-end
-
-_llint_op_stricteq:
- traceExecution()
- strictEq(macro (left, right, result) cieq left, right, result end, _llint_slow_path_stricteq)
-
-
-_llint_op_nstricteq:
- traceExecution()
- strictEq(macro (left, right, result) cineq left, right, result end, _llint_slow_path_nstricteq)
-
-
-_llint_op_less:
- traceExecution()
- callSlowPath(_llint_slow_path_less)
- dispatch(4)
-
-
-_llint_op_lesseq:
- traceExecution()
- callSlowPath(_llint_slow_path_lesseq)
- dispatch(4)
-
-
-_llint_op_greater:
- traceExecution()
- callSlowPath(_llint_slow_path_greater)
- dispatch(4)
-
-
-_llint_op_greatereq:
- traceExecution()
- callSlowPath(_llint_slow_path_greatereq)
- dispatch(4)
-
-
-_llint_op_pre_inc:
- traceExecution()
- loadi 4[PC], t0
- bineq TagOffset[cfr, t0, 8], Int32Tag, .opPreIncSlow
- loadi PayloadOffset[cfr, t0, 8], t1
- baddio 1, t1, .opPreIncSlow
- storei t1, PayloadOffset[cfr, t0, 8]
- dispatch(2)
-
-.opPreIncSlow:
- callSlowPath(_llint_slow_path_pre_inc)
- dispatch(2)
-
-
-_llint_op_pre_dec:
- traceExecution()
- loadi 4[PC], t0
- bineq TagOffset[cfr, t0, 8], Int32Tag, .opPreDecSlow
- loadi PayloadOffset[cfr, t0, 8], t1
- bsubio 1, t1, .opPreDecSlow
- storei t1, PayloadOffset[cfr, t0, 8]
- dispatch(2)
-
-.opPreDecSlow:
- callSlowPath(_llint_slow_path_pre_dec)
- dispatch(2)
-
-
-_llint_op_post_inc:
- traceExecution()
- loadi 8[PC], t0
- loadi 4[PC], t1
- bineq TagOffset[cfr, t0, 8], Int32Tag, .opPostIncSlow
- bieq t0, t1, .opPostIncDone
- loadi PayloadOffset[cfr, t0, 8], t2
- move t2, t3
- baddio 1, t3, .opPostIncSlow
- storei Int32Tag, TagOffset[cfr, t1, 8]
- storei t2, PayloadOffset[cfr, t1, 8]
- storei t3, PayloadOffset[cfr, t0, 8]
-.opPostIncDone:
- dispatch(3)
-
-.opPostIncSlow:
- callSlowPath(_llint_slow_path_post_inc)
- dispatch(3)
-
-
-_llint_op_post_dec:
- traceExecution()
- loadi 8[PC], t0
- loadi 4[PC], t1
- bineq TagOffset[cfr, t0, 8], Int32Tag, .opPostDecSlow
- bieq t0, t1, .opPostDecDone
- loadi PayloadOffset[cfr, t0, 8], t2
- move t2, t3
- bsubio 1, t3, .opPostDecSlow
- storei Int32Tag, TagOffset[cfr, t1, 8]
- storei t2, PayloadOffset[cfr, t1, 8]
- storei t3, PayloadOffset[cfr, t0, 8]
-.opPostDecDone:
- dispatch(3)
-
-.opPostDecSlow:
- callSlowPath(_llint_slow_path_post_dec)
- dispatch(3)
-
-
-_llint_op_to_jsnumber:
- traceExecution()
- loadi 8[PC], t0
- loadi 4[PC], t1
- loadConstantOrVariable(t0, t2, t3)
- bieq t2, Int32Tag, .opToJsnumberIsInt
- biaeq t2, EmptyValueTag, .opToJsnumberSlow
-.opToJsnumberIsInt:
- storei t2, TagOffset[cfr, t1, 8]
- storei t3, PayloadOffset[cfr, t1, 8]
- dispatch(3)
-
-.opToJsnumberSlow:
- callSlowPath(_llint_slow_path_to_jsnumber)
- dispatch(3)
-
-
-_llint_op_negate:
- traceExecution()
- loadi 8[PC], t0
- loadi 4[PC], t3
- loadConstantOrVariable(t0, t1, t2)
- bineq t1, Int32Tag, .opNegateSrcNotInt
- btiz t2, 0x7fffffff, .opNegateSlow
- negi t2
- storei Int32Tag, TagOffset[cfr, t3, 8]
- storei t2, PayloadOffset[cfr, t3, 8]
- dispatch(3)
-.opNegateSrcNotInt:
- bia t1, LowestTag, .opNegateSlow
- xori 0x80000000, t1
- storei t1, TagOffset[cfr, t3, 8]
- storei t2, PayloadOffset[cfr, t3, 8]
- dispatch(3)
-
-.opNegateSlow:
- callSlowPath(_llint_slow_path_negate)
- dispatch(3)
-
-
-macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, slow_path)
- loadi 12[PC], t2
- loadi 8[PC], t0
- loadConstantOrVariable(t2, t3, t1)
- loadConstantOrVariable2Reg(t0, t2, t0)
- bineq t2, Int32Tag, .op1NotInt
- bineq t3, Int32Tag, .op2NotInt
- loadi 4[PC], t2
- integerOperationAndStore(t3, t1, t0, .slow, t2)
- dispatch(5)
-
-.op1NotInt:
- # First operand is definitely not an int, the second operand could be anything.
- bia t2, LowestTag, .slow
- bib t3, LowestTag, .op1NotIntOp2Double
- bineq t3, Int32Tag, .slow
- ci2d t1, ft1
- jmp .op1NotIntReady
-.op1NotIntOp2Double:
- fii2d t1, t3, ft1
-.op1NotIntReady:
- loadi 4[PC], t1
- fii2d t0, t2, ft0
- doubleOperation(ft1, ft0)
- stored ft0, [cfr, t1, 8]
- dispatch(5)
-
-.op2NotInt:
- # First operand is definitely an int, the second operand is definitely not.
- loadi 4[PC], t2
- bia t3, LowestTag, .slow
- ci2d t0, ft0
- fii2d t1, t3, ft1
- doubleOperation(ft1, ft0)
- stored ft0, [cfr, t2, 8]
- dispatch(5)
-
-.slow:
- callSlowPath(slow_path)
- dispatch(5)
-end
-
-macro binaryOp(integerOperation, doubleOperation, slow_path)
- binaryOpCustomStore(
- macro (int32Tag, left, right, slow, index)
- integerOperation(left, right, slow)
- storei int32Tag, TagOffset[cfr, index, 8]
- storei right, PayloadOffset[cfr, index, 8]
- end,
- doubleOperation, slow_path)
-end
-
-_llint_op_add:
- traceExecution()
- binaryOp(
- macro (left, right, slow) baddio left, right, slow end,
- macro (left, right) addd left, right end,
- _llint_slow_path_add)
-
-
-_llint_op_mul:
- traceExecution()
- binaryOpCustomStore(
- macro (int32Tag, left, right, slow, index)
- const scratch = int32Tag # We know that we can reuse the int32Tag register since it has a constant.
- move right, scratch
- bmulio left, scratch, slow
- btinz scratch, .done
- bilt left, 0, slow
- bilt right, 0, slow
- .done:
- storei Int32Tag, TagOffset[cfr, index, 8]
- storei scratch, PayloadOffset[cfr, index, 8]
- end,
- macro (left, right) muld left, right end,
- _llint_slow_path_mul)
-
-
-_llint_op_sub:
- traceExecution()
- binaryOp(
- macro (left, right, slow) bsubio left, right, slow end,
- macro (left, right) subd left, right end,
- _llint_slow_path_sub)
-
-
-_llint_op_div:
- traceExecution()
- binaryOpCustomStore(
- macro (int32Tag, left, right, slow, index)
- ci2d left, ft0
- ci2d right, ft1
- divd ft0, ft1
- bcd2i ft1, right, .notInt
- storei int32Tag, TagOffset[cfr, index, 8]
- storei right, PayloadOffset[cfr, index, 8]
- jmp .done
- .notInt:
- stored ft1, [cfr, index, 8]
- .done:
- end,
- macro (left, right) divd left, right end,
- _llint_slow_path_div)
-
-
-_llint_op_mod:
- traceExecution()
- callSlowPath(_llint_slow_path_mod)
- dispatch(4)
-
-
-macro bitOp(operation, slow_path, advance)
- loadi 12[PC], t2
- loadi 8[PC], t0
- loadConstantOrVariable(t2, t3, t1)
- loadConstantOrVariable2Reg(t0, t2, t0)
- bineq t3, Int32Tag, .slow
- bineq t2, Int32Tag, .slow
- loadi 4[PC], t2
- operation(t1, t0, .slow)
- storei t3, TagOffset[cfr, t2, 8]
- storei t0, PayloadOffset[cfr, t2, 8]
- dispatch(advance)
-
-.slow:
- callSlowPath(slow_path)
- dispatch(advance)
-end
-
-_llint_op_lshift:
- traceExecution()
- bitOp(
- macro (left, right, slow) lshifti left, right end,
- _llint_slow_path_lshift,
- 4)
-
-
-_llint_op_rshift:
- traceExecution()
- bitOp(
- macro (left, right, slow) rshifti left, right end,
- _llint_slow_path_rshift,
- 4)
-
-
-_llint_op_urshift:
- traceExecution()
- bitOp(
- macro (left, right, slow)
- urshifti left, right
- bilt right, 0, slow
- end,
- _llint_slow_path_urshift,
- 4)
-
-
-_llint_op_bitand:
- traceExecution()
- bitOp(
- macro (left, right, slow) andi left, right end,
- _llint_slow_path_bitand,
- 5)
-
-
-_llint_op_bitxor:
- traceExecution()
- bitOp(
- macro (left, right, slow) xori left, right end,
- _llint_slow_path_bitxor,
- 5)
-
-
-_llint_op_bitor:
- traceExecution()
- bitOp(
- macro (left, right, slow) ori left, right end,
- _llint_slow_path_bitor,
- 5)
-
-
-_llint_op_bitnot:
- traceExecution()
- loadi 8[PC], t1
- loadi 4[PC], t0
- loadConstantOrVariable(t1, t2, t3)
- bineq t2, Int32Tag, .opBitnotSlow
- noti t3
- storei t2, TagOffset[cfr, t0, 8]
- storei t3, PayloadOffset[cfr, t0, 8]
- dispatch(3)
-
-.opBitnotSlow:
- callSlowPath(_llint_slow_path_bitnot)
- dispatch(3)
-
-
-_llint_op_check_has_instance:
- traceExecution()
- loadi 4[PC], t1
- loadConstantOrVariablePayload(t1, CellTag, t0, .opCheckHasInstanceSlow)
- loadp JSCell::m_structure[t0], t0
- btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsHasInstance, .opCheckHasInstanceSlow
- dispatch(2)
-
-.opCheckHasInstanceSlow:
- callSlowPath(_llint_slow_path_check_has_instance)
- dispatch(2)
-
-
-_llint_op_instanceof:
- traceExecution()
- # Check that baseVal implements the default HasInstance behavior.
- # FIXME: This should be deprecated.
- loadi 12[PC], t1
- loadConstantOrVariablePayloadUnchecked(t1, t0)
- loadp JSCell::m_structure[t0], t0
- btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsDefaultHasInstance, .opInstanceofSlow
-
- # Actually do the work.
- loadi 16[PC], t0
- loadi 4[PC], t3
- loadConstantOrVariablePayload(t0, CellTag, t1, .opInstanceofSlow)
- loadp JSCell::m_structure[t1], t2
- bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opInstanceofSlow
- loadi 8[PC], t0
- loadConstantOrVariablePayload(t0, CellTag, t2, .opInstanceofSlow)
-
- # Register state: t1 = prototype, t2 = value
- move 1, t0
-.opInstanceofLoop:
- loadp JSCell::m_structure[t2], t2
- loadi Structure::m_prototype + PayloadOffset[t2], t2
- bpeq t2, t1, .opInstanceofDone
- btinz t2, .opInstanceofLoop
-
- move 0, t0
-.opInstanceofDone:
- storei BooleanTag, TagOffset[cfr, t3, 8]
- storei t0, PayloadOffset[cfr, t3, 8]
- dispatch(5)
-
-.opInstanceofSlow:
- callSlowPath(_llint_slow_path_instanceof)
- dispatch(5)
-
-
-_llint_op_typeof:
- traceExecution()
- callSlowPath(_llint_slow_path_typeof)
- dispatch(3)
-
-
-_llint_op_is_undefined:
- traceExecution()
- callSlowPath(_llint_slow_path_is_undefined)
- dispatch(3)
-
-
-_llint_op_is_boolean:
- traceExecution()
- callSlowPath(_llint_slow_path_is_boolean)
- dispatch(3)
-
-
-_llint_op_is_number:
- traceExecution()
- callSlowPath(_llint_slow_path_is_number)
- dispatch(3)
-
-
-_llint_op_is_string:
- traceExecution()
- callSlowPath(_llint_slow_path_is_string)
- dispatch(3)
-
-
-_llint_op_is_object:
- traceExecution()
- callSlowPath(_llint_slow_path_is_object)
- dispatch(3)
-
-
-_llint_op_is_function:
- traceExecution()
- callSlowPath(_llint_slow_path_is_function)
- dispatch(3)
-
-
-_llint_op_in:
- traceExecution()
- callSlowPath(_llint_slow_path_in)
- dispatch(4)
-
-
-_llint_op_resolve:
- traceExecution()
- callSlowPath(_llint_slow_path_resolve)
- dispatch(4)
-
-
-_llint_op_resolve_skip:
- traceExecution()
- callSlowPath(_llint_slow_path_resolve_skip)
- dispatch(5)
-
-
-macro resolveGlobal(size, slow)
- # Operands are as follows:
- # 4[PC] Destination for the load.
- # 8[PC] Property identifier index in the code block.
- # 12[PC] Structure pointer, initialized to 0 by bytecode generator.
- # 16[PC] Offset in global object, initialized to 0 by bytecode generator.
- loadp CodeBlock[cfr], t0
- loadp CodeBlock::m_globalObject[t0], t0
- loadp JSCell::m_structure[t0], t1
- bpneq t1, 12[PC], slow
- loadi 16[PC], t1
- loadp JSObject::m_propertyStorage[t0], t0
- loadi TagOffset[t0, t1, 8], t2
- loadi PayloadOffset[t0, t1, 8], t3
- loadi 4[PC], t0
- storei t2, TagOffset[cfr, t0, 8]
- storei t3, PayloadOffset[cfr, t0, 8]
- loadi (size - 1) * 4[PC], t0
- valueProfile(t2, t3, t0)
-end
-
-_llint_op_resolve_global:
- traceExecution()
- resolveGlobal(6, .opResolveGlobalSlow)
- dispatch(6)
-
-.opResolveGlobalSlow:
- callSlowPath(_llint_slow_path_resolve_global)
- dispatch(6)
-
-
-# Gives you the scope in t0, while allowing you to optionally perform additional checks on the
-# scopes as they are traversed. scopeCheck() is called with two arguments: the register
-# holding the scope, and a register that can be used for scratch. Note that this does not
-# use t3, so you can hold stuff in t3 if need be.
-macro getScope(deBruijinIndexOperand, scopeCheck)
- loadp ScopeChain + PayloadOffset[cfr], t0
- loadi deBruijinIndexOperand, t2
-
- btiz t2, .done
-
- loadp CodeBlock[cfr], t1
- bineq CodeBlock::m_codeType[t1], FunctionCode, .loop
- btbz CodeBlock::m_needsFullScopeChain[t1], .loop
-
- loadi CodeBlock::m_activationRegister[t1], t1
-
- # Need to conditionally skip over one scope.
- bieq TagOffset[cfr, t1, 8], EmptyValueTag, .noActivation
- scopeCheck(t0, t1)
- loadp ScopeChainNode::next[t0], t0
-.noActivation:
- subi 1, t2
-
- btiz t2, .done
-.loop:
- scopeCheck(t0, t1)
- loadp ScopeChainNode::next[t0], t0
- subi 1, t2
- btinz t2, .loop
-
-.done:
-end
-
-_llint_op_resolve_global_dynamic:
- traceExecution()
- loadp JITStackFrame::globalData[sp], t3
- loadp JSGlobalData::activationStructure[t3], t3
- getScope(
- 20[PC],
- macro (scope, scratch)
- loadp ScopeChainNode::object[scope], scratch
- bpneq JSCell::m_structure[scratch], t3, .opResolveGlobalDynamicSuperSlow
- end)
- resolveGlobal(7, .opResolveGlobalDynamicSlow)
- dispatch(7)
-
-.opResolveGlobalDynamicSuperSlow:
- callSlowPath(_llint_slow_path_resolve_for_resolve_global_dynamic)
- dispatch(7)
-
-.opResolveGlobalDynamicSlow:
- callSlowPath(_llint_slow_path_resolve_global_dynamic)
- dispatch(7)
-
-
-_llint_op_get_scoped_var:
- traceExecution()
- # Operands are as follows:
- # 4[PC] Destination for the load.
- # 8[PC] Index of register in the scope.
- # 12[PC] De Bruijin index.
- getScope(12[PC], macro (scope, scratch) end)
- loadi 4[PC], t1
- loadi 8[PC], t2
- loadp ScopeChainNode::object[t0], t0
- loadp JSVariableObject::m_registers[t0], t0
- loadi TagOffset[t0, t2, 8], t3
- loadi PayloadOffset[t0, t2, 8], t0
- storei t3, TagOffset[cfr, t1, 8]
- storei t0, PayloadOffset[cfr, t1, 8]
- loadi 16[PC], t1
- valueProfile(t3, t0, t1)
- dispatch(5)
-
-
-_llint_op_put_scoped_var:
- traceExecution()
- getScope(8[PC], macro (scope, scratch) end)
- loadi 12[PC], t1
- loadConstantOrVariable(t1, t3, t2)
- loadi 4[PC], t1
- writeBarrier(t3, t2)
- loadp ScopeChainNode::object[t0], t0
- loadp JSVariableObject::m_registers[t0], t0
- storei t3, TagOffset[t0, t1, 8]
- storei t2, PayloadOffset[t0, t1, 8]
- dispatch(4)
-
-
-_llint_op_get_global_var:
- traceExecution()
- loadi 8[PC], t1
- loadi 4[PC], t3
- loadp CodeBlock[cfr], t0
- loadp CodeBlock::m_globalObject[t0], t0
- loadp JSGlobalObject::m_registers[t0], t0
- loadi TagOffset[t0, t1, 8], t2
- loadi PayloadOffset[t0, t1, 8], t1
- storei t2, TagOffset[cfr, t3, 8]
- storei t1, PayloadOffset[cfr, t3, 8]
- loadi 12[PC], t3
- valueProfile(t2, t1, t3)
- dispatch(4)
-
-
-_llint_op_put_global_var:
- traceExecution()
- loadi 8[PC], t1
- loadp CodeBlock[cfr], t0
- loadp CodeBlock::m_globalObject[t0], t0
- loadp JSGlobalObject::m_registers[t0], t0
- loadConstantOrVariable(t1, t2, t3)
- loadi 4[PC], t1
- writeBarrier(t2, t3)
- storei t2, TagOffset[t0, t1, 8]
- storei t3, PayloadOffset[t0, t1, 8]
- dispatch(3)
-
-
-_llint_op_resolve_base:
- traceExecution()
- callSlowPath(_llint_slow_path_resolve_base)
- dispatch(5)
-
-
-_llint_op_ensure_property_exists:
- traceExecution()
- callSlowPath(_llint_slow_path_ensure_property_exists)
- dispatch(3)
-
-
-_llint_op_resolve_with_base:
- traceExecution()
- callSlowPath(_llint_slow_path_resolve_with_base)
- dispatch(5)
-
-
-_llint_op_resolve_with_this:
- traceExecution()
- callSlowPath(_llint_slow_path_resolve_with_this)
- dispatch(5)
-
-
-_llint_op_get_by_id:
- traceExecution()
- # We only do monomorphic get_by_id caching for now, and we do not modify the
- # opcode. We do, however, allow for the cache to change anytime if fails, since
- # ping-ponging is free. At best we get lucky and the get_by_id will continue
- # to take fast path on the new cache. At worst we take slow path, which is what
- # we would have been doing anyway.
- loadi 8[PC], t0
- loadi 16[PC], t1
- loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdSlow)
- loadi 20[PC], t2
- loadp JSObject::m_propertyStorage[t3], t0
- bpneq JSCell::m_structure[t3], t1, .opGetByIdSlow
- loadi 4[PC], t1
- loadi TagOffset[t0, t2], t3
- loadi PayloadOffset[t0, t2], t2
- storei t3, TagOffset[cfr, t1, 8]
- storei t2, PayloadOffset[cfr, t1, 8]
- loadi 32[PC], t1
- valueProfile(t3, t2, t1)
- dispatch(9)
-
-.opGetByIdSlow:
- callSlowPath(_llint_slow_path_get_by_id)
- dispatch(9)
-
-
-_llint_op_get_arguments_length:
- traceExecution()
- loadi 8[PC], t0
- loadi 4[PC], t1
- bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opGetArgumentsLengthSlow
- loadi ArgumentCount + PayloadOffset[cfr], t2
- subi 1, t2
- storei Int32Tag, TagOffset[cfr, t1, 8]
- storei t2, PayloadOffset[cfr, t1, 8]
- dispatch(4)
-
-.opGetArgumentsLengthSlow:
- callSlowPath(_llint_slow_path_get_arguments_length)
- dispatch(4)
-
-
-_llint_op_put_by_id:
- traceExecution()
- loadi 4[PC], t3
- loadi 16[PC], t1
- loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow)
- loadi 12[PC], t2
- loadp JSObject::m_propertyStorage[t0], t3
- bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow
- loadi 20[PC], t1
- loadConstantOrVariable2Reg(t2, t0, t2)
- writeBarrier(t0, t2)
- storei t0, TagOffset[t3, t1]
- storei t2, PayloadOffset[t3, t1]
- dispatch(9)
-
-.opPutByIdSlow:
- callSlowPath(_llint_slow_path_put_by_id)
- dispatch(9)
-
-
-macro putByIdTransition(additionalChecks)
- traceExecution()
- loadi 4[PC], t3
- loadi 16[PC], t1
- loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow)
- loadi 12[PC], t2
- bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow
- additionalChecks(t1, t3, .opPutByIdSlow)
- loadi 20[PC], t1
- loadp JSObject::m_propertyStorage[t0], t3
- addp t1, t3
- loadConstantOrVariable2Reg(t2, t1, t2)
- writeBarrier(t1, t2)
- storei t1, TagOffset[t3]
- loadi 24[PC], t1
- storei t2, PayloadOffset[t3]
- storep t1, JSCell::m_structure[t0]
- dispatch(9)
-end
-
-_llint_op_put_by_id_transition_direct:
- putByIdTransition(macro (oldStructure, scratch, slow) end)
-
-
-_llint_op_put_by_id_transition_normal:
- putByIdTransition(
- macro (oldStructure, scratch, slow)
- const protoCell = oldStructure # Reusing the oldStructure register for the proto
-
- loadp 28[PC], scratch
- assert(macro (ok) btpnz scratch, ok end)
- loadp StructureChain::m_vector[scratch], scratch
- assert(macro (ok) btpnz scratch, ok end)
- bieq Structure::m_prototype + TagOffset[oldStructure], NullTag, .done
- .loop:
- loadi Structure::m_prototype + PayloadOffset[oldStructure], protoCell
- loadp JSCell::m_structure[protoCell], oldStructure
- bpneq oldStructure, [scratch], slow
- addp 4, scratch
- bineq Structure::m_prototype + TagOffset[oldStructure], NullTag, .loop
- .done:
- end)
-
-
-_llint_op_del_by_id:
- traceExecution()
- callSlowPath(_llint_slow_path_del_by_id)
- dispatch(4)
-
-
-_llint_op_get_by_val:
- traceExecution()
- loadp CodeBlock[cfr], t1
- loadi 8[PC], t2
- loadi 12[PC], t3
- loadp CodeBlock::m_globalData[t1], t1
- loadConstantOrVariablePayload(t2, CellTag, t0, .opGetByValSlow)
- loadp JSGlobalData::jsArrayClassInfo[t1], t2
- loadConstantOrVariablePayload(t3, Int32Tag, t1, .opGetByValSlow)
- bpneq [t0], t2, .opGetByValSlow
- loadp JSArray::m_storage[t0], t3
- biaeq t1, JSArray::m_vectorLength[t0], .opGetByValSlow
- loadi 4[PC], t0
- loadi ArrayStorage::m_vector + TagOffset[t3, t1, 8], t2
- loadi ArrayStorage::m_vector + PayloadOffset[t3, t1, 8], t1
- bieq t2, EmptyValueTag, .opGetByValSlow
- storei t2, TagOffset[cfr, t0, 8]
- storei t1, PayloadOffset[cfr, t0, 8]
- loadi 16[PC], t0
- valueProfile(t2, t1, t0)
- dispatch(5)
-
-.opGetByValSlow:
- callSlowPath(_llint_slow_path_get_by_val)
- dispatch(5)
-
-
-_llint_op_get_argument_by_val:
- traceExecution()
- loadi 8[PC], t0
- loadi 12[PC], t1
- bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opGetArgumentByValSlow
- loadConstantOrVariablePayload(t1, Int32Tag, t2, .opGetArgumentByValSlow)
- addi 1, t2
- loadi ArgumentCount + PayloadOffset[cfr], t1
- biaeq t2, t1, .opGetArgumentByValSlow
- negi t2
- loadi 4[PC], t3
- loadi ThisArgumentOffset + TagOffset[cfr, t2, 8], t0
- loadi ThisArgumentOffset + PayloadOffset[cfr, t2, 8], t1
- storei t0, TagOffset[cfr, t3, 8]
- storei t1, PayloadOffset[cfr, t3, 8]
- dispatch(5)
-
-.opGetArgumentByValSlow:
- callSlowPath(_llint_slow_path_get_argument_by_val)
- dispatch(5)
-
-
-_llint_op_get_by_pname:
- traceExecution()
- loadi 12[PC], t0
- loadConstantOrVariablePayload(t0, CellTag, t1, .opGetByPnameSlow)
- loadi 16[PC], t0
- bpneq t1, PayloadOffset[cfr, t0, 8], .opGetByPnameSlow
- loadi 8[PC], t0
- loadConstantOrVariablePayload(t0, CellTag, t2, .opGetByPnameSlow)
- loadi 20[PC], t0
- loadi PayloadOffset[cfr, t0, 8], t3
- loadp JSCell::m_structure[t2], t0
- bpneq t0, JSPropertyNameIterator::m_cachedStructure[t3], .opGetByPnameSlow
- loadi 24[PC], t0
- loadi [cfr, t0, 8], t0
- subi 1, t0
- biaeq t0, JSPropertyNameIterator::m_numCacheableSlots[t3], .opGetByPnameSlow
- loadp JSObject::m_propertyStorage[t2], t2
- loadi TagOffset[t2, t0, 8], t1
- loadi PayloadOffset[t2, t0, 8], t3
- loadi 4[PC], t0
- storei t1, TagOffset[cfr, t0, 8]
- storei t3, PayloadOffset[cfr, t0, 8]
- dispatch(7)
-
-.opGetByPnameSlow:
- callSlowPath(_llint_slow_path_get_by_pname)
- dispatch(7)
-
-
-_llint_op_put_by_val:
- traceExecution()
- loadi 4[PC], t0
- loadConstantOrVariablePayload(t0, CellTag, t1, .opPutByValSlow)
- loadi 8[PC], t0
- loadConstantOrVariablePayload(t0, Int32Tag, t2, .opPutByValSlow)
- loadp CodeBlock[cfr], t0
- loadp CodeBlock::m_globalData[t0], t0
- loadp JSGlobalData::jsArrayClassInfo[t0], t0
- bpneq [t1], t0, .opPutByValSlow
- biaeq t2, JSArray::m_vectorLength[t1], .opPutByValSlow
- loadp JSArray::m_storage[t1], t0
- bieq ArrayStorage::m_vector + TagOffset[t0, t2, 8], EmptyValueTag, .opPutByValEmpty
-.opPutByValStoreResult:
- loadi 12[PC], t3
- loadConstantOrVariable2Reg(t3, t1, t3)
- writeBarrier(t1, t3)
- storei t1, ArrayStorage::m_vector + TagOffset[t0, t2, 8]
- storei t3, ArrayStorage::m_vector + PayloadOffset[t0, t2, 8]
- dispatch(4)
-
-.opPutByValEmpty:
- addi 1, ArrayStorage::m_numValuesInVector[t0]
- bib t2, ArrayStorage::m_length[t0], .opPutByValStoreResult
- addi 1, t2, t1
- storei t1, ArrayStorage::m_length[t0]
- jmp .opPutByValStoreResult
-
-.opPutByValSlow:
- callSlowPath(_llint_slow_path_put_by_val)
- dispatch(4)
-
-
-_llint_op_del_by_val:
- traceExecution()
- callSlowPath(_llint_slow_path_del_by_val)
- dispatch(4)
-
-
-_llint_op_put_by_index:
- traceExecution()
- callSlowPath(_llint_slow_path_put_by_index)
- dispatch(4)
-
-
-_llint_op_put_getter_setter:
- traceExecution()
- callSlowPath(_llint_slow_path_put_getter_setter)
- dispatch(5)
-
-
-_llint_op_loop:
- nop
-_llint_op_jmp:
- traceExecution()
- dispatchBranch(4[PC])
-
-
-_llint_op_jmp_scopes:
- traceExecution()
- callSlowPath(_llint_slow_path_jmp_scopes)
- dispatch(0)
-
-
-macro jumpTrueOrFalse(conditionOp, slow)
- loadi 4[PC], t1
- loadConstantOrVariablePayload(t1, BooleanTag, t0, .slow)
- conditionOp(t0, .target)
- dispatch(3)
-
-.target:
- dispatchBranch(8[PC])
-
-.slow:
- callSlowPath(slow)
- dispatch(0)
-end
-
-_llint_op_loop_if_true:
- nop
-_llint_op_jtrue:
- traceExecution()
- jumpTrueOrFalse(
- macro (value, target) btinz value, target end,
- _llint_slow_path_jtrue)
-
-
-_llint_op_loop_if_false:
- nop
-_llint_op_jfalse:
- traceExecution()
- jumpTrueOrFalse(
- macro (value, target) btiz value, target end,
- _llint_slow_path_jfalse)
-
-
-macro equalNull(cellHandler, immediateHandler)
- loadi 4[PC], t0
- loadi TagOffset[cfr, t0, 8], t1
- loadi PayloadOffset[cfr, t0, 8], t0
- bineq t1, CellTag, .immediate
- loadp JSCell::m_structure[t0], t2
- cellHandler(Structure::m_typeInfo + TypeInfo::m_flags[t2], .target)
- dispatch(3)
-
-.target:
- dispatchBranch(8[PC])
-
-.immediate:
- ori 1, t1
- immediateHandler(t1, .target)
- dispatch(3)
-end
-
-_llint_op_jeq_null:
- traceExecution()
- equalNull(
- macro (value, target) btbnz value, MasqueradesAsUndefined, target end,
- macro (value, target) bieq value, NullTag, target end)
-
-
-_llint_op_jneq_null:
- traceExecution()
- equalNull(
- macro (value, target) btbz value, MasqueradesAsUndefined, target end,
- macro (value, target) bineq value, NullTag, target end)
-
-
-_llint_op_jneq_ptr:
- traceExecution()
- loadi 4[PC], t0
- loadi 8[PC], t1
- bineq TagOffset[cfr, t0, 8], CellTag, .opJneqPtrBranch
- bpeq PayloadOffset[cfr, t0, 8], t1, .opJneqPtrFallThrough
-.opJneqPtrBranch:
- dispatchBranch(12[PC])
-.opJneqPtrFallThrough:
- dispatch(4)
-
-
-macro compare(integerCompare, doubleCompare, slow_path)
- loadi 4[PC], t2
- loadi 8[PC], t3
- loadConstantOrVariable(t2, t0, t1)
- loadConstantOrVariable2Reg(t3, t2, t3)
- bineq t0, Int32Tag, .op1NotInt
- bineq t2, Int32Tag, .op2NotInt
- integerCompare(t1, t3, .jumpTarget)
- dispatch(4)
-
-.op1NotInt:
- bia t0, LowestTag, .slow
- bib t2, LowestTag, .op1NotIntOp2Double
- bineq t2, Int32Tag, .slow
- ci2d t3, ft1
- jmp .op1NotIntReady
-.op1NotIntOp2Double:
- fii2d t3, t2, ft1
-.op1NotIntReady:
- fii2d t1, t0, ft0
- doubleCompare(ft0, ft1, .jumpTarget)
- dispatch(4)
-
-.op2NotInt:
- ci2d t1, ft0
- bia t2, LowestTag, .slow
- fii2d t3, t2, ft1
- doubleCompare(ft0, ft1, .jumpTarget)
- dispatch(4)
-
-.jumpTarget:
- dispatchBranch(12[PC])
-
-.slow:
- callSlowPath(slow_path)
- dispatch(0)
-end
-
-_llint_op_loop_if_less:
- nop
-_llint_op_jless:
- traceExecution()
- compare(
- macro (left, right, target) bilt left, right, target end,
- macro (left, right, target) bdlt left, right, target end,
- _llint_slow_path_jless)
-
-
-_llint_op_jnless:
- traceExecution()
- compare(
- macro (left, right, target) bigteq left, right, target end,
- macro (left, right, target) bdgtequn left, right, target end,
- _llint_slow_path_jnless)
-
-
-_llint_op_loop_if_greater:
- nop
-_llint_op_jgreater:
- traceExecution()
- compare(
- macro (left, right, target) bigt left, right, target end,
- macro (left, right, target) bdgt left, right, target end,
- _llint_slow_path_jgreater)
-
-
-_llint_op_jngreater:
- traceExecution()
- compare(
- macro (left, right, target) bilteq left, right, target end,
- macro (left, right, target) bdltequn left, right, target end,
- _llint_slow_path_jngreater)
-
-
-_llint_op_loop_if_lesseq:
- nop
-_llint_op_jlesseq:
- traceExecution()
- compare(
- macro (left, right, target) bilteq left, right, target end,
- macro (left, right, target) bdlteq left, right, target end,
- _llint_slow_path_jlesseq)
-
-
-_llint_op_jnlesseq:
- traceExecution()
- compare(
- macro (left, right, target) bigt left, right, target end,
- macro (left, right, target) bdgtun left, right, target end,
- _llint_slow_path_jnlesseq)
-
-
-_llint_op_loop_if_greatereq:
- nop
-_llint_op_jgreatereq:
- traceExecution()
- compare(
- macro (left, right, target) bigteq left, right, target end,
- macro (left, right, target) bdgteq left, right, target end,
- _llint_slow_path_jgreatereq)
-
-
-_llint_op_jngreatereq:
- traceExecution()
- compare(
- macro (left, right, target) bilt left, right, target end,
- macro (left, right, target) bdltun left, right, target end,
- _llint_slow_path_jngreatereq)
-
-
-_llint_op_loop_hint:
- traceExecution()
- checkSwitchToJITForLoop()
- dispatch(1)
-
-
-_llint_op_switch_imm:
- traceExecution()
- loadi 12[PC], t2
- loadi 4[PC], t3
- loadConstantOrVariable(t2, t1, t0)
- loadp CodeBlock[cfr], t2
- loadp CodeBlock::m_rareData[t2], t2
- muli sizeof SimpleJumpTable, t3 # FIXME: would be nice to peephole this!
- loadp CodeBlock::RareData::m_immediateSwitchJumpTables + VectorBufferOffset[t2], t2
- addp t3, t2
- bineq t1, Int32Tag, .opSwitchImmNotInt
- subi SimpleJumpTable::min[t2], t0
- biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchImmFallThrough
- loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t3
- loadi [t3, t0, 4], t1
- btiz t1, .opSwitchImmFallThrough
- dispatchBranchWithOffset(t1)
-
-.opSwitchImmNotInt:
- bib t1, LowestTag, .opSwitchImmSlow # Go to slow path if it's a double.
-.opSwitchImmFallThrough:
- dispatchBranch(8[PC])
-
-.opSwitchImmSlow:
- callSlowPath(_llint_slow_path_switch_imm)
- dispatch(0)
-
-
-_llint_op_switch_char:
- traceExecution()
- loadi 12[PC], t2
- loadi 4[PC], t3
- loadConstantOrVariable(t2, t1, t0)
- loadp CodeBlock[cfr], t2
- loadp CodeBlock::m_rareData[t2], t2
- muli sizeof SimpleJumpTable, t3
- loadp CodeBlock::RareData::m_characterSwitchJumpTables + VectorBufferOffset[t2], t2
- addp t3, t2
- bineq t1, CellTag, .opSwitchCharFallThrough
- loadp JSCell::m_structure[t0], t1
- bbneq Structure::m_typeInfo + TypeInfo::m_type[t1], StringType, .opSwitchCharFallThrough
- loadp JSString::m_value[t0], t0
- bineq StringImpl::m_length[t0], 1, .opSwitchCharFallThrough
- loadp StringImpl::m_data8[t0], t1
- btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit
- loadh [t1], t0
- jmp .opSwitchCharReady
-.opSwitchChar8Bit:
- loadb [t1], t0
-.opSwitchCharReady:
- subi SimpleJumpTable::min[t2], t0
- biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchCharFallThrough
- loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t2
- loadi [t2, t0, 4], t1
- btiz t1, .opSwitchImmFallThrough
- dispatchBranchWithOffset(t1)
-
-.opSwitchCharFallThrough:
- dispatchBranch(8[PC])
-
-
-_llint_op_switch_string:
- traceExecution()
- callSlowPath(_llint_slow_path_switch_string)
- dispatch(0)
-
-
-_llint_op_new_func:
- traceExecution()
- btiz 12[PC], .opNewFuncUnchecked
- loadi 4[PC], t1
- bineq TagOffset[cfr, t1, 8], EmptyValueTag, .opNewFuncDone
-.opNewFuncUnchecked:
- callSlowPath(_llint_slow_path_new_func)
-.opNewFuncDone:
- dispatch(4)
-
-
-_llint_op_new_func_exp:
- traceExecution()
- callSlowPath(_llint_slow_path_new_func_exp)
- dispatch(3)
-
-
-macro doCall(slow_path)
- loadi 4[PC], t0
- loadi 16[PC], t1
- loadp LLIntCallLinkInfo::callee[t1], t2
- loadConstantOrVariablePayload(t0, CellTag, t3, .opCallSlow)
- bineq t3, t2, .opCallSlow
- loadi 12[PC], t3
- addp 24, PC
- lshifti 3, t3
- addp cfr, t3 # t3 contains the new value of cfr
- loadp JSFunction::m_scopeChain[t2], t0
- storei t2, Callee + PayloadOffset[t3]
- storei t0, ScopeChain + PayloadOffset[t3]
- loadi 8 - 24[PC], t2
- storei PC, ArgumentCount + TagOffset[cfr]
- storep cfr, CallerFrame[t3]
- storei t2, ArgumentCount + PayloadOffset[t3]
- storei CellTag, Callee + TagOffset[t3]
- storei CellTag, ScopeChain + TagOffset[t3]
- move t3, cfr
- call LLIntCallLinkInfo::machineCodeTarget[t1]
- dispatchAfterCall()
-
-.opCallSlow:
- slowPathForCall(6, slow_path)
-end
-
-_llint_op_call:
- traceExecution()
- doCall(_llint_slow_path_call)
-
-
-_llint_op_construct:
- traceExecution()
- doCall(_llint_slow_path_construct)
-
-
-_llint_op_call_varargs:
- traceExecution()
- slowPathForCall(6, _llint_slow_path_call_varargs)
-
-
-_llint_op_call_eval:
- traceExecution()
-
- # Eval is executed in one of two modes:
- #
- # 1) We find that we're really invoking eval() in which case the
- # execution is perfomed entirely inside the slow_path, and it
- # returns the PC of a function that just returns the return value
- # that the eval returned.
- #
- # 2) We find that we're invoking something called eval() that is not
- # the real eval. Then the slow_path returns the PC of the thing to
- # call, and we call it.
- #
- # This allows us to handle two cases, which would require a total of
- # up to four pieces of state that cannot be easily packed into two
- # registers (C functions can return up to two registers, easily):
- #
- # - The call frame register. This may or may not have been modified
- # by the slow_path, but the convention is that it returns it. It's not
- # totally clear if that's necessary, since the cfr is callee save.
- # But that's our style in this here interpreter so we stick with it.
- #
- # - A bit to say if the slow_path successfully executed the eval and has
- # the return value, or did not execute the eval but has a PC for us
- # to call.
- #
- # - Either:
- # - The JS return value (two registers), or
- #
- # - The PC to call.
- #
- # It turns out to be easier to just always have this return the cfr
- # and a PC to call, and that PC may be a dummy thunk that just
- # returns the JS value that the eval returned.
-
- slowPathForCall(4, _llint_slow_path_call_eval)
-
-
-_llint_generic_return_point:
- dispatchAfterCall()
-
-
-_llint_op_tear_off_activation:
- traceExecution()
- loadi 4[PC], t0
- loadi 8[PC], t1
- bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opTearOffActivationCreated
- bieq TagOffset[cfr, t1, 8], EmptyValueTag, .opTearOffActivationNotCreated
-.opTearOffActivationCreated:
- callSlowPath(_llint_slow_path_tear_off_activation)
-.opTearOffActivationNotCreated:
- dispatch(3)
-
-
-_llint_op_tear_off_arguments:
- traceExecution()
- loadi 4[PC], t0
- subi 1, t0 # Get the unmodifiedArgumentsRegister
- bieq TagOffset[cfr, t0, 8], EmptyValueTag, .opTearOffArgumentsNotCreated
- callSlowPath(_llint_slow_path_tear_off_arguments)
-.opTearOffArgumentsNotCreated:
- dispatch(2)
-
-
-macro doReturn()
- loadp ReturnPC[cfr], t2
- loadp CallerFrame[cfr], cfr
- restoreReturnAddressBeforeReturn(t2)
- ret
-end
-
-_llint_op_ret:
- traceExecution()
- checkSwitchToJITForEpilogue()
- loadi 4[PC], t2
- loadConstantOrVariable(t2, t1, t0)
- doReturn()
-
-
-_llint_op_call_put_result:
- loadi 4[PC], t2
- loadi 8[PC], t3
- storei t1, TagOffset[cfr, t2, 8]
- storei t0, PayloadOffset[cfr, t2, 8]
- valueProfile(t1, t0, t3)
- traceExecution() # Needs to be here because it would clobber t1, t0
- dispatch(3)
-
-
-_llint_op_ret_object_or_this:
- traceExecution()
- checkSwitchToJITForEpilogue()
- loadi 4[PC], t2
- loadConstantOrVariable(t2, t1, t0)
- bineq t1, CellTag, .opRetObjectOrThisNotObject
- loadp JSCell::m_structure[t0], t2
- bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opRetObjectOrThisNotObject
- doReturn()
-
-.opRetObjectOrThisNotObject:
- loadi 8[PC], t2
- loadConstantOrVariable(t2, t1, t0)
- doReturn()
-
-
-_llint_op_method_check:
- traceExecution()
- # We ignore method checks and use normal get_by_id optimizations.
- dispatch(1)
-
-
-_llint_op_strcat:
- traceExecution()
- callSlowPath(_llint_slow_path_strcat)
- dispatch(4)
-
-
-_llint_op_to_primitive:
- traceExecution()
- loadi 8[PC], t2
- loadi 4[PC], t3
- loadConstantOrVariable(t2, t1, t0)
- bineq t1, CellTag, .opToPrimitiveIsImm
- loadp JSCell::m_structure[t0], t2
- bbneq Structure::m_typeInfo + TypeInfo::m_type[t2], StringType, .opToPrimitiveSlowCase
-.opToPrimitiveIsImm:
- storei t1, TagOffset[cfr, t3, 8]
- storei t0, PayloadOffset[cfr, t3, 8]
- dispatch(3)
-
-.opToPrimitiveSlowCase:
- callSlowPath(_llint_slow_path_to_primitive)
- dispatch(3)
-
-
-_llint_op_get_pnames:
- traceExecution()
- callSlowPath(_llint_slow_path_get_pnames)
- dispatch(0) # The slow_path either advances the PC or jumps us to somewhere else.
-
-
-_llint_op_next_pname:
- traceExecution()
- loadi 12[PC], t1
- loadi 16[PC], t2
- loadi PayloadOffset[cfr, t1, 8], t0
- bieq t0, PayloadOffset[cfr, t2, 8], .opNextPnameEnd
- loadi 20[PC], t2
- loadi PayloadOffset[cfr, t2, 8], t2
- loadp JSPropertyNameIterator::m_jsStrings[t2], t3
- loadi [t3, t0, 8], t3
- addi 1, t0
- storei t0, PayloadOffset[cfr, t1, 8]
- loadi 4[PC], t1
- storei CellTag, TagOffset[cfr, t1, 8]
- storei t3, PayloadOffset[cfr, t1, 8]
- loadi 8[PC], t3
- loadi PayloadOffset[cfr, t3, 8], t3
- loadp JSCell::m_structure[t3], t1
- bpneq t1, JSPropertyNameIterator::m_cachedStructure[t2], .opNextPnameSlow
- loadp JSPropertyNameIterator::m_cachedPrototypeChain[t2], t0
- loadp StructureChain::m_vector[t0], t0
- btpz [t0], .opNextPnameTarget
-.opNextPnameCheckPrototypeLoop:
- bieq Structure::m_prototype + TagOffset[t1], NullTag, .opNextPnameSlow
- loadp Structure::m_prototype + PayloadOffset[t1], t2
- loadp JSCell::m_structure[t2], t1
- bpneq t1, [t0], .opNextPnameSlow
- addp 4, t0
- btpnz [t0], .opNextPnameCheckPrototypeLoop
-.opNextPnameTarget:
- dispatchBranch(24[PC])
-
-.opNextPnameEnd:
- dispatch(7)
-
-.opNextPnameSlow:
- callSlowPath(_llint_slow_path_next_pname) # This either keeps the PC where it was (causing us to loop) or sets it to target.
- dispatch(0)
-
-
-_llint_op_push_scope:
- traceExecution()
- callSlowPath(_llint_slow_path_push_scope)
- dispatch(2)
-
-
-_llint_op_pop_scope:
- traceExecution()
- callSlowPath(_llint_slow_path_pop_scope)
- dispatch(1)
-
-
-_llint_op_push_new_scope:
- traceExecution()
- callSlowPath(_llint_slow_path_push_new_scope)
- dispatch(4)
-
-
-_llint_op_catch:
- # This is where we end up from the JIT's throw trampoline (because the
- # machine code return address will be set to _llint_op_catch), and from
- # the interpreter's throw trampoline (see _llint_throw_trampoline).
- # The JIT throwing protocol calls for the cfr to be in t0. The throwing
- # code must have known that we were throwing to the interpreter, and have
- # set JSGlobalData::targetInterpreterPCForThrow.
- move t0, cfr
- loadp JITStackFrame::globalData[sp], t3
- loadi JSGlobalData::targetInterpreterPCForThrow[t3], PC
- loadi JSGlobalData::exception + PayloadOffset[t3], t0
- loadi JSGlobalData::exception + TagOffset[t3], t1
- storei 0, JSGlobalData::exception + PayloadOffset[t3]
- storei EmptyValueTag, JSGlobalData::exception + TagOffset[t3]
- loadi 4[PC], t2
- storei t0, PayloadOffset[cfr, t2, 8]
- storei t1, TagOffset[cfr, t2, 8]
- traceExecution() # This needs to be here because we don't want to clobber t0, t1, t2, t3 above.
- dispatch(2)
-
-
-_llint_op_throw:
- traceExecution()
- callSlowPath(_llint_slow_path_throw)
- dispatch(2)
-
-
-_llint_op_throw_reference_error:
- traceExecution()
- callSlowPath(_llint_slow_path_throw_reference_error)
- dispatch(2)
-
-
-_llint_op_jsr:
- traceExecution()
- loadi 4[PC], t0
- addi 3 * 4, PC, t1
- storei t1, [cfr, t0, 8]
- dispatchBranch(8[PC])
-
-
-_llint_op_sret:
- traceExecution()
- loadi 4[PC], t0
- loadp [cfr, t0, 8], PC
- dispatch(0)
-
-
-_llint_op_debug:
- traceExecution()
- callSlowPath(_llint_slow_path_debug)
- dispatch(4)
-
-
-_llint_op_profile_will_call:
- traceExecution()
- loadp JITStackFrame::enabledProfilerReference[sp], t0
- btpz [t0], .opProfileWillCallDone
- callSlowPath(_llint_slow_path_profile_will_call)
-.opProfileWillCallDone:
- dispatch(2)
-
-
-_llint_op_profile_did_call:
- traceExecution()
- loadp JITStackFrame::enabledProfilerReference[sp], t0
- btpz [t0], .opProfileWillCallDone
- callSlowPath(_llint_slow_path_profile_did_call)
-.opProfileDidCallDone:
- dispatch(2)
-
-
-_llint_op_end:
- traceExecution()
- checkSwitchToJITForEpilogue()
- loadi 4[PC], t0
- loadi TagOffset[cfr, t0, 8], t1
- loadi PayloadOffset[cfr, t0, 8], t0
- doReturn()
-
-
-_llint_throw_from_slow_path_trampoline:
- # When throwing from the interpreter (i.e. throwing from LLIntSlowPaths), so
- # the throw target is not necessarily interpreted code, we come to here.
- # This essentially emulates the JIT's throwing protocol.
- loadp JITStackFrame::globalData[sp], t1
- loadp JSGlobalData::callFrameForThrow[t1], t0
- jmp JSGlobalData::targetMachinePCForThrow[t1]
-
-
-_llint_throw_during_call_trampoline:
- preserveReturnAddressAfterCall(t2)
- loadp JITStackFrame::globalData[sp], t1
- loadp JSGlobalData::callFrameForThrow[t1], t0
- jmp JSGlobalData::targetMachinePCForThrow[t1]
-
-
-# Lastly, make sure that we can link even though we don't support all opcodes.
-# These opcodes should never arise when using LLInt or either JIT. We assert
-# as much.
-
-macro notSupported()
- if ASSERT_ENABLED
- crash()
- else
- # We should use whatever the smallest possible instruction is, just to
- # ensure that there is a gap between instruction labels. If multiple
- # smallest instructions exist, we should pick the one that is most
- # likely result in execution being halted. Currently that is the break
- # instruction on all architectures we're interested in. (Break is int3
- # on Intel, which is 1 byte, and bkpt on ARMv7, which is 2 bytes.)
- break
- end
-end
-
-_llint_op_get_array_length:
- notSupported()
-
-_llint_op_get_by_id_chain:
- notSupported()
-
-_llint_op_get_by_id_custom_chain:
- notSupported()
-
-_llint_op_get_by_id_custom_proto:
- notSupported()
-
-_llint_op_get_by_id_custom_self:
- notSupported()
-
-_llint_op_get_by_id_generic:
- notSupported()
-
-_llint_op_get_by_id_getter_chain:
- notSupported()
-
-_llint_op_get_by_id_getter_proto:
- notSupported()
-
-_llint_op_get_by_id_getter_self:
- notSupported()
-
-_llint_op_get_by_id_proto:
- notSupported()
-
-_llint_op_get_by_id_self:
- notSupported()
-
-_llint_op_get_string_length:
- notSupported()
-
-_llint_op_put_by_id_generic:
- notSupported()
-
-_llint_op_put_by_id_replace:
- notSupported()
-
-_llint_op_put_by_id_transition:
- notSupported()
-
-
-# Indicate the end of LLInt.
-_llint_end:
- crash()
-
+++ /dev/null
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "LowLevelInterpreter.h"
-
-#if ENABLE(LLINT)
-
-#include "LLIntOfflineAsmConfig.h"
-#include <wtf/InlineASM.h>
-
-// This is a file generated by offlineasm, which contains all of the assembly code
-// for the interpreter, as compiled from LowLevelInterpreter.asm.
-#include "LLIntAssembly.h"
-
-#endif // ENABLE(LLINT)
+++ /dev/null
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef LowLevelInterpreter_h
-#define LowLevelInterpreter_h
-
-#include <wtf/Platform.h>
-
-#if ENABLE(LLINT)
-
-#include "Opcode.h"
-
-#define LLINT_INSTRUCTION_DECL(opcode, length) extern "C" void llint_##opcode();
- FOR_EACH_OPCODE_ID(LLINT_INSTRUCTION_DECL);
-#undef LLINT_INSTRUCTION_DECL
-
-extern "C" void llint_begin();
-extern "C" void llint_end();
-extern "C" void llint_program_prologue();
-extern "C" void llint_eval_prologue();
-extern "C" void llint_function_for_call_prologue();
-extern "C" void llint_function_for_construct_prologue();
-extern "C" void llint_function_for_call_arity_check();
-extern "C" void llint_function_for_construct_arity_check();
-extern "C" void llint_generic_return_point();
-extern "C" void llint_throw_from_slow_path_trampoline();
-extern "C" void llint_throw_during_call_trampoline();
-
-#endif // ENABLE(LLINT)
-
-#endif // LowLevelInterpreter_h
+++ /dev/null
-# Copyright (C) 2011 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
-# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-# THE POSSIBILITY OF SUCH DAMAGE.
-
-require "ast"
-require "opt"
-
-class Node
- def armV7Single
- doubleOperand = armV7Operand
- raise "Bogus register name #{doubleOperand}" unless doubleOperand =~ /^d/
- "s" + ($~.post_match.to_i * 2).to_s
- end
-end
-
-class SpecialRegister < NoChildren
- def initialize(name)
- @name = name
- end
-
- def armV7Operand
- @name
- end
-
- def address?
- false
- end
-
- def label?
- false
- end
-
- def immediate?
- false
- end
-
- def register?
- true
- end
-end
-
-ARMv7_EXTRA_GPRS = [SpecialRegister.new("r9"), SpecialRegister.new("r8"), SpecialRegister.new("r3")]
-ARMv7_EXTRA_FPRS = [SpecialRegister.new("d7")]
-ARMv7_SCRATCH_FPR = SpecialRegister.new("d8")
-
-def armV7MoveImmediate(value, register)
- # Currently we only handle the simple cases, and fall back to mov/movt for the complex ones.
- if value >= 0 && value < 256
- $asm.puts "movw #{register.armV7Operand}, \##{value}"
- elsif (~value) >= 0 && (~value) < 256
- $asm.puts "mvn #{register.armV7Operand}, \##{~value}"
- else
- $asm.puts "movw #{register.armV7Operand}, \##{value & 0xffff}"
- if (value & 0xffff0000) != 0
- $asm.puts "movt #{register.armV7Operand}, \##{value >> 16}"
- end
- end
-end
-
-class RegisterID
- def armV7Operand
- case name
- when "t0", "a0", "r0"
- "r0"
- when "t1", "a1", "r1"
- "r1"
- when "t2", "a2"
- "r2"
- when "a3"
- "r3"
- when "t3"
- "r4"
- when "t4"
- "r7"
- when "cfr"
- "r5"
- when "lr"
- "lr"
- when "sp"
- "sp"
- else
- raise "Bad register #{name} for ARMv7 at #{codeOriginString}"
- end
- end
-end
-
-class FPRegisterID
- def armV7Operand
- case name
- when "ft0", "fr"
- "d0"
- when "ft1"
- "d1"
- when "ft2"
- "d2"
- when "ft3"
- "d3"
- when "ft4"
- "d4"
- when "ft5"
- "d5"
- else
- raise "Bad register #{name} for ARMv7 at #{codeOriginString}"
- end
- end
-end
-
-class Immediate
- def armV7Operand
- raise "Invalid immediate #{value} at #{codeOriginString}" if value < 0 or value > 255
- "\##{value}"
- end
-end
-
-class Address
- def armV7Operand
- raise "Bad offset at #{codeOriginString}" if offset.value < -0xff or offset.value > 0xfff
- "[#{base.armV7Operand}, \##{offset.value}]"
- end
-end
-
-class BaseIndex
- def armV7Operand
- raise "Bad offset at #{codeOriginString}" if offset.value != 0
- "[#{base.armV7Operand}, #{index.armV7Operand}, lsl \##{scaleShift}]"
- end
-end
-
-class AbsoluteAddress
- def armV7Operand
- raise "Unconverted absolute address at #{codeOriginString}"
- end
-end
-
-#
-# Lowering of branch ops. For example:
-#
-# baddiz foo, bar, baz
-#
-# will become:
-#
-# addi foo, bar
-# bz baz
-#
-
-def armV7LowerBranchOps(list)
- newList = []
- list.each {
- | node |
- if node.is_a? Instruction
- case node.opcode
- when /^b(addi|subi|ori|addp)/
- op = $1
- branch = "b" + $~.post_match
-
- case op
- when "addi", "addp"
- op = "addis"
- when "subi"
- op = "subis"
- when "ori"
- op = "oris"
- end
-
- newList << Instruction.new(node.codeOrigin, op, node.operands[0..-2])
- newList << Instruction.new(node.codeOrigin, branch, [node.operands[-1]])
- when "bmulio"
- tmp1 = Tmp.new(node.codeOrigin, :gpr)
- tmp2 = Tmp.new(node.codeOrigin, :gpr)
- newList << Instruction.new(node.codeOrigin, "smulli", [node.operands[0], node.operands[1], node.operands[1], tmp1])
- newList << Instruction.new(node.codeOrigin, "rshifti", [node.operands[-2], Immediate.new(node.codeOrigin, 31), tmp2])
- newList << Instruction.new(node.codeOrigin, "bineq", [tmp1, tmp2, node.operands[-1]])
- when /^bmuli/
- condition = $~.post_match
- newList << Instruction.new(node.codeOrigin, "muli", node.operands[0..-2])
- newList << Instruction.new(node.codeOrigin, "bti" + condition, [node.operands[-2], node.operands[-1]])
- else
- newList << node
- end
- else
- newList << node
- end
- }
- newList
-end
-
-#
-# Lowering of shift ops. For example:
-#
-# lshifti foo, bar
-#
-# will become:
-#
-# andi foo, 31, tmp
-# lshifti tmp, bar
-#
-
-def armV7SanitizeShift(operand, list)
- return operand if operand.immediate?
-
- tmp = Tmp.new(operand.codeOrigin, :gpr)
- list << Instruction.new(operand.codeOrigin, "andi", [operand, Immediate.new(operand.codeOrigin, 31), tmp])
- tmp
-end
-
-def armV7LowerShiftOps(list)
- newList = []
- list.each {
- | node |
- if node.is_a? Instruction
- case node.opcode
- when "lshifti", "rshifti", "urshifti"
- if node.operands.size == 2
- newList << Instruction.new(node.codeOrigin, node.opcode, [armV7SanitizeShift(node.operands[0], newList), node.operands[1]])
- else
- newList << Instruction.new(node.codeOrigin, node.opcode, [node.operands[0], armV7SanitizeShift(node.operands[1], newList), node.operands[2]])
- raise "Wrong number of operands for shift at #{node.codeOriginString}" unless node.operands.size == 3
- end
- else
- newList << node
- end
- else
- newList << node
- end
- }
- newList
-end
-
-#
-# Lowering of malformed addresses. For example:
-#
-# loadp 10000[foo], bar
-#
-# will become:
-#
-# move 10000, tmp
-# addp foo, tmp
-# loadp 0[tmp], bar
-#
-
-class Node
- def armV7LowerMalformedAddressesRecurse(list)
- mapChildren {
- | node |
- node.armV7LowerMalformedAddressesRecurse(list)
- }
- end
-end
-
-class Address
- def armV7LowerMalformedAddressesRecurse(list)
- if offset.value < -0xff or offset.value > 0xfff
- tmp = Tmp.new(codeOrigin, :gpr)
- list << Instruction.new(codeOrigin, "move", [offset, tmp])
- list << Instruction.new(codeOrigin, "addp", [base, tmp])
- Address.new(codeOrigin, tmp, Immediate.new(codeOrigin, 0))
- else
- self
- end
- end
-end
-
-class BaseIndex
- def armV7LowerMalformedAddressesRecurse(list)
- if offset.value != 0
- tmp = Tmp.new(codeOrigin, :gpr)
- list << Instruction.new(codeOrigin, "move", [offset, tmp])
- list << Instruction.new(codeOrigin, "addp", [base, tmp])
- BaseIndex.new(codeOrigin, tmp, index, scale, Immediate.new(codeOrigin, 0))
- else
- self
- end
- end
-end
-
-class AbsoluteAddress
- def armV7LowerMalformedAddressesRecurse(list)
- tmp = Tmp.new(codeOrigin, :gpr)
- list << Instruction.new(codeOrigin, "move", [address, tmp])
- Address.new(codeOrigin, tmp, Immediate.new(codeOrigin, 0))
- end
-end
-
-def armV7LowerMalformedAddresses(list)
- newList = []
- list.each {
- | node |
- newList << node.armV7LowerMalformedAddressesRecurse(newList)
- }
- newList
-end
-
-#
-# Lowering of malformed addresses in double loads and stores. For example:
-#
-# loadd [foo, bar, 8], baz
-#
-# becomes:
-#
-# leap [foo, bar, 8], tmp
-# loadd [tmp], baz
-#
-
-class Node
- def armV7DoubleAddress(list)
- self
- end
-end
-
-class BaseIndex
- def armV7DoubleAddress(list)
- tmp = Tmp.new(codeOrigin, :gpr)
- list << Instruction.new(codeOrigin, "leap", [self, tmp])
- Address.new(codeOrigin, tmp, Immediate.new(codeOrigin, 0))
- end
-end
-
-def armV7LowerMalformedAddressesDouble(list)
- newList = []
- list.each {
- | node |
- if node.is_a? Instruction
- case node.opcode
- when "loadd"
- newList << Instruction.new(node.codeOrigin, "loadd", [node.operands[0].armV7DoubleAddress(newList), node.operands[1]])
- when "stored"
- newList << Instruction.new(node.codeOrigin, "stored", [node.operands[0], node.operands[1].armV7DoubleAddress(newList)])
- else
- newList << node
- end
- else
- newList << node
- end
- }
- newList
-end
-
-#
-# Lowering of misplaced immediates. For example:
-#
-# storei 0, [foo]
-#
-# will become:
-#
-# move 0, tmp
-# storei tmp, [foo]
-#
-
-def armV7LowerMisplacedImmediates(list)
- newList = []
- list.each {
- | node |
- if node.is_a? Instruction
- case node.opcode
- when "storei", "storep"
- operands = node.operands
- newOperands = []
- operands.each {
- | operand |
- if operand.is_a? Immediate
- tmp = Tmp.new(operand.codeOrigin, :gpr)
- newList << Instruction.new(operand.codeOrigin, "move", [operand, tmp])
- newOperands << tmp
- else
- newOperands << operand
- end
- }
- newList << Instruction.new(node.codeOrigin, node.opcode, newOperands)
- else
- newList << node
- end
- else
- newList << node
- end
- }
- newList
-end
-
-#
-# Lowering of malformed immediates except when used in a "move" instruction.
-# For example:
-#
-# addp 642641, foo
-#
-# will become:
-#
-# move 642641, tmp
-# addp tmp, foo
-#
-
-class Node
- def armV7LowerMalformedImmediatesRecurse(list)
- mapChildren {
- | node |
- node.armV7LowerMalformedImmediatesRecurse(list)
- }
- end
-end
-
-class Address
- def armV7LowerMalformedImmediatesRecurse(list)
- self
- end
-end
-
-class BaseIndex
- def armV7LowerMalformedImmediatesRecurse(list)
- self
- end
-end
-
-class AbsoluteAddress
- def armV7LowerMalformedImmediatesRecurse(list)
- self
- end
-end
-
-class Immediate
- def armV7LowerMalformedImmediatesRecurse(list)
- if value < 0 or value > 255
- tmp = Tmp.new(codeOrigin, :gpr)
- list << Instruction.new(codeOrigin, "move", [self, tmp])
- tmp
- else
- self
- end
- end
-end
-
-def armV7LowerMalformedImmediates(list)
- newList = []
- list.each {
- | node |
- if node.is_a? Instruction
- case node.opcode
- when "move"
- newList << node
- when "addi", "addp", "addis", "subi", "subp", "subis"
- if node.operands[0].is_a? Immediate and
- node.operands[0].value < 0 and
- node.operands[0].value >= 255 and
- node.operands.size == 2
- if node.opcode =~ /add/
- newOpcode = "sub" + node.opcode[-1..-1]
- else
- newOpcode = "add" + node.opcode[-1..-1]
- end
- newList << Instruction.new(node.codeOrigin, newOpcode,
- [Immediate.new(-node.operands[0].value)] + node.operands[1..-1])
- else
- newList << node.armV7LowerMalformedImmediatesRecurse(newList)
- end
- when "muli"
- if node.operands[0].is_a? Immediate
- tmp = Tmp.new(codeOrigin, :gpr)
- newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp])
- newList << Instruction.new(node.codeOrigin, "muli", [tmp] + node.operands[1..-1])
- else
- newList << node.armV7LowerMalformedImmediatesRecurse(newList)
- end
- else
- newList << node.armV7LowerMalformedImmediatesRecurse(newList)
- end
- else
- newList << node
- end
- }
- newList
-end
-
-#
-# Lowering of misplaced addresses. For example:
-#
-# addi foo, [bar]
-#
-# will become:
-#
-# loadi [bar], tmp
-# addi foo, tmp
-# storei tmp, [bar]
-#
-# Another example:
-#
-# addi [foo], bar
-#
-# will become:
-#
-# loadi [foo], tmp
-# addi tmp, bar
-#
-
-def armV7AsRegister(preList, postList, operand, suffix, needStore)
- return operand unless operand.address?
-
- tmp = Tmp.new(operand.codeOrigin, if suffix == "d" then :fpr else :gpr end)
- preList << Instruction.new(operand.codeOrigin, "load" + suffix, [operand, tmp])
- if needStore
- postList << Instruction.new(operand.codeOrigin, "store" + suffix, [tmp, operand])
- end
- tmp
-end
-
-def armV7AsRegisters(preList, postList, operands, suffix)
- newOperands = []
- operands.each_with_index {
- | operand, index |
- newOperands << armV7AsRegister(preList, postList, operand, suffix, index == operands.size - 1)
- }
- newOperands
-end
-
-def armV7LowerMisplacedAddresses(list)
- newList = []
- list.each {
- | node |
- if node.is_a? Instruction
- postInstructions = []
- case node.opcode
- when "addi", "addp", "addis", "andi", "andp", "lshifti", "muli", "negi", "noti", "ori", "oris",
- "orp", "rshifti", "urshifti", "subi", "subp", "subis", "xori", "xorp", /^bi/, /^bp/, /^bti/,
- /^btp/, /^ci/, /^cp/, /^ti/
- newList << Instruction.new(node.codeOrigin,
- node.opcode,
- armV7AsRegisters(newList, postInstructions, node.operands, "i"))
- when "bbeq", "bbneq", "bba", "bbaeq", "bbb", "bbbeq", "btbo", "btbz", "btbnz", "tbz", "tbnz",
- "tbo"
- newList << Instruction.new(node.codeOrigin,
- node.opcode,
- armV7AsRegisters(newList, postInstructions, node.operands, "b"))
- when "bbgt", "bbgteq", "bblt", "bblteq", "btbs", "tbs"
- newList << Instruction.new(node.codeOrigin,
- node.opcode,
- armV7AsRegisters(newList, postInstructions, node.operands, "bs"))
- when "addd", "divd", "subd", "muld", "sqrtd", /^bd/
- newList << Instruction.new(node.codeOrigin,
- node.opcode,
- armV7AsRegisters(newList, postInstructions, node.operands, "d"))
- when "jmp", "call"
- newList << Instruction.new(node.codeOrigin,
- node.opcode,
- [armV7AsRegister(newList, postInstructions, node.operands[0], "p", false)])
- else
- newList << node
- end
- newList += postInstructions
- else
- newList << node
- end
- }
- newList
-end
-
-#
-# Lowering of register reuse in compare instructions. For example:
-#
-# cieq t0, t1, t0
-#
-# will become:
-#
-# mov tmp, t0
-# cieq tmp, t1, t0
-#
-
-def armV7LowerRegisterReuse(list)
- newList = []
- list.each {
- | node |
- if node.is_a? Instruction
- case node.opcode
- when "cieq", "cineq", "cia", "ciaeq", "cib", "cibeq", "cigt", "cigteq", "cilt", "cilteq",
- "cpeq", "cpneq", "cpa", "cpaeq", "cpb", "cpbeq", "cpgt", "cpgteq", "cplt", "cplteq",
- "tio", "tis", "tiz", "tinz", "tbo", "tbs", "tbz", "tbnz"
- if node.operands.size == 2
- if node.operands[0] == node.operands[1]
- tmp = Tmp.new(node.codeOrigin, :gpr)
- newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp])
- newList << Instruction.new(node.codeOrigin, node.opcode, [tmp, node.operands[1]])
- else
- newList << node
- end
- else
- raise "Wrong number of arguments at #{node.codeOriginString}" unless node.operands.size == 3
- if node.operands[0] == node.operands[2]
- tmp = Tmp.new(node.codeOrigin, :gpr)
- newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp])
- newList << Instruction.new(node.codeOrigin, node.opcode, [tmp, node.operands[1], node.operands[2]])
- elsif node.operands[1] == node.operands[2]
- tmp = Tmp.new(node.codeOrigin, :gpr)
- newList << Instruction.new(node.codeOrigin, "move", [node.operands[1], tmp])
- newList << Instruction.new(node.codeOrigin, node.opcode, [node.operands[0], tmp, node.operands[2]])
- else
- newList << node
- end
- end
- else
- newList << node
- end
- else
- newList << node
- end
- }
- newList
-end
-
-#
-# Lea support.
-#
-
-class Address
- def armV7EmitLea(destination)
- if destination == base
- $asm.puts "adds #{destination.armV7Operand}, \##{offset.value}"
- else
- $asm.puts "adds #{destination.armV7Operand}, #{base.armV7Operand}, \##{offset.value}"
- end
- end
-end
-
-class BaseIndex
- def armV7EmitLea(destination)
- raise "Malformed BaseIndex, offset should be zero at #{codeOriginString}" unless offset.value == 0
- $asm.puts "add.w #{destination.armV7Operand}, #{base.armV7Operand}, #{index.armV7Operand}, lsl \##{scaleShift}"
- end
-end
-
-# FIXME: we could support AbsoluteAddress for lea, but we don't.
-
-#
-# Actual lowering code follows.
-#
-
-class Sequence
- def lowerARMv7
- myList = @list
-
- # Verify that we will only see instructions and labels.
- myList.each {
- | node |
- unless node.is_a? Instruction or
- node.is_a? Label or
- node.is_a? LocalLabel or
- node.is_a? Skip
- raise "Unexpected #{node.inspect} at #{node.codeOrigin}"
- end
- }
-
- myList = armV7LowerBranchOps(myList)
- myList = armV7LowerShiftOps(myList)
- myList = armV7LowerMalformedAddresses(myList)
- myList = armV7LowerMalformedAddressesDouble(myList)
- myList = armV7LowerMisplacedImmediates(myList)
- myList = armV7LowerMalformedImmediates(myList)
- myList = armV7LowerMisplacedAddresses(myList)
- myList = armV7LowerRegisterReuse(myList)
- myList = assignRegistersToTemporaries(myList, :gpr, ARMv7_EXTRA_GPRS)
- myList = assignRegistersToTemporaries(myList, :fpr, ARMv7_EXTRA_FPRS)
- myList.each {
- | node |
- node.lower("ARMv7")
- }
- end
-end
-
-def armV7Operands(operands)
- operands.map{|v| v.armV7Operand}.join(", ")
-end
-
-def armV7FlippedOperands(operands)
- armV7Operands([operands[-1]] + operands[0..-2])
-end
-
-def emitArmV7Compact(opcode2, opcode3, operands)
- if operands.size == 3
- $asm.puts "#{opcode3} #{armV7FlippedOperands(operands)}"
- else
- raise unless operands.size == 2
- raise unless operands[1].is_a? RegisterID
- if operands[0].is_a? Immediate
- $asm.puts "#{opcode3} #{operands[1].armV7Operand}, #{operands[1].armV7Operand}, #{operands[0].armV7Operand}"
- else
- $asm.puts "#{opcode2} #{armV7FlippedOperands(operands)}"
- end
- end
-end
-
-def emitArmV7(opcode, operands)
- if operands.size == 3
- $asm.puts "#{opcode} #{armV7FlippedOperands(operands)}"
- else
- raise unless operands.size == 2
- $asm.puts "#{opcode} #{operands[1].armV7Operand}, #{operands[1].armV7Operand}, #{operands[0].armV7Operand}"
- end
-end
-
-def emitArmV7DoubleBranch(branchOpcode, operands)
- $asm.puts "vcmpe.f64 #{armV7Operands(operands[0..1])}"
- $asm.puts "vmrs apsr_nzcv, fpscr"
- $asm.puts "#{branchOpcode} #{operands[2].asmLabel}"
-end
-
-def emitArmV7Test(operands)
- value = operands[0]
- case operands.size
- when 2
- mask = Immediate.new(codeOrigin, -1)
- when 3
- mask = operands[1]
- else
- raise "Expected 2 or 3 operands but got #{operands.size} at #{codeOriginString}"
- end
-
- if mask.is_a? Immediate and mask.value == -1
- $asm.puts "tst #{value.armV7Operand}, #{value.armV7Operand}"
- elsif mask.is_a? Immediate
- $asm.puts "tst.w #{value.armV7Operand}, #{mask.armV7Operand}"
- else
- $asm.puts "tst #{value.armV7Operand}, #{mask.armV7Operand}"
- end
-end
-
-def emitArmV7Compare(operands, code)
- $asm.puts "movs #{operands[2].armV7Operand}, \#0"
- $asm.puts "cmp #{operands[0].armV7Operand}, #{operands[1].armV7Operand}"
- $asm.puts "it #{code}"
- $asm.puts "mov#{code} #{operands[2].armV7Operand}, \#1"
-end
-
-def emitArmV7TestSet(operands, code)
- $asm.puts "movs #{operands[-1].armV7Operand}, \#0"
- emitArmV7Test(operands)
- $asm.puts "it #{code}"
- $asm.puts "mov#{code} #{operands[-1].armV7Operand}, \#1"
-end
-
-class Instruction
- def lowerARMv7
- $asm.comment codeOriginString
- case opcode
- when "addi", "addp", "addis"
- if opcode == "addis"
- suffix = "s"
- else
- suffix = ""
- end
- if operands.size == 3 and operands[0].is_a? Immediate
- raise unless operands[1].is_a? RegisterID
- raise unless operands[2].is_a? RegisterID
- if operands[0].value == 0 and suffix.empty?
- unless operands[1] == operands[2]
- $asm.puts "mov #{operands[2].armV7Operand}, #{operands[1].armV7Operand}"
- end
- else
- $asm.puts "adds #{operands[2].armV7Operand}, #{operands[1].armV7Operand}, #{operands[0].armV7Operand}"
- end
- elsif operands.size == 3 and operands[0].is_a? RegisterID
- raise unless operands[1].is_a? RegisterID
- raise unless operands[2].is_a? RegisterID
- $asm.puts "adds #{armV7FlippedOperands(operands)}"
- else
- if operands[0].is_a? Immediate
- unless Immediate.new(nil, 0) == operands[0]
- $asm.puts "adds #{armV7FlippedOperands(operands)}"
- end
- else
- $asm.puts "add#{suffix} #{armV7FlippedOperands(operands)}"
- end
- end
- when "andi", "andp"
- emitArmV7Compact("ands", "and", operands)
- when "ori", "orp"
- emitArmV7Compact("orrs", "orr", operands)
- when "oris"
- emitArmV7Compact("orrs", "orrs", operands)
- when "xori", "xorp"
- emitArmV7Compact("eors", "eor", operands)
- when "lshifti"
- emitArmV7Compact("lsls", "lsls", operands)
- when "rshifti"
- emitArmV7Compact("asrs", "asrs", operands)
- when "urshifti"
- emitArmV7Compact("lsrs", "lsrs", operands)
- when "muli"
- if operands.size == 2 or operands[0] == operands[2] or operands[1] == operands[2]
- emitArmV7("muls", operands)
- else
- $asm.puts "mov #{operands[2].armV7Operand}, #{operands[0].armV7Operand}"
- $asm.puts "muls #{operands[2].armV7Operand}, #{operands[2].armV7Operand}, #{operands[1].armV7Operand}"
- end
- when "subi", "subp", "subis"
- emitArmV7Compact("subs", "subs", operands)
- when "negi"
- $asm.puts "rsbs #{operands[0].armV7Operand}, #{operands[0].armV7Operand}, \#0"
- when "noti"
- $asm.puts "mvns #{operands[0].armV7Operand}, #{operands[0].armV7Operand}"
- when "loadi", "loadp"
- $asm.puts "ldr #{armV7FlippedOperands(operands)}"
- when "storei", "storep"
- $asm.puts "str #{armV7Operands(operands)}"
- when "loadb"
- $asm.puts "ldrb #{armV7FlippedOperands(operands)}"
- when "loadbs"
- $asm.puts "ldrsb.w #{armV7FlippedOperands(operands)}"
- when "storeb"
- $asm.puts "strb #{armV7Operands(operands)}"
- when "loadh"
- $asm.puts "ldrh #{armV7FlippedOperands(operands)}"
- when "loadhs"
- $asm.puts "ldrsh.w #{armV7FlippedOperands(operands)}"
- when "storeh"
- $asm.puts "strh #{armV7Operands(operands)}"
- when "loadd"
- $asm.puts "vldr.64 #{armV7FlippedOperands(operands)}"
- when "stored"
- $asm.puts "vstr.64 #{armV7Operands(operands)}"
- when "addd"
- emitArmV7("vadd.f64", operands)
- when "divd"
- emitArmV7("vdiv.f64", operands)
- when "subd"
- emitArmV7("vsub.f64", operands)
- when "muld"
- emitArmV7("vmul.f64", operands)
- when "sqrtd"
- $asm.puts "vsqrt.f64 #{armV7FlippedOperands(operands)}"
- when "ci2d"
- $asm.puts "vmov #{operands[1].armV7Single}, #{operands[0].armV7Operand}"
- $asm.puts "vcvt.f64.s32 #{operands[1].armV7Operand}, #{operands[1].armV7Single}"
- when "bdeq"
- emitArmV7DoubleBranch("beq", operands)
- when "bdneq"
- $asm.puts "vcmpe.f64 #{armV7Operands(operands[0..1])}"
- $asm.puts "vmrs apsr_nzcv, fpscr"
- isUnordered = LocalLabel.unique("bdneq")
- $asm.puts "bvs #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
- $asm.puts "bne #{operands[2].asmLabel}"
- isUnordered.lower("ARMv7")
- when "bdgt"
- emitArmV7DoubleBranch("bgt", operands)
- when "bdgteq"
- emitArmV7DoubleBranch("bge", operands)
- when "bdlt"
- emitArmV7DoubleBranch("bmi", operands)
- when "bdlteq"
- emitArmV7DoubleBranch("bls", operands)
- when "bdequn"
- $asm.puts "vcmpe.f64 #{armV7Operands(operands[0..1])}"
- $asm.puts "vmrs apsr_nzcv, fpscr"
- $asm.puts "bvs #{operands[2].asmLabel}"
- $asm.puts "beq #{operands[2].asmLabel}"
- when "bdnequn"
- emitArmV7DoubleBranch("bne", operands)
- when "bdgtun"
- emitArmV7DoubleBranch("bhi", operands)
- when "bdgtequn"
- emitArmV7DoubleBranch("bpl", operands)
- when "bdltun"
- emitArmV7DoubleBranch("blt", operands)
- when "bdltequn"
- emitArmV7DoubleBranch("ble", operands)
- when "btd2i"
- # FIXME: may be a good idea to just get rid of this instruction, since the interpreter
- # currently does not use it.
- raise "ARMv7 does not support this opcode yet, #{codeOrigin}"
- when "td2i"
- $asm.puts "vcvt.s32.f64 #{ARMv7_SCRATCH_FPR.armV7Single}, #{operands[0].armV7Operand}"
- $asm.puts "vmov #{operands[1].armV7Operand}, #{ARMv7_SCRATCH_FPR.armV7Single}"
- when "bcd2i"
- $asm.puts "vcvt.s32.f64 #{ARMv7_SCRATCH_FPR.armV7Single}, #{operands[0].armV7Operand}"
- $asm.puts "vmov #{operands[1].armV7Operand}, #{ARMv7_SCRATCH_FPR.armV7Single}"
- $asm.puts "vcvt.f64.s32 #{ARMv7_SCRATCH_FPR.armV7Operand}, #{ARMv7_SCRATCH_FPR.armV7Single}"
- emitArmV7DoubleBranch("bne", [ARMv7_SCRATCH_FPR, operands[0], operands[2]])
- $asm.puts "tst #{operands[1].armV7Operand}, #{operands[1].armV7Operand}"
- $asm.puts "beq #{operands[2].asmLabel}"
- when "movdz"
- # FIXME: either support this or remove it.
- raise "ARMv7 does not support this opcode yet, #{codeOrigin}"
- when "pop"
- $asm.puts "pop #{operands[0].armV7Operand}"
- when "push"
- $asm.puts "push #{operands[0].armV7Operand}"
- when "move", "sxi2p", "zxi2p"
- if operands[0].is_a? Immediate
- armV7MoveImmediate(operands[0].value, operands[1])
- else
- $asm.puts "mov #{armV7FlippedOperands(operands)}"
- end
- when "nop"
- $asm.puts "nop"
- when "bieq", "bpeq", "bbeq"
- if Immediate.new(nil, 0) == operands[0]
- $asm.puts "tst #{operands[1].armV7Operand}, #{operands[1].armV7Operand}"
- elsif Immediate.new(nil, 0) == operands[1]
- $asm.puts "tst #{operands[0].armV7Operand}, #{operands[0].armV7Operand}"
- else
- $asm.puts "cmp #{armV7Operands(operands[0..1])}"
- end
- $asm.puts "beq #{operands[2].asmLabel}"
- when "bineq", "bpneq", "bbneq"
- if Immediate.new(nil, 0) == operands[0]
- $asm.puts "tst #{operands[1].armV7Operand}, #{operands[1].armV7Operand}"
- elsif Immediate.new(nil, 0) == operands[1]
- $asm.puts "tst #{operands[0].armV7Operand}, #{operands[0].armV7Operand}"
- else
- $asm.puts "cmp #{armV7Operands(operands[0..1])}"
- end
- $asm.puts "bne #{operands[2].asmLabel}"
- when "bia", "bpa", "bba"
- $asm.puts "cmp #{armV7Operands(operands[0..1])}"
- $asm.puts "bhi #{operands[2].asmLabel}"
- when "biaeq", "bpaeq", "bbaeq"
- $asm.puts "cmp #{armV7Operands(operands[0..1])}"
- $asm.puts "bhs #{operands[2].asmLabel}"
- when "bib", "bpb", "bbb"
- $asm.puts "cmp #{armV7Operands(operands[0..1])}"
- $asm.puts "blo #{operands[2].asmLabel}"
- when "bibeq", "bpbeq", "bbbeq"
- $asm.puts "cmp #{armV7Operands(operands[0..1])}"
- $asm.puts "bls #{operands[2].asmLabel}"
- when "bigt", "bpgt", "bbgt"
- $asm.puts "cmp #{armV7Operands(operands[0..1])}"
- $asm.puts "bgt #{operands[2].asmLabel}"
- when "bigteq", "bpgteq", "bbgteq"
- $asm.puts "cmp #{armV7Operands(operands[0..1])}"
- $asm.puts "bge #{operands[2].asmLabel}"
- when "bilt", "bplt", "bblt"
- $asm.puts "cmp #{armV7Operands(operands[0..1])}"
- $asm.puts "blt #{operands[2].asmLabel}"
- when "bilteq", "bplteq", "bblteq"
- $asm.puts "cmp #{armV7Operands(operands[0..1])}"
- $asm.puts "ble #{operands[2].asmLabel}"
- when "btiz", "btpz", "btbz"
- emitArmV7Test(operands)
- $asm.puts "beq #{operands[-1].asmLabel}"
- when "btinz", "btpnz", "btbnz"
- emitArmV7Test(operands)
- $asm.puts "bne #{operands[-1].asmLabel}"
- when "btio", "btpo", "btbo"
- emitArmV7Test(operands)
- $asm.puts "bvs #{operands[-1].asmLabel}"
- when "btis", "btps", "btbs"
- emitArmV7Test(operands)
- $asm.puts "bmi #{operands[-1].asmLabel}"
- when "jmp"
- if operands[0].label?
- $asm.puts "b #{operands[0].asmLabel}"
- else
- $asm.puts "mov pc, #{operands[0].armV7Operand}"
- end
- when "call"
- if operands[0].label?
- $asm.puts "blx #{operands[0].asmLabel}"
- else
- $asm.puts "blx #{operands[0].armV7Operand}"
- end
- when "break"
- $asm.puts "bkpt"
- when "ret"
- $asm.puts "bx lr"
- when "cieq", "cpeq"
- emitArmV7Compare(operands, "eq")
- when "cineq", "cpneq"
- emitArmV7Compare(operands, "ne")
- when "cia", "cpa"
- emitArmV7Compare(operands, "hi")
- when "ciaeq", "cpaeq"
- emitArmV7Compare(operands, "hs")
- when "cib", "cpb"
- emitArmV7Compare(operands, "lo")
- when "cibeq", "cpbeq"
- emitArmV7Compare(operands, "ls")
- when "cigt", "cpgt"
- emitArmV7Compare(operands, "gt")
- when "cigteq", "cpgteq"
- emitArmV7Compare(operands, "ge")
- when "cilt", "cplt"
- emitArmV7Compare(operands, "lt")
- when "cilteq", "cplteq"
- emitArmV7Compare(operands, "le")
- when "tio", "tbo"
- emitArmV7TestSet(operands, "vs")
- when "tis", "tbs"
- emitArmV7TestSet(operands, "mi")
- when "tiz", "tbz"
- emitArmV7TestSet(operands, "eq")
- when "tinz", "tbnz"
- emitArmV7TestSet(operands, "ne")
- when "peek"
- $asm.puts "ldr #{operands[1].armV7Operand}, [sp, \##{operands[0].value * 4}]"
- when "poke"
- $asm.puts "str #{operands[1].armV7Operand}, [sp, \##{operands[0].value * 4}]"
- when "fii2d"
- $asm.puts "vmov #{operands[2].armV7Operand}, #{operands[0].armV7Operand}, #{operands[1].armV7Operand}"
- when "fd2ii"
- $asm.puts "vmov #{operands[1].armV7Operand}, #{operands[2].armV7Operand}, #{operands[0].armV7Operand}"
- when "bo"
- $asm.puts "bvs #{operands[0].asmLabel}"
- when "bs"
- $asm.puts "bmi #{operands[0].asmLabel}"
- when "bz"
- $asm.puts "beq #{operands[0].asmLabel}"
- when "bnz"
- $asm.puts "bne #{operands[0].asmLabel}"
- when "leai", "leap"
- operands[0].armV7EmitLea(operands[1])
- when "smulli"
- raise "Wrong number of arguments to smull in #{self.inspect} at #{codeOriginString}" unless operands.length == 4
- $asm.puts "smull #{operands[2].armV7Operand}, #{operands[3].armV7Operand}, #{operands[0].armV7Operand}, #{operands[1].armV7Operand}"
- else
- raise "Unhandled opcode #{opcode} at #{codeOriginString}"
- end
- end
-end
-
+++ /dev/null
-#!/usr/bin/env ruby
-
-# Copyright (C) 2011 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
-# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-# THE POSSIBILITY OF SUCH DAMAGE.
-
-$: << File.dirname(__FILE__)
-
-require "backends"
-require "digest/sha1"
-require "offsets"
-require "parser"
-require "self_hash"
-require "settings"
-require "transform"
-
-class Assembler
- def initialize(outp)
- @outp = outp
- @state = :cpp
- @commentState = :none
- @comment = nil
- end
-
- def enterAsm
- @outp.puts "asm ("
- @state = :asm
- end
-
- def leaveAsm
- putsLastComment
- @outp.puts ");"
- @state = :cpp
- end
-
- def inAsm
- enterAsm
- yield
- leaveAsm
- end
-
- def lastComment
- if @comment
- result = "// #{@comment}"
- else
- result = ""
- end
- @commentState = :none
- @comment = nil
- result
- end
-
- def putsLastComment
- comment = lastComment
- unless comment.empty?
- @outp.puts comment
- end
- end
-
- def puts(*line)
- raise unless @state == :asm
- @outp.puts("\"\\t" + line.join('') + "\\n\" #{lastComment}")
- end
-
- def print(line)
- raise unless @state == :asm
- @outp.print("\"" + line + "\"")
- end
-
- def putsLabel(labelName)
- raise unless @state == :asm
- @outp.puts("OFFLINE_ASM_GLOBAL_LABEL(#{labelName}) #{lastComment}")
- end
-
- def putsLocalLabel(labelName)
- raise unless @state == :asm
- @outp.puts("LOCAL_LABEL_STRING(#{labelName}) \":\\n\" #{lastComment}")
- end
-
- def self.labelReference(labelName)
- "\" SYMBOL_STRING(#{labelName}) \""
- end
-
- def self.localLabelReference(labelName)
- "\" LOCAL_LABEL_STRING(#{labelName}) \""
- end
-
- def comment(text)
- case @commentState
- when :none
- @comment = text
- @commentState = :one
- when :one
- @outp.puts "// #{@comment}"
- @outp.puts "// #{text}"
- @comment = nil
- @commentState = :many
- when :many
- @outp.puts "// #{text}"
- else
- raise
- end
- end
-end
-
-asmFile = ARGV.shift
-offsetsFile = ARGV.shift
-outputFlnm = ARGV.shift
-
-$stderr.puts "offlineasm: Parsing #{asmFile} and #{offsetsFile} and creating assembly file #{outputFlnm}."
-
-offsetsList, configIndex = offsetsAndConfigurationIndex(offsetsFile)
-inputData = IO::read(asmFile)
-
-inputHash =
- "// offlineasm input hash: " + Digest::SHA1.hexdigest(inputData) +
- " " + Digest::SHA1.hexdigest((offsetsList + [configIndex]).join(' ')) +
- " " + selfHash
-
-if FileTest.exist? outputFlnm
- File.open(outputFlnm, "r") {
- | inp |
- firstLine = inp.gets
- if firstLine and firstLine.chomp == inputHash
- $stderr.puts "offlineasm: Nothing changed."
- exit 0
- end
- }
-end
-
-File.open(outputFlnm, "w") {
- | outp |
- $output = outp
- $output.puts inputHash
-
- $asm = Assembler.new($output)
-
- ast = parse(lex(inputData))
-
- forSettings(computeSettingsCombinations(ast)[configIndex], ast) {
- | concreteSettings, lowLevelAST, backend |
- assertConfiguration(concreteSettings)
- lowLevelAST = lowLevelAST.resolve(*buildOffsetsMap(lowLevelAST, offsetsList))
- emitCodeInConfiguration(concreteSettings, lowLevelAST, backend) {
- $asm.inAsm {
- lowLevelAST.lower(backend)
- }
- }
- }
-}
-
-$stderr.puts "offlineasm: Assembly file #{outputFlnm} successfully generated."
-
+++ /dev/null
-# Copyright (C) 2011 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
-# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-# THE POSSIBILITY OF SUCH DAMAGE.
-
-#
-# Base utility types for the AST.
-#
-
-# Valid methods for Node:
-#
-# node.children -> Returns an array of immediate children.
-#
-# node.descendents -> Returns an array of all strict descendants (children
-# and children of children, transitively).
-#
-# node.flatten -> Returns an array containing the strict descendants and
-# the node itself.
-#
-# node.filter(type) -> Returns an array containing those elements in
-# node.flatten that are of the given type (is_a? type returns true).
-#
-# node.mapChildren{|v| ...} -> Returns a new node with all children
-# replaced according to the given block.
-#
-# Examples:
-#
-# node.filter(Setting).uniq -> Returns all of the settings that the AST's
-# IfThenElse blocks depend on.
-#
-# node.filter(StructOffset).uniq -> Returns all of the structure offsets
-# that the AST depends on.
-
-class Node
- attr_reader :codeOrigin
-
- def initialize(codeOrigin)
- @codeOrigin = codeOrigin
- end
-
- def codeOriginString
- "line number #{@codeOrigin}"
- end
-
- def descendants
- children.collect{|v| v.flatten}.flatten
- end
-
- def flatten
- [self] + descendants
- end
-
- def filter(type)
- flatten.select{|v| v.is_a? type}
- end
-end
-
-class NoChildren < Node
- def initialize(codeOrigin)
- super(codeOrigin)
- end
-
- def children
- []
- end
-
- def mapChildren
- self
- end
-end
-
-class StructOffsetKey
- attr_reader :struct, :field
-
- def initialize(struct, field)
- @struct = struct
- @field = field
- end
-
- def hash
- @struct.hash + @field.hash * 3
- end
-
- def eql?(other)
- @struct == other.struct and @field == other.field
- end
-end
-
-#
-# AST nodes.
-#
-
-class StructOffset < NoChildren
- attr_reader :struct, :field
-
- def initialize(codeOrigin, struct, field)
- super(codeOrigin)
- @struct = struct
- @field = field
- end
-
- @@mapping = {}
-
- def self.forField(codeOrigin, struct, field)
- key = StructOffsetKey.new(struct, field)
-
- unless @@mapping[key]
- @@mapping[key] = StructOffset.new(codeOrigin, struct, field)
- end
- @@mapping[key]
- end
-
- def dump
- "#{struct}::#{field}"
- end
-
- def <=>(other)
- if @struct != other.struct
- return @struct <=> other.struct
- end
- @field <=> other.field
- end
-
- def address?
- false
- end
-
- def label?
- false
- end
-
- def immediate?
- true
- end
-
- def register?
- false
- end
-end
-
-class Sizeof < NoChildren
- attr_reader :struct
-
- def initialize(codeOrigin, struct)
- super(codeOrigin)
- @struct = struct
- end
-
- @@mapping = {}
-
- def self.forName(codeOrigin, struct)
- unless @@mapping[struct]
- @@mapping[struct] = Sizeof.new(codeOrigin, struct)
- end
- @@mapping[struct]
- end
-
- def dump
- "sizeof #{@struct}"
- end
-
- def <=>(other)
- @struct <=> other.struct
- end
-
- def address?
- false
- end
-
- def label?
- false
- end
-
- def immediate?
- true
- end
-
- def register?
- false
- end
-end
-
-class Immediate < NoChildren
- attr_reader :value
-
- def initialize(codeOrigin, value)
- super(codeOrigin)
- @value = value
- raise "Bad immediate value #{value.inspect} at #{codeOriginString}" unless value.is_a? Integer
- end
-
- def dump
- "#{value}"
- end
-
- def ==(other)
- other.is_a? Immediate and other.value == @value
- end
-
- def address?
- false
- end
-
- def label?
- false
- end
-
- def immediate?
- true
- end
-
- def register?
- false
- end
-end
-
-class AddImmediates < Node
- attr_reader :left, :right
-
- def initialize(codeOrigin, left, right)
- super(codeOrigin)
- @left = left
- @right = right
- end
-
- def children
- [@left, @right]
- end
-
- def mapChildren
- AddImmediates.new(codeOrigin, (yield @left), (yield @right))
- end
-
- def dump
- "(#{left.dump} + #{right.dump})"
- end
-
- def address?
- false
- end
-
- def label?
- false
- end
-
- def immediate?
- true
- end
-
- def register?
- false
- end
-end
-
-class SubImmediates < Node
- attr_reader :left, :right
-
- def initialize(codeOrigin, left, right)
- super(codeOrigin)
- @left = left
- @right = right
- end
-
- def children
- [@left, @right]
- end
-
- def mapChildren
- SubImmediates.new(codeOrigin, (yield @left), (yield @right))
- end
-
- def dump
- "(#{left.dump} - #{right.dump})"
- end
-
- def address?
- false
- end
-
- def label?
- false
- end
-
- def immediate?
- true
- end
-
- def register?
- false
- end
-end
-
-class MulImmediates < Node
- attr_reader :left, :right
-
- def initialize(codeOrigin, left, right)
- super(codeOrigin)
- @left = left
- @right = right
- end
-
- def children
- [@left, @right]
- end
-
- def mapChildren
- MulImmediates.new(codeOrigin, (yield @left), (yield @right))
- end
-
- def dump
- "(#{left.dump} * #{right.dump})"
- end
-
- def address?
- false
- end
-
- def label?
- false
- end
-
- def immediate?
- true
- end
-
- def register?
- false
- end
-end
-
-class NegImmediate < Node
- attr_reader :child
-
- def initialize(codeOrigin, child)
- super(codeOrigin)
- @child = child
- end
-
- def children
- [@child]
- end
-
- def mapChildren
- NegImmediate.new(codeOrigin, (yield @child))
- end
-
- def dump
- "(-#{@child.dump})"
- end
-
- def address?
- false
- end
-
- def label?
- false
- end
-
- def immediate?
- true
- end
-
- def register?
- false
- end
-end
-
-class RegisterID < NoChildren
- attr_reader :name
-
- def initialize(codeOrigin, name)
- super(codeOrigin)
- @name = name
- end
-
- @@mapping = {}
-
- def self.forName(codeOrigin, name)
- unless @@mapping[name]
- @@mapping[name] = RegisterID.new(codeOrigin, name)
- end
- @@mapping[name]
- end
-
- def dump
- name
- end
-
- def address?
- false
- end
-
- def label?
- false
- end
-
- def immediate?
- false
- end
-
- def register?
- true
- end
-end
-
-class FPRegisterID < NoChildren
- attr_reader :name
-
- def initialize(codeOrigin, name)
- super(codeOrigin)
- @name = name
- end
-
- @@mapping = {}
-
- def self.forName(codeOrigin, name)
- unless @@mapping[name]
- @@mapping[name] = FPRegisterID.new(codeOrigin, name)
- end
- @@mapping[name]
- end
-
- def dump
- name
- end
-
- def address?
- false
- end
-
- def label?
- false
- end
-
- def immediate?
- false
- end
-
- def register?
- true
- end
-end
-
-class Variable < NoChildren
- attr_reader :name
-
- def initialize(codeOrigin, name)
- super(codeOrigin)
- @name = name
- end
-
- @@mapping = {}
-
- def self.forName(codeOrigin, name)
- unless @@mapping[name]
- @@mapping[name] = Variable.new(codeOrigin, name)
- end
- @@mapping[name]
- end
-
- def dump
- name
- end
-end
-
-class Address < Node
- attr_reader :base, :offset
-
- def initialize(codeOrigin, base, offset)
- super(codeOrigin)
- @base = base
- @offset = offset
- raise "Bad base for address #{base.inspect} at #{codeOriginString}" unless base.is_a? Variable or base.register?
- raise "Bad offset for address #{offset.inspect} at #{codeOriginString}" unless offset.is_a? Variable or offset.immediate?
- end
-
- def children
- [@base, @offset]
- end
-
- def mapChildren
- Address.new(codeOrigin, (yield @base), (yield @offset))
- end
-
- def dump
- "#{offset.dump}[#{base.dump}]"
- end
-
- def address?
- true
- end
-
- def label?
- false
- end
-
- def immediate?
- false
- end
-
- def register?
- false
- end
-end
-
-class BaseIndex < Node
- attr_reader :base, :index, :scale, :offset
-
- def initialize(codeOrigin, base, index, scale, offset)
- super(codeOrigin)
- @base = base
- @index = index
- @scale = scale
- raise unless [1, 2, 4, 8].member? @scale
- @offset = offset
- end
-
- def scaleShift
- case scale
- when 1
- 0
- when 2
- 1
- when 4
- 2
- when 8
- 3
- else
- raise "Bad scale at #{codeOriginString}"
- end
- end
-
- def children
- [@base, @index, @offset]
- end
-
- def mapChildren
- BaseIndex.new(codeOrigin, (yield @base), (yield @index), @scale, (yield @offset))
- end
-
- def dump
- "#{offset.dump}[#{base.dump}, #{index.dump}, #{scale}]"
- end
-
- def address?
- true
- end
-
- def label?
- false
- end
-
- def immediate?
- false
- end
-
- def register?
- false
- end
-end
-
-class AbsoluteAddress < NoChildren
- attr_reader :address
-
- def initialize(codeOrigin, address)
- super(codeOrigin)
- @address = address
- end
-
- def dump
- "#{address.dump}[]"
- end
-
- def address?
- true
- end
-
- def label?
- false
- end
-
- def immediate?
- false
- end
-
- def register?
- false
- end
-end
-
-class Instruction < Node
- attr_reader :opcode, :operands
-
- def initialize(codeOrigin, opcode, operands)
- super(codeOrigin)
- @opcode = opcode
- @operands = operands
- end
-
- def children
- operands
- end
-
- def mapChildren(&proc)
- Instruction.new(codeOrigin, @opcode, @operands.map(&proc))
- end
-
- def dump
- "\t" + opcode.to_s + " " + operands.collect{|v| v.dump}.join(", ")
- end
-end
-
-class Error < NoChildren
- def initialize(codeOrigin)
- super(codeOrigin)
- end
-
- def dump
- "\terror"
- end
-end
-
-class ConstDecl < Node
- attr_reader :variable, :value
-
- def initialize(codeOrigin, variable, value)
- super(codeOrigin)
- @variable = variable
- @value = value
- end
-
- def children
- [@variable, @value]
- end
-
- def mapChildren
- ConstDecl.new(codeOrigin, (yield @variable), (yield @value))
- end
-
- def dump
- "const #{@variable.dump} = #{@value.dump}"
- end
-end
-
-$labelMapping = {}
-
-class Label < NoChildren
- attr_reader :name
-
- def initialize(codeOrigin, name)
- super(codeOrigin)
- @name = name
- end
-
- def self.forName(codeOrigin, name)
- if $labelMapping[name]
- raise "Label name collision: #{name}" unless $labelMapping[name].is_a? Label
- else
- $labelMapping[name] = Label.new(codeOrigin, name)
- end
- $labelMapping[name]
- end
-
- def dump
- "#{name}:"
- end
-end
-
-class LocalLabel < NoChildren
- attr_reader :name
-
- def initialize(codeOrigin, name)
- super(codeOrigin)
- @name = name
- end
-
- @@uniqueNameCounter = 0
-
- def self.forName(codeOrigin, name)
- if $labelMapping[name]
- raise "Label name collision: #{name}" unless $labelMapping[name].is_a? LocalLabel
- else
- $labelMapping[name] = LocalLabel.new(codeOrigin, name)
- end
- $labelMapping[name]
- end
-
- def self.unique(comment)
- newName = "_#{comment}"
- if $labelMapping[newName]
- while $labelMapping[newName = "_#{@@uniqueNameCounter}_#{comment}"]
- @@uniqueNameCounter += 1
- end
- end
- forName(nil, newName)
- end
-
- def cleanName
- if name =~ /^\./
- "_" + name[1..-1]
- else
- name
- end
- end
-
- def dump
- "#{name}:"
- end
-end
-
-class LabelReference < Node
- attr_reader :label
-
- def initialize(codeOrigin, label)
- super(codeOrigin)
- @label = label
- end
-
- def children
- [@label]
- end
-
- def mapChildren
- LabelReference.new(codeOrigin, (yield @label))
- end
-
- def name
- label.name
- end
-
- def dump
- label.name
- end
-
- def address?
- false
- end
-
- def label?
- true
- end
-end
-
-class LocalLabelReference < NoChildren
- attr_reader :label
-
- def initialize(codeOrigin, label)
- super(codeOrigin)
- @label = label
- end
-
- def children
- [@label]
- end
-
- def mapChildren
- LocalLabelReference.new(codeOrigin, (yield @label))
- end
-
- def name
- label.name
- end
-
- def dump
- label.name
- end
-
- def address?
- false
- end
-
- def label?
- true
- end
-end
-
-class Sequence < Node
- attr_reader :list
-
- def initialize(codeOrigin, list)
- super(codeOrigin)
- @list = list
- end
-
- def children
- list
- end
-
- def mapChildren(&proc)
- Sequence.new(codeOrigin, @list.map(&proc))
- end
-
- def dump
- list.collect{|v| v.dump}.join("\n")
- end
-end
-
-class True < NoChildren
- def initialize
- super(nil)
- end
-
- @@instance = True.new
-
- def self.instance
- @@instance
- end
-
- def value
- true
- end
-
- def dump
- "true"
- end
-end
-
-class False < NoChildren
- def initialize
- super(nil)
- end
-
- @@instance = False.new
-
- def self.instance
- @@instance
- end
-
- def value
- false
- end
-
- def dump
- "false"
- end
-end
-
-class TrueClass
- def asNode
- True.instance
- end
-end
-
-class FalseClass
- def asNode
- False.instance
- end
-end
-
-class Setting < NoChildren
- attr_reader :name
-
- def initialize(codeOrigin, name)
- super(codeOrigin)
- @name = name
- end
-
- @@mapping = {}
-
- def self.forName(codeOrigin, name)
- unless @@mapping[name]
- @@mapping[name] = Setting.new(codeOrigin, name)
- end
- @@mapping[name]
- end
-
- def dump
- name
- end
-end
-
-class And < Node
- attr_reader :left, :right
-
- def initialize(codeOrigin, left, right)
- super(codeOrigin)
- @left = left
- @right = right
- end
-
- def children
- [@left, @right]
- end
-
- def mapChildren
- And.new(codeOrigin, (yield @left), (yield @right))
- end
-
- def dump
- "(#{left.dump} and #{right.dump})"
- end
-end
-
-class Or < Node
- attr_reader :left, :right
-
- def initialize(codeOrigin, left, right)
- super(codeOrigin)
- @left = left
- @right = right
- end
-
- def children
- [@left, @right]
- end
-
- def mapChildren
- Or.new(codeOrigin, (yield @left), (yield @right))
- end
-
- def dump
- "(#{left.dump} or #{right.dump})"
- end
-end
-
-class Not < Node
- attr_reader :child
-
- def initialize(codeOrigin, child)
- super(codeOrigin)
- @child = child
- end
-
- def children
- [@left, @right]
- end
-
- def mapChildren
- Not.new(codeOrigin, (yield @child))
- end
-
- def dump
- "(not #{child.dump})"
- end
-end
-
-class Skip < NoChildren
- def initialize(codeOrigin)
- super(codeOrigin)
- end
-
- def dump
- "\tskip"
- end
-end
-
-class IfThenElse < Node
- attr_reader :predicate, :thenCase
- attr_accessor :elseCase
-
- def initialize(codeOrigin, predicate, thenCase)
- super(codeOrigin)
- @predicate = predicate
- @thenCase = thenCase
- @elseCase = Skip.new(codeOrigin)
- end
-
- def children
- if @elseCase
- [@predicate, @thenCase, @elseCase]
- else
- [@predicate, @thenCase]
- end
- end
-
- def mapChildren
- IfThenElse.new(codeOrigin, (yield @predicate), (yield @thenCase), (yield @elseCase))
- end
-
- def dump
- "if #{predicate.dump}\n" + thenCase.dump + "\nelse\n" + elseCase.dump + "\nend"
- end
-end
-
-class Macro < Node
- attr_reader :name, :variables, :body
-
- def initialize(codeOrigin, name, variables, body)
- super(codeOrigin)
- @name = name
- @variables = variables
- @body = body
- end
-
- def children
- @variables + [@body]
- end
-
- def mapChildren
- Macro.new(codeOrigin, @name, @variables.map{|v| yield v}, (yield @body))
- end
-
- def dump
- "macro #{name}(" + variables.collect{|v| v.dump}.join(", ") + ")\n" + body.dump + "\nend"
- end
-end
-
-class MacroCall < Node
- attr_reader :name, :operands
-
- def initialize(codeOrigin, name, operands)
- super(codeOrigin)
- @name = name
- @operands = operands
- raise unless @operands
- @operands.each{|v| raise unless v}
- end
-
- def children
- @operands
- end
-
- def mapChildren(&proc)
- MacroCall.new(codeOrigin, @name, @operands.map(&proc))
- end
-
- def dump
- "\t#{name}(" + operands.collect{|v| v.dump}.join(", ") + ")"
- end
-end
-
+++ /dev/null
-# Copyright (C) 2011 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
-# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-# THE POSSIBILITY OF SUCH DAMAGE.
-
-require "armv7"
-require "ast"
-require "x86"
-
-BACKENDS =
- [
- "X86",
- "ARMv7"
- ]
-
-# Keep the set of working backends separate from the set of backends that might be
-# supported. This is great because the BACKENDS list is almost like a reserved
-# words list, in that it causes settings resolution to treat those words specially.
-# Hence this lets us set aside the name of a backend we might want to support in
-# the future while not actually supporting the backend yet.
-WORKING_BACKENDS =
- [
- "X86",
- "ARMv7"
- ]
-
-BACKEND_PATTERN = Regexp.new('\\A(' + BACKENDS.join(')|(') + ')\\Z')
-
-class Node
- def lower(name)
- send("lower" + name)
- end
-end
-
-# Overrides for lower() for those nodes that are backend-agnostic
-
-class Label
- def lower(name)
- $asm.putsLabel(self.name[1..-1])
- end
-end
-
-class LocalLabel
- def lower(name)
- $asm.putsLocalLabel "_offlineasm_#{self.name[1..-1]}"
- end
-end
-
-class LabelReference
- def asmLabel
- Assembler.labelReference(name[1..-1])
- end
-end
-
-class LocalLabelReference
- def asmLabel
- Assembler.localLabelReference("_offlineasm_"+name[1..-1])
- end
-end
-
-class Skip
- def lower(name)
- end
-end
-
-class Sequence
- def lower(name)
- if respond_to? "lower#{name}"
- send("lower#{name}")
- else
- @list.each {
- | node |
- node.lower(name)
- }
- end
- end
-end
-
+++ /dev/null
-#!/usr/bin/env ruby
-
-# Copyright (C) 2011 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
-# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-# THE POSSIBILITY OF SUCH DAMAGE.
-
-$: << File.dirname(__FILE__)
-
-require "backends"
-require "digest/sha1"
-require "offsets"
-require "parser"
-require "self_hash"
-require "settings"
-require "transform"
-
-inputFlnm = ARGV.shift
-outputFlnm = ARGV.shift
-
-$stderr.puts "offlineasm: Parsing #{inputFlnm} and creating offset extractor #{outputFlnm}."
-
-def emitMagicNumber
- OFFSET_MAGIC_NUMBERS.each {
- | number |
- $output.puts "#{number},"
- }
-end
-
-inputData = IO::read(inputFlnm)
-inputHash = "// offlineasm input hash: #{Digest::SHA1.hexdigest(inputData)} #{selfHash}"
-
-if FileTest.exist? outputFlnm
- File.open(outputFlnm, "r") {
- | inp |
- firstLine = inp.gets
- if firstLine and firstLine.chomp == inputHash
- $stderr.puts "offlineasm: Nothing changed."
- exit 0
- end
- }
-end
-
-originalAST = parse(lex(inputData))
-
-#
-# Optimize the AST to make configuration extraction faster. This reduces the AST to a form
-# that only contains the things that matter for our purposes: offsets, sizes, and if
-# statements.
-#
-
-class Node
- def offsetsPruneTo(sequence)
- children.each {
- | child |
- child.offsetsPruneTo(sequence)
- }
- end
-
- def offsetsPrune
- result = Sequence.new(codeOrigin, [])
- offsetsPruneTo(result)
- result
- end
-end
-
-class IfThenElse
- def offsetsPruneTo(sequence)
- ifThenElse = IfThenElse.new(codeOrigin, predicate, thenCase.offsetsPrune)
- ifThenElse.elseCase = elseCase.offsetsPrune
- sequence.list << ifThenElse
- end
-end
-
-class StructOffset
- def offsetsPruneTo(sequence)
- sequence.list << self
- end
-end
-
-class Sizeof
- def offsetsPruneTo(sequence)
- sequence.list << self
- end
-end
-
-prunedAST = originalAST.offsetsPrune
-
-File.open(outputFlnm, "w") {
- | outp |
- $output = outp
- outp.puts inputHash
- emitCodeInAllConfigurations(prunedAST) {
- | settings, ast, backend, index |
- offsetsList = ast.filter(StructOffset).uniq.sort
- sizesList = ast.filter(Sizeof).uniq.sort
-
- length = (OFFSET_MAGIC_NUMBERS.size + 1) * (1 + offsetsList.size + sizesList.size)
-
- outp.puts "static const unsigned extractorTable[#{length}] = {"
- emitMagicNumber
- outp.puts "#{index},"
- offsetsList.each {
- | offset |
- emitMagicNumber
- outp.puts "OFFLINE_ASM_OFFSETOF(#{offset.struct}, #{offset.field}),"
- }
- sizesList.each {
- | offset |
- emitMagicNumber
- outp.puts "sizeof(#{offset.struct}),"
- }
- outp.puts "};"
- }
-}
-
-$stderr.puts "offlineasm: offset extractor #{outputFlnm} successfully generated."
-
+++ /dev/null
-# Copyright (C) 2011 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
-# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-# THE POSSIBILITY OF SUCH DAMAGE.
-
-# Interesting invariant, which we take advantage of: branching instructions
-# always begin with "b", and no non-branching instructions begin with "b".
-# Terminal instructions are "jmp" and "ret".
-
-MACRO_INSTRUCTIONS =
- [
- "addi",
- "andi",
- "lshifti",
- "muli",
- "negi",
- "noti",
- "ori",
- "rshifti",
- "urshifti",
- "subi",
- "xori",
- "loadi",
- "loadb",
- "loadbs",
- "loadh",
- "loadhs",
- "storei",
- "storeb",
- "loadd",
- "moved",
- "stored",
- "addd",
- "divd",
- "subd",
- "muld",
- "sqrtd",
- "ci2d",
- "fii2d", # usage: fii2d <gpr with least significant bits>, <gpr with most significant bits>, <fpr>
- "fd2ii", # usage: fd2ii <fpr>, <gpr with least significant bits>, <gpr with most significant bits>
- "bdeq",
- "bdneq",
- "bdgt",
- "bdgteq",
- "bdlt",
- "bdlteq",
- "bdequn",
- "bdnequn",
- "bdgtun",
- "bdgtequn",
- "bdltun",
- "bdltequn",
- "btd2i",
- "td2i",
- "bcd2i",
- "movdz",
- "pop",
- "push",
- "move",
- "sxi2p",
- "zxi2p",
- "nop",
- "bieq",
- "bineq",
- "bia",
- "biaeq",
- "bib",
- "bibeq",
- "bigt",
- "bigteq",
- "bilt",
- "bilteq",
- "bbeq",
- "bbneq",
- "bba",
- "bbaeq",
- "bbb",
- "bbbeq",
- "bbgt",
- "bbgteq",
- "bblt",
- "bblteq",
- "btio",
- "btis",
- "btiz",
- "btinz",
- "btbo",
- "btbs",
- "btbz",
- "btbnz",
- "jmp",
- "baddio",
- "baddis",
- "baddiz",
- "baddinz",
- "bsubio",
- "bsubis",
- "bsubiz",
- "bsubinz",
- "bmulio",
- "bmulis",
- "bmuliz",
- "bmulinz",
- "borio",
- "boris",
- "boriz",
- "borinz",
- "break",
- "call",
- "ret",
- "cieq",
- "cineq",
- "cia",
- "ciaeq",
- "cib",
- "cibeq",
- "cigt",
- "cigteq",
- "cilt",
- "cilteq",
- "tio",
- "tis",
- "tiz",
- "tinz",
- "tbo",
- "tbs",
- "tbz",
- "tbnz",
- "peek",
- "poke",
- "bpeq",
- "bpneq",
- "bpa",
- "bpaeq",
- "bpb",
- "bpbeq",
- "bpgt",
- "bpgteq",
- "bplt",
- "bplteq",
- "addp",
- "andp",
- "orp",
- "subp",
- "xorp",
- "loadp",
- "cpeq",
- "cpneq",
- "cpa",
- "cpaeq",
- "cpb",
- "cpbeq",
- "cpgt",
- "cpgteq",
- "cplt",
- "cplteq",
- "storep",
- "btpo",
- "btps",
- "btpz",
- "btpnz",
- "baddpo",
- "baddps",
- "baddpz",
- "baddpnz",
- "bo",
- "bs",
- "bz",
- "bnz",
- "leai",
- "leap",
- ]
-
-X86_INSTRUCTIONS =
- [
- "cdqi",
- "idivi"
- ]
-
-ARMv7_INSTRUCTIONS =
- [
- "smulli",
- "addis",
- "subis",
- "oris"
- ]
-
-INSTRUCTIONS = MACRO_INSTRUCTIONS + X86_INSTRUCTIONS + ARMv7_INSTRUCTIONS
-
-INSTRUCTION_PATTERN = Regexp.new('\\A((' + INSTRUCTIONS.join(')|(') + '))\\Z')
-
-def isBranch(instruction)
- instruction =~ /^b/
-end
-
-def hasFallThrough(instruction)
- instruction != "ret" and instruction != "jmp"
-end
-
+++ /dev/null
-# Copyright (C) 2011 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
-# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-# THE POSSIBILITY OF SUCH DAMAGE.
-
-MAGIC_NUMBERS = [ 0xec577ac7, 0x0ff5e755 ]
-
-
+++ /dev/null
-# Copyright (C) 2011 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
-# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-# THE POSSIBILITY OF SUCH DAMAGE.
-
-require "ast"
-require "offset_extractor_constants"
-
-OFFSET_MAGIC_NUMBERS = [ 0xec577ac7, 0x0ff5e755 ]
-
-#
-# offsetsList(ast)
-# sizesList(ast)
-#
-# Returns a list of offsets and sizes used by the AST.
-#
-
-def offsetsList(ast)
- ast.filter(StructOffset).uniq.sort
-end
-
-def sizesList(ast)
- ast.filter(Sizeof).uniq.sort
-end
-
-#
-# offsetsAndConfigurationIndex(ast, file) ->
-# [offsets, index]
-#
-# Parses the offsets from a file and returns a list of offsets and the
-# index of the configuration that is valid in this build target.
-#
-
-def offsetsAndConfigurationIndex(file)
- index = nil
- offsets = []
- endiannessMarkerBytes = nil
-
- def readInt(endianness, inp)
- bytes = []
- 4.times {
- bytes << inp.getbyte
- }
-
- if endianness == :little
- # Little endian
- (bytes[0] << 0 |
- bytes[1] << 8 |
- bytes[2] << 16 |
- bytes[3] << 24)
- else
- # Big endian
- (bytes[0] << 24 |
- bytes[1] << 16 |
- bytes[2] << 8 |
- bytes[3] << 0)
- end
- end
-
- [:little, :big].each {
- | endianness |
- magicBytes = []
- MAGIC_NUMBERS.each {
- | number |
- currentBytes = []
- 4.times {
- currentBytes << (number & 0xff)
- number >>= 8
- }
- if endianness == :big
- currentBytes.reverse!
- end
- magicBytes += currentBytes
- }
-
- File.open(file, "r") {
- | inp |
- whereInMarker = 0
- loop {
- byte = inp.getbyte
- break unless byte
- if byte == magicBytes[whereInMarker]
- whereInMarker += 1
- if whereInMarker == magicBytes.size
- # We have a match! If we have not yet read the endianness marker and index,
- # then read those now; otherwise read an offset.
-
- if not index
- index = readInt(endianness, inp)
- else
- offsets << readInt(endianness, inp)
- end
-
- whereInMarker = 0
- end
- else
- whereInMarker = 0
- end
- }
- }
-
- break if index
- }
-
- raise unless index
-
- [offsets, index]
-end
-
-#
-# buildOffsetsMap(ast, offsetsList) -> [offsets, sizes]
-#
-# Builds a mapping between StructOffset nodes and their values.
-#
-
-def buildOffsetsMap(ast, offsetsList)
- offsetsMap = {}
- sizesMap = {}
- astOffsetsList = offsetsList(ast)
- astSizesList = sizesList(ast)
- raise unless astOffsetsList.size + astSizesList.size == offsetsList.size
- offsetsList(ast).each_with_index {
- | structOffset, index |
- offsetsMap[structOffset] = offsetsList.shift
- }
- sizesList(ast).each_with_index {
- | sizeof, index |
- sizesMap[sizeof] = offsetsList.shift
- }
- [offsetsMap, sizesMap]
-end
-
+++ /dev/null
-# Copyright (C) 2011 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
-# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-# THE POSSIBILITY OF SUCH DAMAGE.
-
-require "ast"
-
-#
-# "Optimization" passes. These are used to lower the representation for
-# backends that cannot handle some of our higher-level instructions.
-#
-
-#
-# A temporary - a variable that will be allocated to a register after we're
-# done.
-#
-
-class Node
- def replaceTemporariesWithRegisters(kind)
- mapChildren {
- | node |
- node.replaceTemporariesWithRegisters(kind)
- }
- end
-end
-
-class Tmp < NoChildren
- attr_reader :firstMention, :lastMention
- attr_reader :kind
- attr_accessor :register
-
- def initialize(codeOrigin, kind)
- super(codeOrigin)
- @kind = kind
- end
-
- def dump
- "$tmp#{object_id}"
- end
-
- def mention!(position)
- if not @firstMention or position < @firstMention
- @firstMention = position
- end
- if not @lastMention or position > @lastMention
- @lastMention = position
- end
- end
-
- def replaceTemporariesWithRegisters(kind)
- if @kind == kind
- raise "Did not allocate register to temporary at #{codeOriginString}" unless @register
- @register
- else
- self
- end
- end
-
- def address?
- false
- end
-
- def label?
- false
- end
-
- def immediate?
- false
- end
-
- def register?
- true
- end
-end
-
-# Assign registers to temporaries, by finding which temporaries interfere
-# with each other. Note that this relies on temporary live ranges not crossing
-# basic block boundaries.
-
-def assignRegistersToTemporaries(list, kind, registers)
- list.each_with_index {
- | node, index |
- node.filter(Tmp).uniq.each {
- | tmp |
- if tmp.kind == kind
- tmp.mention! index
- end
- }
- }
-
- freeRegisters = registers.dup
- list.each_with_index {
- | node, index |
- tmpList = node.filter(Tmp).uniq
- tmpList.each {
- | tmp |
- if tmp.kind == kind and tmp.firstMention == index
- raise "Could not allocate register to temporary at #{node.codeOriginString}" if freeRegisters.empty?
- tmp.register = freeRegisters.pop
- end
- }
- tmpList.each {
- | tmp |
- if tmp.kind == kind and tmp.lastMention == index
- freeRegisters.push tmp.register
- raise "Register allocation inconsistency at #{node.codeOriginString}" if freeRegisters.size > registers.size
- end
- }
- }
-
- list.map {
- | node |
- node.replaceTemporariesWithRegisters(kind)
- }
-end
-
+++ /dev/null
-# Copyright (C) 2011 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
-# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-# THE POSSIBILITY OF SUCH DAMAGE.
-
-require "ast"
-require "instructions"
-require "registers"
-
-class Token
- attr_reader :codeOrigin, :string
-
- def initialize(codeOrigin, string)
- @codeOrigin = codeOrigin
- @string = string
- end
-
- def ==(other)
- if other.is_a? Token
- @string == other.string
- else
- @string == other
- end
- end
-
- def =~(other)
- @string =~ other
- end
-
- def to_s
- "#{@string.inspect} at line #{codeOrigin}"
- end
-
- def parseError(*comment)
- if comment.empty?
- raise "Parse error: #{to_s}"
- else
- raise "Parse error: #{to_s}: #{comment[0]}"
- end
- end
-end
-
-#
-# The lexer. Takes a string and returns an array of tokens.
-#
-
-def lex(str)
- result = []
- lineNumber = 1
- while not str.empty?
- case str
- when /\A\#([^\n]*)/
- # comment, ignore
- when /\A\n/
- result << Token.new(lineNumber, $&)
- lineNumber += 1
- when /\A[a-zA-Z]([a-zA-Z0-9_]*)/
- result << Token.new(lineNumber, $&)
- when /\A\.([a-zA-Z0-9_]*)/
- result << Token.new(lineNumber, $&)
- when /\A_([a-zA-Z0-9_]*)/
- result << Token.new(lineNumber, $&)
- when /\A([ \t]+)/
- # whitespace, ignore
- when /\A0x([0-9a-fA-F]+)/
- result << Token.new(lineNumber, $&.hex.to_s)
- when /\A0([0-7]+)/
- result << Token.new(lineNumber, $&.oct.to_s)
- when /\A([0-9]+)/
- result << Token.new(lineNumber, $&)
- when /\A::/
- result << Token.new(lineNumber, $&)
- when /\A[:,\(\)\[\]=\+\-*]/
- result << Token.new(lineNumber, $&)
- else
- raise "Lexer error at line number #{lineNumber}, unexpected sequence #{str[0..20].inspect}"
- end
- str = $~.post_match
- end
- result
-end
-
-#
-# Token identification.
-#
-
-def isRegister(token)
- token =~ REGISTER_PATTERN
-end
-
-def isInstruction(token)
- token =~ INSTRUCTION_PATTERN
-end
-
-def isKeyword(token)
- token =~ /\A((true)|(false)|(if)|(then)|(else)|(elsif)|(end)|(and)|(or)|(not)|(macro)|(const)|(sizeof)|(error))\Z/ or
- token =~ REGISTER_PATTERN or
- token =~ INSTRUCTION_PATTERN
-end
-
-def isIdentifier(token)
- token =~ /\A[a-zA-Z]([a-zA-Z0-9_]*)\Z/ and not isKeyword(token)
-end
-
-def isLabel(token)
- token =~ /\A_([a-zA-Z0-9_]*)\Z/
-end
-
-def isLocalLabel(token)
- token =~ /\A\.([a-zA-Z0-9_]*)\Z/
-end
-
-def isVariable(token)
- isIdentifier(token) or isRegister(token)
-end
-
-def isInteger(token)
- token =~ /\A[0-9]/
-end
-
-#
-# The parser. Takes an array of tokens and returns an AST. Methods
-# other than parse(tokens) are not for public consumption.
-#
-
-class Parser
- def initialize(tokens)
- @tokens = tokens
- @idx = 0
- end
-
- def parseError(*comment)
- if @tokens[@idx]
- @tokens[@idx].parseError(*comment)
- else
- if comment.empty?
- raise "Parse error at end of file"
- else
- raise "Parse error at end of file: #{comment[0]}"
- end
- end
- end
-
- def consume(regexp)
- if regexp
- parseError unless @tokens[@idx] =~ regexp
- else
- parseError unless @idx == @tokens.length
- end
- @idx += 1
- end
-
- def skipNewLine
- while @tokens[@idx] == "\n"
- @idx += 1
- end
- end
-
- def parsePredicateAtom
- if @tokens[@idx] == "not"
- @idx += 1
- parsePredicateAtom
- elsif @tokens[@idx] == "("
- @idx += 1
- skipNewLine
- result = parsePredicate
- parseError unless @tokens[@idx] == ")"
- @idx += 1
- result
- elsif @tokens[@idx] == "true"
- result = True.instance
- @idx += 1
- result
- elsif @tokens[@idx] == "false"
- result = False.instance
- @idx += 1
- result
- elsif isIdentifier @tokens[@idx]
- result = Setting.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
- @idx += 1
- result
- else
- parseError
- end
- end
-
- def parsePredicateAnd
- result = parsePredicateAtom
- while @tokens[@idx] == "and"
- codeOrigin = @tokens[@idx].codeOrigin
- @idx += 1
- skipNewLine
- right = parsePredicateAtom
- result = And.new(codeOrigin, result, right)
- end
- result
- end
-
- def parsePredicate
- # some examples of precedence:
- # not a and b -> (not a) and b
- # a and b or c -> (a and b) or c
- # a or b and c -> a or (b and c)
-
- result = parsePredicateAnd
- while @tokens[@idx] == "or"
- codeOrigin = @tokens[@idx].codeOrigin
- @idx += 1
- skipNewLine
- right = parsePredicateAnd
- result = Or.new(codeOrigin, result, right)
- end
- result
- end
-
- def parseVariable
- if isRegister(@tokens[@idx])
- if @tokens[@idx] =~ FPR_PATTERN
- result = FPRegisterID.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
- else
- result = RegisterID.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
- end
- elsif isIdentifier(@tokens[@idx])
- result = Variable.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
- else
- parseError
- end
- @idx += 1
- result
- end
-
- def parseAddress(offset)
- parseError unless @tokens[@idx] == "["
- codeOrigin = @tokens[@idx].codeOrigin
-
- # Three possibilities:
- # [] -> AbsoluteAddress
- # [a] -> Address
- # [a,b] -> BaseIndex with scale = 1
- # [a,b,c] -> BaseIndex
-
- @idx += 1
- if @tokens[@idx] == "]"
- @idx += 1
- return AbsoluteAddress.new(codeOrigin, offset)
- end
- a = parseVariable
- if @tokens[@idx] == "]"
- result = Address.new(codeOrigin, a, offset)
- else
- parseError unless @tokens[@idx] == ","
- @idx += 1
- b = parseVariable
- if @tokens[@idx] == "]"
- result = BaseIndex.new(codeOrigin, a, b, 1, offset)
- else
- parseError unless @tokens[@idx] == ","
- @idx += 1
- parseError unless ["1", "2", "4", "8"].member? @tokens[@idx].string
- c = @tokens[@idx].string.to_i
- @idx += 1
- parseError unless @tokens[@idx] == "]"
- result = BaseIndex.new(codeOrigin, a, b, c, offset)
- end
- end
- @idx += 1
- result
- end
-
- def parseColonColon
- skipNewLine
- codeOrigin = @tokens[@idx].codeOrigin
- parseError unless isIdentifier @tokens[@idx]
- names = [@tokens[@idx].string]
- @idx += 1
- while @tokens[@idx] == "::"
- @idx += 1
- parseError unless isIdentifier @tokens[@idx]
- names << @tokens[@idx].string
- @idx += 1
- end
- raise if names.empty?
- [codeOrigin, names]
- end
-
- def parseExpressionAtom
- skipNewLine
- if @tokens[@idx] == "-"
- @idx += 1
- NegImmediate.new(@tokens[@idx - 1].codeOrigin, parseExpressionAtom)
- elsif @tokens[@idx] == "("
- @idx += 1
- result = parseExpression
- parseError unless @tokens[@idx] == ")"
- @idx += 1
- result
- elsif isInteger @tokens[@idx]
- result = Immediate.new(@tokens[@idx].codeOrigin, @tokens[@idx].string.to_i)
- @idx += 1
- result
- elsif isIdentifier @tokens[@idx]
- codeOrigin, names = parseColonColon
- if names.size > 1
- StructOffset.forField(codeOrigin, names[0..-2].join('::'), names[-1])
- else
- Variable.forName(codeOrigin, names[0])
- end
- elsif isRegister @tokens[@idx]
- parseVariable
- elsif @tokens[@idx] == "sizeof"
- @idx += 1
- codeOrigin, names = parseColonColon
- Sizeof.forName(codeOrigin, names.join('::'))
- else
- parseError
- end
- end
-
- def parseExpressionMul
- skipNewLine
- result = parseExpressionAtom
- while @tokens[@idx] == "*"
- if @tokens[@idx] == "*"
- @idx += 1
- result = MulImmediates.new(@tokens[@idx - 1].codeOrigin, result, parseExpressionAtom)
- else
- raise
- end
- end
- result
- end
-
- def couldBeExpression
- @tokens[@idx] == "-" or @tokens[@idx] == "sizeof" or isInteger(@tokens[@idx]) or isVariable(@tokens[@idx]) or @tokens[@idx] == "("
- end
-
- def parseExpression
- skipNewLine
- result = parseExpressionMul
- while @tokens[@idx] == "+" or @tokens[@idx] == "-"
- if @tokens[@idx] == "+"
- @idx += 1
- result = AddImmediates.new(@tokens[@idx - 1].codeOrigin, result, parseExpressionMul)
- elsif @tokens[@idx] == "-"
- @idx += 1
- result = SubImmediates.new(@tokens[@idx - 1].codeOrigin, result, parseExpressionMul)
- else
- raise
- end
- end
- result
- end
-
- def parseOperand(comment)
- skipNewLine
- if couldBeExpression
- expr = parseExpression
- if @tokens[@idx] == "["
- parseAddress(expr)
- else
- expr
- end
- elsif @tokens[@idx] == "["
- parseAddress(Immediate.new(@tokens[@idx].codeOrigin, 0))
- elsif isLabel @tokens[@idx]
- result = LabelReference.new(@tokens[@idx].codeOrigin, Label.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string))
- @idx += 1
- result
- elsif isLocalLabel @tokens[@idx]
- result = LocalLabelReference.new(@tokens[@idx].codeOrigin, LocalLabel.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string))
- @idx += 1
- result
- else
- parseError(comment)
- end
- end
-
- def parseMacroVariables
- skipNewLine
- consume(/\A\(\Z/)
- variables = []
- loop {
- skipNewLine
- if @tokens[@idx] == ")"
- @idx += 1
- break
- elsif isIdentifier(@tokens[@idx])
- variables << Variable.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
- @idx += 1
- skipNewLine
- if @tokens[@idx] == ")"
- @idx += 1
- break
- elsif @tokens[@idx] == ","
- @idx += 1
- else
- parseError
- end
- else
- parseError
- end
- }
- variables
- end
-
- def parseSequence(final, comment)
- firstCodeOrigin = @tokens[@idx].codeOrigin
- list = []
- loop {
- if (@idx == @tokens.length and not final) or (final and @tokens[@idx] =~ final)
- break
- elsif @tokens[@idx] == "\n"
- # ignore
- @idx += 1
- elsif @tokens[@idx] == "const"
- @idx += 1
- parseError unless isVariable @tokens[@idx]
- variable = Variable.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
- @idx += 1
- parseError unless @tokens[@idx] == "="
- @idx += 1
- value = parseOperand("while inside of const #{variable.name}")
- list << ConstDecl.new(@tokens[@idx].codeOrigin, variable, value)
- elsif @tokens[@idx] == "error"
- list << Error.new(@tokens[@idx].codeOrigin)
- @idx += 1
- elsif @tokens[@idx] == "if"
- codeOrigin = @tokens[@idx].codeOrigin
- @idx += 1
- skipNewLine
- predicate = parsePredicate
- consume(/\A((then)|(\n))\Z/)
- skipNewLine
- ifThenElse = IfThenElse.new(codeOrigin, predicate, parseSequence(/\A((else)|(end)|(elsif))\Z/, "while inside of \"if #{predicate.dump}\""))
- list << ifThenElse
- while @tokens[@idx] == "elsif"
- codeOrigin = @tokens[@idx].codeOrigin
- @idx += 1
- skipNewLine
- predicate = parsePredicate
- consume(/\A((then)|(\n))\Z/)
- skipNewLine
- elseCase = IfThenElse.new(codeOrigin, predicate, parseSequence(/\A((else)|(end)|(elsif))\Z/, "while inside of \"if #{predicate.dump}\""))
- ifThenElse.elseCase = elseCase
- ifThenElse = elseCase
- end
- if @tokens[@idx] == "else"
- @idx += 1
- ifThenElse.elseCase = parseSequence(/\Aend\Z/, "while inside of else case for \"if #{predicate.dump}\"")
- @idx += 1
- else
- parseError unless @tokens[@idx] == "end"
- @idx += 1
- end
- elsif @tokens[@idx] == "macro"
- codeOrigin = @tokens[@idx].codeOrigin
- @idx += 1
- skipNewLine
- parseError unless isIdentifier(@tokens[@idx])
- name = @tokens[@idx].string
- @idx += 1
- variables = parseMacroVariables
- body = parseSequence(/\Aend\Z/, "while inside of macro #{name}")
- @idx += 1
- list << Macro.new(codeOrigin, name, variables, body)
- elsif isInstruction @tokens[@idx]
- codeOrigin = @tokens[@idx].codeOrigin
- name = @tokens[@idx].string
- @idx += 1
- if (not final and @idx == @tokens.size) or (final and @tokens[@idx] =~ final)
- # Zero operand instruction, and it's the last one.
- list << Instruction.new(codeOrigin, name, [])
- break
- elsif @tokens[@idx] == "\n"
- # Zero operand instruction.
- list << Instruction.new(codeOrigin, name, [])
- @idx += 1
- else
- # It's definitely an instruction, and it has at least one operand.
- operands = []
- endOfSequence = false
- loop {
- operands << parseOperand("while inside of instruction #{name}")
- if (not final and @idx == @tokens.size) or (final and @tokens[@idx] =~ final)
- # The end of the instruction and of the sequence.
- endOfSequence = true
- break
- elsif @tokens[@idx] == ","
- # Has another operand.
- @idx += 1
- elsif @tokens[@idx] == "\n"
- # The end of the instruction.
- @idx += 1
- break
- else
- parseError("Expected a comma, newline, or #{final} after #{operands.last.dump}")
- end
- }
- list << Instruction.new(codeOrigin, name, operands)
- if endOfSequence
- break
- end
- end
- elsif isIdentifier @tokens[@idx]
- codeOrigin = @tokens[@idx].codeOrigin
- name = @tokens[@idx].string
- @idx += 1
- if @tokens[@idx] == "("
- # Macro invocation.
- @idx += 1
- operands = []
- skipNewLine
- if @tokens[@idx] == ")"
- @idx += 1
- else
- loop {
- skipNewLine
- if @tokens[@idx] == "macro"
- # It's a macro lambda!
- codeOriginInner = @tokens[@idx].codeOrigin
- @idx += 1
- variables = parseMacroVariables
- body = parseSequence(/\Aend\Z/, "while inside of anonymous macro passed as argument to #{name}")
- @idx += 1
- operands << Macro.new(codeOriginInner, nil, variables, body)
- else
- operands << parseOperand("while inside of macro call to #{name}")
- end
- skipNewLine
- if @tokens[@idx] == ")"
- @idx += 1
- break
- elsif @tokens[@idx] == ","
- @idx += 1
- else
- parseError "Unexpected #{@tokens[@idx].string.inspect} while parsing invocation of macro #{name}"
- end
- }
- end
- list << MacroCall.new(codeOrigin, name, operands)
- else
- parseError "Expected \"(\" after #{name}"
- end
- elsif isLabel @tokens[@idx] or isLocalLabel @tokens[@idx]
- codeOrigin = @tokens[@idx].codeOrigin
- name = @tokens[@idx].string
- @idx += 1
- parseError unless @tokens[@idx] == ":"
- # It's a label.
- if isLabel name
- list << Label.forName(codeOrigin, name)
- else
- list << LocalLabel.forName(codeOrigin, name)
- end
- @idx += 1
- else
- parseError "Expecting terminal #{final} #{comment}"
- end
- }
- Sequence.new(firstCodeOrigin, list)
- end
-end
-
-def parse(tokens)
- parser = Parser.new(tokens)
- parser.parseSequence(nil, "")
-end
-
+++ /dev/null
-# Copyright (C) 2011 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
-# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-# THE POSSIBILITY OF SUCH DAMAGE.
-
-GPRS =
- [
- "t0",
- "t1",
- "t2",
- "t3",
- "t4",
- "cfr",
- "a0",
- "a1",
- "r0",
- "r1",
- "sp",
- "lr"
- ]
-
-FPRS =
- [
- "ft0",
- "ft1",
- "ft2",
- "ft3",
- "ft4",
- "ft5",
- "fa0",
- "fa1",
- "fa2",
- "fa3",
- "fr"
- ]
-
-REGISTERS = GPRS + FPRS
-
-GPR_PATTERN = Regexp.new('\\A((' + GPRS.join(')|(') + '))\\Z')
-FPR_PATTERN = Regexp.new('\\A((' + FPRS.join(')|(') + '))\\Z')
-
-REGISTER_PATTERN = Regexp.new('\\A((' + REGISTERS.join(')|(') + '))\\Z')
+++ /dev/null
-# Copyright (C) 2011 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
-# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-# THE POSSIBILITY OF SUCH DAMAGE.
-
-require "digest/sha1"
-require "pathname"
-
-#
-# selfHash -> SHA1 hexdigest
-#
-# Returns a hash of the offlineasm source code. This allows dependency
-# tracking for not just changes in input, but also changes in the assembler
-# itself.
-#
-
-def selfHash
- contents = ""
- myPath = Pathname.new(__FILE__).dirname
- Dir.foreach(myPath) {
- | entry |
- if entry =~ /\.rb$/
- contents += IO::read(myPath + entry)
- end
- }
- return Digest::SHA1.hexdigest(contents)
-end
-
+++ /dev/null
-# Copyright (C) 2011 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
-# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-# THE POSSIBILITY OF SUCH DAMAGE.
-
-require "ast"
-require "backends"
-require "parser"
-require "transform"
-
-#
-# computeSettingsCombinations(ast) -> settingsCombiations
-#
-# Computes an array of settings maps, where a settings map constitutes
-# a configuration for the assembly code being generated. The map
-# contains key value pairs where keys are settings names (strings) and
-# the values are booleans (true for enabled, false for disabled).
-#
-
-def computeSettingsCombinations(ast)
- settingsCombinations = []
-
- def settingsCombinator(settingsCombinations, mapSoFar, remaining)
- if remaining.empty?
- settingsCombinations << mapSoFar
- return
- end
-
- newMap = mapSoFar.dup
- newMap[remaining[0]] = true
- settingsCombinator(settingsCombinations, newMap, remaining[1..-1])
-
- newMap = mapSoFar.dup
- newMap[remaining[0]] = false
- settingsCombinator(settingsCombinations, newMap, remaining[1..-1])
- end
-
- settingsCombinator(settingsCombinations, {}, (ast.filter(Setting).uniq.collect{|v| v.name} + ["X86", "ARMv7"]).uniq)
-
- settingsCombinations
-end
-
-#
-# forSettings(concreteSettings, ast) {
-# | concreteSettings, lowLevelAST, backend | ... }
-#
-# Determines if the settings combination is valid, and if so, calls
-# the block with the information you need to generate code.
-#
-
-def forSettings(concreteSettings, ast)
- # Check which architectures this combinator claims to support.
- numClaimedBackends = 0
- selectedBackend = nil
- BACKENDS.each {
- | backend |
- isSupported = concreteSettings[backend]
- raise unless isSupported != nil
- numClaimedBackends += if isSupported then 1 else 0 end
- if isSupported
- selectedBackend = backend
- end
- }
-
- return if numClaimedBackends > 1
-
- # Resolve the AST down to a low-level form (no macros or conditionals).
- lowLevelAST = ast.resolveSettings(concreteSettings)
-
- yield concreteSettings, lowLevelAST, selectedBackend
-end
-
-#
-# forEachValidSettingsCombination(ast) {
-# | concreteSettings, ast, backend, index | ... }
-#
-# forEachValidSettingsCombination(ast, settingsCombinations) {
-# | concreteSettings, ast, backend, index | ... }
-#
-# Executes the given block for each valid settings combination in the
-# settings map. The ast passed into the block is resolved
-# (ast.resolve) against the settings.
-#
-# The first form will call computeSettingsCombinations(ast) for you.
-#
-
-def forEachValidSettingsCombination(ast, *optionalSettingsCombinations)
- raise if optionalSettingsCombinations.size > 1
-
- if optionalSettingsCombinations.empty?
- settingsCombinations = computeSettingsCombinations(ast)
- else
- settingsCombinations = optionalSettingsCombiations[0]
- end
-
- settingsCombinations.each_with_index {
- | concreteSettings, index |
- forSettings(concreteSettings, ast) {
- | concreteSettings_, lowLevelAST, backend |
- yield concreteSettings, lowLevelAST, backend, index
- }
- }
-end
-
-#
-# cppSettingsTest(concreteSettings)
-#
-# Returns the C++ code used to test if we are in a configuration that
-# corresponds to the given concrete settings.
-#
-
-def cppSettingsTest(concreteSettings)
- "#if " + concreteSettings.to_a.collect{
- | pair |
- (if pair[1]
- ""
- else
- "!"
- end) + "OFFLINE_ASM_" + pair[0]
- }.join(" && ")
-end
-
-#
-# isASTErroneous(ast)
-#
-# Tests to see if the AST claims that there is an error - i.e. if the
-# user's code, after settings resolution, has Error nodes.
-#
-
-def isASTErroneous(ast)
- not ast.filter(Error).empty?
-end
-
-#
-# assertConfiguration(concreteSettings)
-#
-# Emits a check that asserts that we're using the given configuration.
-#
-
-def assertConfiguration(concreteSettings)
- $output.puts cppSettingsTest(concreteSettings)
- $output.puts "#else"
- $output.puts "#error \"Configuration mismatch.\""
- $output.puts "#endif"
-end
-
-#
-# emitCodeInConfiguration(concreteSettings, ast, backend) {
-# | concreteSettings, ast, backend | ... }
-#
-# Emits all relevant guards to see if the configuration holds and
-# calls the block if the configuration is not erroneous.
-#
-
-def emitCodeInConfiguration(concreteSettings, ast, backend)
- $output.puts cppSettingsTest(concreteSettings)
-
- if isASTErroneous(ast)
- $output.puts "#error \"Invalid configuration.\""
- elsif not WORKING_BACKENDS.include? backend
- $output.puts "#error \"This backend is not supported yet.\""
- else
- yield concreteSettings, ast, backend
- end
-
- $output.puts "#endif"
-end
-
-#
-# emitCodeInAllConfigurations(ast) {
-# | concreteSettings, ast, backend, index | ... }
-#
-# Emits guard codes for all valid configurations, and calls the block
-# for those configurations that are valid and not erroneous.
-#
-
-def emitCodeInAllConfigurations(ast)
- forEachValidSettingsCombination(ast) {
- | concreteSettings, lowLevelAST, backend, index |
- $output.puts cppSettingsTest(concreteSettings)
- yield concreteSettings, lowLevelAST, backend, index
- $output.puts "#endif"
- }
-end
-
-
-
+++ /dev/null
-# Copyright (C) 2011 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
-# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-# THE POSSIBILITY OF SUCH DAMAGE.
-
-require "ast"
-
-#
-# node.resolveSettings(settings)
-#
-# Construct a new AST that does not have any IfThenElse nodes by
-# substituting concrete boolean values for each Setting.
-#
-
-class Node
- def resolveSettings(settings)
- mapChildren {
- | child |
- child.resolveSettings(settings)
- }
- end
-end
-
-class True
- def resolveSettings(settings)
- self
- end
-end
-
-class False
- def resolveSettings(settings)
- self
- end
-end
-
-class Setting
- def resolveSettings(settings)
- settings[@name].asNode
- end
-end
-
-class And
- def resolveSettings(settings)
- (@left.resolveSettings(settings).value and @right.resolveSettings(settings).value).asNode
- end
-end
-
-class Or
- def resolveSettings(settings)
- (@left.resolveSettings(settings).value or @right.resolveSettings(settings).value).asNode
- end
-end
-
-class Not
- def resolveSettings(settings)
- (not @child.resolveSettings(settings).value).asNode
- end
-end
-
-class IfThenElse
- def resolveSettings(settings)
- if @predicate.resolveSettings(settings).value
- @thenCase.resolveSettings(settings)
- else
- @elseCase.resolveSettings(settings)
- end
- end
-end
-
-class Sequence
- def resolveSettings(settings)
- newList = []
- @list.each {
- | item |
- item = item.resolveSettings(settings)
- if item.is_a? Sequence
- newList += item.list
- else
- newList << item
- end
- }
- Sequence.new(codeOrigin, newList)
- end
-end
-
-#
-# node.demacroify(macros)
-# node.substitute(mapping)
-#
-# demacroify() constructs a new AST that does not have any Macro
-# nodes, while substitute() replaces Variable nodes with the given
-# nodes in the mapping.
-#
-
-class Node
- def demacroify(macros)
- mapChildren {
- | child |
- child.demacroify(macros)
- }
- end
-
- def substitute(mapping)
- mapChildren {
- | child |
- child.substitute(mapping)
- }
- end
-
- def substituteLabels(mapping)
- mapChildren {
- | child |
- child.substituteLabels(mapping)
- }
- end
-end
-
-class Macro
- def substitute(mapping)
- myMapping = {}
- mapping.each_pair {
- | key, value |
- unless @variables.include? key
- myMapping[key] = value
- end
- }
- mapChildren {
- | child |
- child.substitute(myMapping)
- }
- end
-end
-
-class Variable
- def substitute(mapping)
- if mapping[self]
- mapping[self]
- else
- self
- end
- end
-end
-
-class LocalLabel
- def substituteLabels(mapping)
- if mapping[self]
- mapping[self]
- else
- self
- end
- end
-end
-
-class Sequence
- def substitute(constants)
- newList = []
- myConstants = constants.dup
- @list.each {
- | item |
- if item.is_a? ConstDecl
- myConstants[item.variable] = item.value.substitute(myConstants)
- else
- newList << item.substitute(myConstants)
- end
- }
- Sequence.new(codeOrigin, newList)
- end
-
- def renameLabels(comment)
- mapping = {}
-
- @list.each {
- | item |
- if item.is_a? LocalLabel
- mapping[item] = LocalLabel.unique(if comment then comment + "_" else "" end + item.cleanName)
- end
- }
-
- substituteLabels(mapping)
- end
-
- def demacroify(macros)
- myMacros = macros.dup
- @list.each {
- | item |
- if item.is_a? Macro
- myMacros[item.name] = item
- end
- }
- newList = []
- @list.each {
- | item |
- if item.is_a? Macro
- # Ignore.
- elsif item.is_a? MacroCall
- mapping = {}
- myMyMacros = myMacros.dup
- raise "Could not find macro #{item.name} at #{item.codeOriginString}" unless myMacros[item.name]
- raise "Argument count mismatch for call to #{item.name} at #{item.codeOriginString}" unless item.operands.size == myMacros[item.name].variables.size
- item.operands.size.times {
- | idx |
- if item.operands[idx].is_a? Variable and myMacros[item.operands[idx].name]
- myMyMacros[myMacros[item.name].variables[idx].name] = myMacros[item.operands[idx].name]
- mapping[myMacros[item.name].variables[idx].name] = nil
- elsif item.operands[idx].is_a? Macro
- myMyMacros[myMacros[item.name].variables[idx].name] = item.operands[idx]
- mapping[myMacros[item.name].variables[idx].name] = nil
- else
- myMyMacros[myMacros[item.name].variables[idx]] = nil
- mapping[myMacros[item.name].variables[idx]] = item.operands[idx]
- end
- }
- newList += myMacros[item.name].body.substitute(mapping).demacroify(myMyMacros).renameLabels(item.name).list
- else
- newList << item.demacroify(myMacros)
- end
- }
- Sequence.new(codeOrigin, newList).substitute({})
- end
-end
-
-#
-# node.resolveOffsets(offsets, sizes)
-#
-# Construct a new AST that has offset values instead of symbolic
-# offsets.
-#
-
-class Node
- def resolveOffsets(offsets, sizes)
- mapChildren {
- | child |
- child.resolveOffsets(offsets, sizes)
- }
- end
-end
-
-class StructOffset
- def resolveOffsets(offsets, sizes)
- if offsets[self]
- Immediate.new(codeOrigin, offsets[self])
- else
- self
- end
- end
-end
-
-class Sizeof
- def resolveOffsets(offsets, sizes)
- if sizes[self]
- Immediate.new(codeOrigin, sizes[self])
- else
- puts "Could not find #{self.inspect} in #{sizes.keys.inspect}"
- puts "sizes = #{sizes.inspect}"
- self
- end
- end
-end
-
-#
-# node.fold
-#
-# Resolve constant references and compute arithmetic expressions.
-#
-
-class Node
- def fold
- mapChildren {
- | child |
- child.fold
- }
- end
-end
-
-class AddImmediates
- def fold
- @left = @left.fold
- @right = @right.fold
- return self unless @left.is_a? Immediate
- return self unless @right.is_a? Immediate
- Immediate.new(codeOrigin, @left.value + @right.value)
- end
-end
-
-class SubImmediates
- def fold
- @left = @left.fold
- @right = @right.fold
- return self unless @left.is_a? Immediate
- return self unless @right.is_a? Immediate
- Immediate.new(codeOrigin, @left.value - @right.value)
- end
-end
-
-class MulImmediates
- def fold
- @left = @left.fold
- @right = @right.fold
- return self unless @left.is_a? Immediate
- return self unless @right.is_a? Immediate
- Immediate.new(codeOrigin, @left.value * @right.value)
- end
-end
-
-class NegImmediate
- def fold
- @child = @child.fold
- return self unless @child.is_a? Immediate
- Immediate.new(codeOrigin, -@child.value)
- end
-end
-
-#
-# node.resolveAfterSettings(offsets, sizes)
-#
-# Compile assembly against a set of offsets.
-#
-
-class Node
- def resolve(offsets, sizes)
- demacroify({}).resolveOffsets(offsets, sizes).fold
- end
-end
-
+++ /dev/null
-# Copyright (C) 2011 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
-# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-# THE POSSIBILITY OF SUCH DAMAGE.
-
-class RegisterID
- def supports8BitOnX86
- case name
- when "t0", "a0", "r0", "t1", "a1", "r1", "t2", "t3"
- true
- when "t4", "cfr"
- false
- else
- raise
- end
- end
-
- def x86Operand(kind)
- case name
- when "t0", "a0", "r0"
- case kind
- when :byte
- "%al"
- when :half
- "%ax"
- when :int
- "%eax"
- else
- raise
- end
- when "t1", "a1", "r1"
- case kind
- when :byte
- "%dl"
- when :half
- "%dx"
- when :int
- "%edx"
- else
- raise
- end
- when "t2"
- case kind
- when :byte
- "%cl"
- when :half
- "%cx"
- when :int
- "%ecx"
- else
- raise
- end
- when "t3"
- case kind
- when :byte
- "%bl"
- when :half
- "%bx"
- when :int
- "%ebx"
- else
- raise
- end
- when "t4"
- case kind
- when :byte
- "%sil"
- when :half
- "%si"
- when :int
- "%esi"
- else
- raise
- end
- when "cfr"
- case kind
- when :byte
- "%dil"
- when :half
- "%di"
- when :int
- "%edi"
- else
- raise
- end
- when "sp"
- case kind
- when :byte
- "%spl"
- when :half
- "%sp"
- when :int
- "%esp"
- else
- raise
- end
- else
- raise "Bad register #{name} for X86 at #{codeOriginString}"
- end
- end
- def x86CallOperand(kind)
- "*#{x86Operand(kind)}"
- end
-end
-
-class FPRegisterID
- def x86Operand(kind)
- raise unless kind == :double
- case name
- when "ft0", "fa0", "fr"
- "%xmm0"
- when "ft1", "fa1"
- "%xmm1"
- when "ft2", "fa2"
- "%xmm2"
- when "ft3", "fa3"
- "%xmm3"
- when "ft4"
- "%xmm4"
- when "ft5"
- "%xmm5"
- else
- raise "Bad register #{name} for X86 at #{codeOriginString}"
- end
- end
- def x86CallOperand(kind)
- "*#{x86Operand(kind)}"
- end
-end
-
-class Immediate
- def x86Operand(kind)
- "$#{value}"
- end
- def x86CallOperand(kind)
- "#{value}"
- end
-end
-
-class Address
- def supports8BitOnX86
- true
- end
-
- def x86Operand(kind)
- "#{offset.value}(#{base.x86Operand(:int)})"
- end
- def x86CallOperand(kind)
- "*#{x86Operand(kind)}"
- end
-end
-
-class BaseIndex
- def supports8BitOnX86
- true
- end
-
- def x86Operand(kind)
- "#{offset.value}(#{base.x86Operand(:int)}, #{index.x86Operand(:int)}, #{scale})"
- end
-
- def x86CallOperand(kind)
- "*#{x86operand(kind)}"
- end
-end
-
-class AbsoluteAddress
- def supports8BitOnX86
- true
- end
-
- def x86Operand(kind)
- "#{address.value}"
- end
-
- def x86CallOperand(kind)
- "*#{address.value}"
- end
-end
-
-class LabelReference
- def x86CallOperand(kind)
- asmLabel
- end
-end
-
-class LocalLabelReference
- def x86CallOperand(kind)
- asmLabel
- end
-end
-
-class Instruction
- def x86Operands(*kinds)
- raise unless kinds.size == operands.size
- result = []
- kinds.size.times {
- | idx |
- result << operands[idx].x86Operand(kinds[idx])
- }
- result.join(", ")
- end
-
- def x86Suffix(kind)
- case kind
- when :byte
- "b"
- when :half
- "w"
- when :int
- "l"
- when :double
- "sd"
- else
- raise
- end
- end
-
- def handleX86OpWithNumOperands(opcode, kind, numOperands)
- if numOperands == 3
- if operands[0] == operands[2]
- $asm.puts "#{opcode} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
- elsif operands[1] == operands[2]
- $asm.puts "#{opcode} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
- else
- $asm.puts "mov#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
- $asm.puts "#{opcode} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
- end
- else
- $asm.puts "#{opcode} #{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}"
- end
- end
-
- def handleX86Op(opcode, kind)
- handleX86OpWithNumOperands(opcode, kind, operands.size)
- end
-
- def handleX86Shift(opcode, kind)
- if operands[0].is_a? Immediate or operands[0] == RegisterID.forName(nil, "t2")
- $asm.puts "#{opcode} #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(kind)}"
- else
- $asm.puts "xchgl #{operands[0].x86Operand(:int)}, %ecx"
- $asm.puts "#{opcode} %cl, #{operands[1].x86Operand(kind)}"
- $asm.puts "xchgl #{operands[0].x86Operand(:int)}, %ecx"
- end
- end
-
- def handleX86DoubleBranch(branchOpcode, mode)
- case mode
- when :normal
- $asm.puts "ucomisd #{operands[1].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
- when :reverse
- $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
- else
- raise mode.inspect
- end
- $asm.puts "#{branchOpcode} #{operands[2].asmLabel}"
- end
-
- def handleX86IntCompare(opcodeSuffix, kind)
- if operands[0].is_a? Immediate and operands[0].value == 0 and operands[1].is_a? RegisterID and (opcodeSuffix == "e" or opcodeSuffix == "ne")
- $asm.puts "test#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}"
- elsif operands[1].is_a? Immediate and operands[1].value == 0 and operands[0].is_a? RegisterID and (opcodeSuffix == "e" or opcodeSuffix == "ne")
- $asm.puts "test#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}"
- else
- $asm.puts "cmp#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[0].x86Operand(kind)}"
- end
- end
-
- def handleX86IntBranch(branchOpcode, kind)
- handleX86IntCompare(branchOpcode[1..-1], kind)
- $asm.puts "#{branchOpcode} #{operands[2].asmLabel}"
- end
-
- def handleX86Set(setOpcode, operand)
- if operand.supports8BitOnX86
- $asm.puts "#{setOpcode} #{operand.x86Operand(:byte)}"
- $asm.puts "movzbl #{operand.x86Operand(:byte)}, #{operand.x86Operand(:int)}"
- else
- $asm.puts "xchgl #{operand.x86Operand(:int)}, %eax"
- $asm.puts "#{setOpcode} %al"
- $asm.puts "movzbl %al, %eax"
- $asm.puts "xchgl #{operand.x86Operand(:int)}, %eax"
- end
- end
-
- def handleX86IntCompareSet(setOpcode, kind)
- handleX86IntCompare(setOpcode[3..-1], kind)
- handleX86Set(setOpcode, operands[2])
- end
-
- def handleX86Test(kind)
- value = operands[0]
- case operands.size
- when 2
- mask = Immediate.new(codeOrigin, -1)
- when 3
- mask = operands[1]
- else
- raise "Expected 2 or 3 operands, but got #{operands.size} at #{codeOriginString}"
- end
-
- if mask.is_a? Immediate and mask.value == -1
- if value.is_a? RegisterID
- $asm.puts "test#{x86Suffix(kind)} #{value.x86Operand(kind)}, #{value.x86Operand(kind)}"
- else
- $asm.puts "cmp#{x86Suffix(kind)} $0, #{value.x86Operand(kind)}"
- end
- else
- $asm.puts "test#{x86Suffix(kind)} #{mask.x86Operand(kind)}, #{value.x86Operand(kind)}"
- end
- end
-
- def handleX86BranchTest(branchOpcode, kind)
- handleX86Test(kind)
- $asm.puts "#{branchOpcode} #{operands.last.asmLabel}"
- end
-
- def handleX86SetTest(setOpcode, kind)
- handleX86Test(kind)
- handleX86Set(setOpcode, operands.last)
- end
-
- def handleX86OpBranch(opcode, branchOpcode, kind)
- handleX86OpWithNumOperands(opcode, kind, operands.size - 1)
- case operands.size
- when 4
- jumpTarget = operands[3]
- when 3
- jumpTarget = operands[2]
- else
- raise self.inspect
- end
- $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}"
- end
-
- def handleX86SubBranch(branchOpcode, kind)
- if operands.size == 4 and operands[1] == operands[2]
- $asm.puts "negl #{operands[2].x86Operand(:int)}"
- $asm.puts "addl #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:int)}"
- else
- handleX86OpWithNumOperands("sub#{x86Suffix(kind)}", kind, operands.size - 1)
- end
- case operands.size
- when 4
- jumpTarget = operands[3]
- when 3
- jumpTarget = operands[2]
- else
- raise self.inspect
- end
- $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}"
- end
-
- def lowerX86
- $asm.comment codeOriginString
- case opcode
- when "addi", "addp"
- if operands.size == 3 and operands[0].is_a? Immediate
- raise unless operands[1].is_a? RegisterID
- raise unless operands[2].is_a? RegisterID
- if operands[0].value == 0
- unless operands[1] == operands[2]
- $asm.puts "movl #{operands[1].x86Operand(:int)}, #{operands[2].x86Operand(:int)}"
- end
- else
- $asm.puts "leal #{operands[0].value}(#{operands[1].x86Operand(:int)}), #{operands[2].x86Operand(:int)}"
- end
- elsif operands.size == 3 and operands[0].is_a? RegisterID
- raise unless operands[1].is_a? RegisterID
- raise unless operands[2].is_a? RegisterID
- $asm.puts "leal (#{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}), #{operands[2].x86Operand(:int)}"
- else
- unless Immediate.new(nil, 0) == operands[0]
- $asm.puts "addl #{x86Operands(:int, :int)}"
- end
- end
- when "andi", "andp"
- handleX86Op("andl", :int)
- when "lshifti"
- handleX86Shift("sall", :int)
- when "muli"
- if operands.size == 3 and operands[0].is_a? Immediate
- $asm.puts "imull #{x86Operands(:int, :int, :int)}"
- else
- # FIXME: could do some peephole in case the left operand is immediate and it's
- # a power of two.
- handleX86Op("imull", :int)
- end
- when "negi"
- $asm.puts "negl #{x86Operands(:int)}"
- when "noti"
- $asm.puts "notl #{x86Operands(:int)}"
- when "ori", "orp"
- handleX86Op("orl", :int)
- when "rshifti"
- handleX86Shift("sarl", :int)
- when "urshifti"
- handleX86Shift("shrl", :int)
- when "subi", "subp"
- if operands.size == 3 and operands[1] == operands[2]
- $asm.puts "negl #{operands[2].x86Operand(:int)}"
- $asm.puts "addl #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:int)}"
- else
- handleX86Op("subl", :int)
- end
- when "xori", "xorp"
- handleX86Op("xorl", :int)
- when "loadi", "storei", "loadp", "storep"
- $asm.puts "movl #{x86Operands(:int, :int)}"
- when "loadb"
- $asm.puts "movzbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}"
- when "loadbs"
- $asm.puts "movsbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}"
- when "loadh"
- $asm.puts "movzwl #{operands[0].x86Operand(:half)}, #{operands[1].x86Operand(:int)}"
- when "loadhs"
- $asm.puts "movswl #{operands[0].x86Operand(:half)}, #{operands[1].x86Operand(:int)}"
- when "storeb"
- $asm.puts "movb #{x86Operands(:byte, :byte)}"
- when "loadd", "moved", "stored"
- $asm.puts "movsd #{x86Operands(:double, :double)}"
- when "addd"
- $asm.puts "addsd #{x86Operands(:double, :double)}"
- when "divd"
- $asm.puts "divsd #{x86Operands(:double, :double)}"
- when "subd"
- $asm.puts "subsd #{x86Operands(:double, :double)}"
- when "muld"
- $asm.puts "mulsd #{x86Operands(:double, :double)}"
- when "sqrtd"
- $asm.puts "sqrtsd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
- when "ci2d"
- $asm.puts "cvtsi2sd #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:double)}"
- when "bdeq"
- isUnordered = LocalLabel.unique("bdeq")
- $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
- $asm.puts "jp #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
- $asm.puts "je #{LabelReference.new(codeOrigin, operands[2]).asmLabel}"
- isUnordered.lower("X86")
- when "bdneq"
- handleX86DoubleBranch("jne", :normal)
- when "bdgt"
- handleX86DoubleBranch("ja", :normal)
- when "bdgteq"
- handleX86DoubleBranch("jae", :normal)
- when "bdlt"
- handleX86DoubleBranch("ja", :reverse)
- when "bdlteq"
- handleX86DoubleBranch("jae", :reverse)
- when "bdequn"
- handleX86DoubleBranch("je", :normal)
- when "bdnequn"
- isUnordered = LocalLabel.unique("bdnequn")
- isEqual = LocalLabel.unique("bdnequn")
- $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
- $asm.puts "jp #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
- $asm.puts "je #{LabelReference.new(codeOrigin, isEqual).asmLabel}"
- isUnordered.lower("X86")
- $asm.puts "jmp #{operands[2].asmLabel}"
- isEqual.lower("X86")
- when "bdgtun"
- handleX86DoubleBranch("jb", :reverse)
- when "bdgtequn"
- handleX86DoubleBranch("jbe", :reverse)
- when "bdltun"
- handleX86DoubleBranch("jb", :normal)
- when "bdltequn"
- handleX86DoubleBranch("jbe", :normal)
- when "btd2i"
- $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
- $asm.puts "cmpl $0x80000000 #{operands[1].x86Operand(:int)}"
- $asm.puts "je #{operands[2].asmLabel}"
- when "td2i"
- $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
- when "bcd2i"
- $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
- $asm.puts "testl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
- $asm.puts "je #{operands[2].asmLabel}"
- $asm.puts "cvtsi2sd #{operands[1].x86Operand(:int)}, %xmm7"
- $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, %xmm7"
- $asm.puts "jp #{operands[2].asmLabel}"
- $asm.puts "jne #{operands[2].asmLabel}"
- when "movdz"
- $asm.puts "xorpd #{operands[0].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
- when "pop"
- $asm.puts "pop #{operands[0].x86Operand(:int)}"
- when "push"
- $asm.puts "push #{operands[0].x86Operand(:int)}"
- when "move", "sxi2p", "zxi2p"
- if Immediate.new(nil, 0) == operands[0] and operands[1].is_a? RegisterID
- $asm.puts "xorl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
- elsif operands[0] != operands[1]
- $asm.puts "movl #{x86Operands(:int, :int)}"
- end
- when "nop"
- $asm.puts "nop"
- when "bieq", "bpeq"
- handleX86IntBranch("je", :int)
- when "bineq", "bpneq"
- handleX86IntBranch("jne", :int)
- when "bia", "bpa"
- handleX86IntBranch("ja", :int)
- when "biaeq", "bpaeq"
- handleX86IntBranch("jae", :int)
- when "bib", "bpb"
- handleX86IntBranch("jb", :int)
- when "bibeq", "bpbeq"
- handleX86IntBranch("jbe", :int)
- when "bigt", "bpgt"
- handleX86IntBranch("jg", :int)
- when "bigteq", "bpgteq"
- handleX86IntBranch("jge", :int)
- when "bilt", "bplt"
- handleX86IntBranch("jl", :int)
- when "bilteq", "bplteq"
- handleX86IntBranch("jle", :int)
- when "bbeq"
- handleX86IntBranch("je", :byte)
- when "bbneq"
- handleX86IntBranch("jne", :byte)
- when "bba"
- handleX86IntBranch("ja", :byte)
- when "bbaeq"
- handleX86IntBranch("jae", :byte)
- when "bbb"
- handleX86IntBranch("jb", :byte)
- when "bbbeq"
- handleX86IntBranch("jbe", :byte)
- when "bbgt"
- handleX86IntBranch("jg", :byte)
- when "bbgteq"
- handleX86IntBranch("jge", :byte)
- when "bblt"
- handleX86IntBranch("jl", :byte)
- when "bblteq"
- handleX86IntBranch("jlteq", :byte)
- when "btio", "btpo"
- handleX86BranchTest("jo", :int)
- when "btis", "btps"
- handleX86BranchTest("js", :int)
- when "btiz", "btpz"
- handleX86BranchTest("jz", :int)
- when "btinz", "btpnz"
- handleX86BranchTest("jnz", :int)
- when "btbo"
- handleX86BranchTest("jo", :byte)
- when "btbs"
- handleX86BranchTest("js", :byte)
- when "btbz"
- handleX86BranchTest("jz", :byte)
- when "btbnz"
- handleX86BranchTest("jnz", :byte)
- when "jmp"
- $asm.puts "jmp #{operands[0].x86CallOperand(:int)}"
- when "baddio", "baddpo"
- handleX86OpBranch("addl", "jo", :int)
- when "baddis", "baddps"
- handleX86OpBranch("addl", "js", :int)
- when "baddiz", "baddpz"
- handleX86OpBranch("addl", "jz", :int)
- when "baddinz", "baddpnz"
- handleX86OpBranch("addl", "jnz", :int)
- when "bsubio"
- handleX86SubBranch("jo", :int)
- when "bsubis"
- handleX86SubBranch("js", :int)
- when "bsubiz"
- handleX86SubBranch("jz", :int)
- when "bsubinz"
- handleX86SubBranch("jnz", :int)
- when "bmulio"
- handleX86OpBranch("imull", "jo", :int)
- when "bmulis"
- handleX86OpBranch("imull", "js", :int)
- when "bmuliz"
- handleX86OpBranch("imull", "jz", :int)
- when "bmulinz"
- handleX86OpBranch("imull", "jnz", :int)
- when "borio"
- handleX86OpBranch("orl", "jo", :int)
- when "boris"
- handleX86OpBranch("orl", "js", :int)
- when "boriz"
- handleX86OpBranch("orl", "jz", :int)
- when "borinz"
- handleX86OpBranch("orl", "jnz", :int)
- when "break"
- $asm.puts "int $3"
- when "call"
- $asm.puts "call #{operands[0].x86CallOperand(:int)}"
- when "ret"
- $asm.puts "ret"
- when "cieq", "cpeq"
- handleX86IntCompareSet("sete", :int)
- when "cineq", "cpneq"
- handleX86IntCompareSet("setne", :int)
- when "cia", "cpa"
- handleX86IntCompareSet("seta", :int)
- when "ciaeq", "cpaeq"
- handleX86IntCompareSet("setae", :int)
- when "cib", "cpb"
- handleX86IntCompareSet("setb", :int)
- when "cibeq", "cpbeq"
- handleX86IntCompareSet("setbe", :int)
- when "cigt", "cpgt"
- handleX86IntCompareSet("setg", :int)
- when "cigteq", "cpgteq"
- handleX86IntCompareSet("setge", :int)
- when "cilt", "cplt"
- handleX86IntCompareSet("setl", :int)
- when "cilteq", "cplteq"
- handleX86IntCompareSet("setle", :int)
- when "tio"
- handleX86SetTest("seto", :int)
- when "tis"
- handleX86SetTest("sets", :int)
- when "tiz"
- handleX86SetTest("setz", :int)
- when "tinz"
- handleX86SetTest("setnz", :int)
- when "tbo"
- handleX86SetTest("seto", :byte)
- when "tbs"
- handleX86SetTest("sets", :byte)
- when "tbz"
- handleX86SetTest("setz", :byte)
- when "tbnz"
- handleX86SetTest("setnz", :byte)
- when "peek"
- $asm.puts "movl #{operands[0].value * 4}(%esp), #{operands[1].x86Operand(:int)}"
- when "poke"
- $asm.puts "movl #{operands[0].x86Operand(:int)}, #{operands[1].value * 4}(%esp)"
- when "cdqi"
- $asm.puts "cdq"
- when "idivi"
- $asm.puts "idivl #{operands[0].x86Operand(:int)}"
- when "fii2d"
- $asm.puts "movd #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:double)}"
- $asm.puts "movd #{operands[1].x86Operand(:int)}, %xmm7"
- $asm.puts "psllq $32, %xmm7"
- $asm.puts "por %xmm7, #{operands[2].x86Operand(:double)}"
- when "fd2ii"
- $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
- $asm.puts "movsd #{operands[0].x86Operand(:double)}, %xmm7"
- $asm.puts "psrlq $32, %xmm7"
- $asm.puts "movsd %xmm7, #{operands[2].x86Operand(:int)}"
- when "bo"
- $asm.puts "jo #{operands[0].asmLabel}"
- when "bs"
- $asm.puts "js #{operands[0].asmLabel}"
- when "bz"
- $asm.puts "jz #{operands[0].asmLabel}"
- when "bnz"
- $asm.puts "jnz #{operands[0].asmLabel}"
- when "leai", "leap"
- $asm.puts "leal #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
- else
- raise "Bad opcode: #{opcode}"
- end
- end
-end
-
+++ /dev/null
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CodeSpecializationKind_h
-#define CodeSpecializationKind_h
-
-namespace JSC {
-
-enum CodeSpecializationKind { CodeForCall, CodeForConstruct };
-
-} // namespace JSC
-
-#endif // CodeSpecializationKind_h
-
#define CommonSlowPaths_h
#include "CodeBlock.h"
-#include "CodeSpecializationKind.h"
#include "ExceptionHelpers.h"
#include "JSArray.h"
namespace CommonSlowPaths {
-ALWAYS_INLINE ExecState* arityCheckFor(ExecState* exec, RegisterFile* registerFile, CodeSpecializationKind kind)
-{
- JSFunction* callee = asFunction(exec->callee());
- ASSERT(!callee->isHostFunction());
- CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecodeFor(kind);
- int argumentCountIncludingThis = exec->argumentCountIncludingThis();
-
- // This ensures enough space for the worst case scenario of zero arguments passed by the caller.
- if (!registerFile->grow(exec->registers() + newCodeBlock->numParameters() + newCodeBlock->m_numCalleeRegisters))
- return 0;
-
- ASSERT(argumentCountIncludingThis < newCodeBlock->numParameters());
-
- // Too few arguments -- copy call frame and arguments, then fill in missing arguments with undefined.
- size_t delta = newCodeBlock->numParameters() - argumentCountIncludingThis;
- Register* src = exec->registers();
- Register* dst = exec->registers() + delta;
-
- int i;
- int end = -ExecState::offsetFor(argumentCountIncludingThis);
- for (i = -1; i >= end; --i)
- dst[i] = src[i];
-
- end -= delta;
- for ( ; i >= end; --i)
- dst[i] = jsUndefined();
-
- ExecState* newExec = ExecState::create(dst);
- ASSERT((void*)newExec <= registerFile->end());
- return newExec;
-}
-
ALWAYS_INLINE bool opInstanceOfSlow(ExecState* exec, JSValue value, JSValue baseVal, JSValue proto)
{
ASSERT(!value.isCell() || !baseVal.isCell() || !proto.isCell()
#include "BytecodeGenerator.h"
#include "CodeBlock.h"
#include "DFGDriver.h"
-#include "ExecutionHarness.h"
#include "JIT.h"
#include "JITDriver.h"
#include "Parser.h"
template<typename T>
static void jettisonCodeBlock(JSGlobalData& globalData, OwnPtr<T>& codeBlock)
{
- ASSERT(JITCode::isOptimizingJIT(codeBlock->getJITType()));
+ ASSERT(codeBlock->getJITType() != JITCode::BaselineJIT);
ASSERT(codeBlock->alternative());
OwnPtr<T> codeBlockToJettison = codeBlock.release();
codeBlock = static_pointer_cast<T>(codeBlockToJettison->releaseAlternative());
return error;
}
-#if ENABLE(JIT)
-void EvalExecutable::jitCompile(JSGlobalData& globalData)
-{
- bool result = jitCompileIfAppropriate(globalData, m_evalCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT());
- ASSERT_UNUSED(result, result);
-}
-#endif
-
-inline const char* samplingDescription(JITCode::JITType jitType)
-{
- switch (jitType) {
- case JITCode::InterpreterThunk:
- return "Interpreter Compilation (TOTAL)";
- case JITCode::BaselineJIT:
- return "Baseline Compilation (TOTAL)";
- case JITCode::DFGJIT:
- return "DFG Compilation (TOTAL)";
- default:
- ASSERT_NOT_REACHED();
- return 0;
- }
-}
-
JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
{
- SamplingRegion samplingRegion(samplingDescription(jitType));
+ SamplingRegion samplingRegion(jitType == JITCode::BaselineJIT ? "Baseline Compilation (TOTAL)" : "DFG Compilation (TOTAL)");
#if !ENABLE(JIT)
UNUSED_PARAM(jitType);
}
#if ENABLE(JIT)
- if (!prepareForExecution(*globalData, m_evalCodeBlock, m_jitCodeForCall, jitType))
+ if (!jitCompileIfAppropriate(*globalData, m_evalCodeBlock, m_jitCodeForCall, jitType))
return 0;
#endif
return error;
}
-#if ENABLE(JIT)
-void ProgramExecutable::jitCompile(JSGlobalData& globalData)
-{
- bool result = jitCompileIfAppropriate(globalData, m_programCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT());
- ASSERT_UNUSED(result, result);
-}
-#endif
-
JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
{
- SamplingRegion samplingRegion(samplingDescription(jitType));
+ SamplingRegion samplingRegion(jitType == JITCode::BaselineJIT ? "Baseline Compilation (TOTAL)" : "DFG Compilation (TOTAL)");
#if !ENABLE(JIT)
UNUSED_PARAM(jitType);
}
#if ENABLE(JIT)
- if (!prepareForExecution(*globalData, m_programCodeBlock, m_jitCodeForCall, jitType))
+ if (!jitCompileIfAppropriate(*globalData, m_programCodeBlock, m_jitCodeForCall, jitType))
return 0;
#endif
while (result->alternative())
result = static_cast<FunctionCodeBlock*>(result->alternative());
ASSERT(result);
- ASSERT(JITCode::isBaselineCode(result->getJITType()));
+ ASSERT(result->getJITType() == JITCode::BaselineJIT);
return result;
}
return error;
}
-#if ENABLE(JIT)
-void FunctionExecutable::jitCompileForCall(JSGlobalData& globalData)
-{
- bool result = jitCompileFunctionIfAppropriate(globalData, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, JITCode::bottomTierJIT());
- ASSERT_UNUSED(result, result);
-}
-
-void FunctionExecutable::jitCompileForConstruct(JSGlobalData& globalData)
-{
- bool result = jitCompileFunctionIfAppropriate(globalData, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, JITCode::bottomTierJIT());
- ASSERT_UNUSED(result, result);
-}
-#endif
-
FunctionCodeBlock* FunctionExecutable::codeBlockWithBytecodeFor(CodeSpecializationKind kind)
{
FunctionCodeBlock* codeBlock = baselineCodeBlockFor(kind);
JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
{
- SamplingRegion samplingRegion(samplingDescription(jitType));
+ SamplingRegion samplingRegion(jitType == JITCode::BaselineJIT ? "Baseline Compilation (TOTAL)" : "DFG Compilation (TOTAL)");
#if !ENABLE(JIT)
UNUSED_PARAM(exec);
m_symbolTable = m_codeBlockForCall->sharedSymbolTable();
#if ENABLE(JIT)
- if (!prepareFunctionForExecution(exec->globalData(), m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, jitType, CodeForCall))
+ if (!jitCompileFunctionIfAppropriate(exec->globalData(), m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, jitType))
return 0;
#endif
JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
{
- SamplingRegion samplingRegion(samplingDescription(jitType));
+ SamplingRegion samplingRegion(jitType == JITCode::BaselineJIT ? "Baseline Compilation (TOTAL)" : "DFG Compilation (TOTAL)");
#if !ENABLE(JIT)
UNUSED_PARAM(jitType);
m_symbolTable = m_codeBlockForConstruct->sharedSymbolTable();
#if ENABLE(JIT)
- if (!prepareFunctionForExecution(exec->globalData(), m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, jitType, CodeForConstruct))
+ if (!jitCompileFunctionIfAppropriate(exec->globalData(), m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, jitType))
return 0;
#endif
#define Executable_h
#include "CallData.h"
-#include "CodeSpecializationKind.h"
#include "JSFunction.h"
#include "Interpreter.h"
#include "Nodes.h"
class Debugger;
class EvalCodeBlock;
class FunctionCodeBlock;
- class LLIntOffsetsExtractor;
class ProgramCodeBlock;
class ScopeChainNode;
struct ExceptionInfo;
+ enum CodeSpecializationKind { CodeForCall, CodeForConstruct };
enum CompilationKind { FirstCompilation, OptimizingCompilation };
inline bool isCall(CodeSpecializationKind kind)
};
class EvalExecutable : public ScriptExecutable {
- friend class LLIntOffsetsExtractor;
public:
typedef ScriptExecutable Base;
#if ENABLE(JIT)
void jettisonOptimizedCode(JSGlobalData&);
- void jitCompile(JSGlobalData&);
#endif
EvalCodeBlock& generatedBytecode()
};
class ProgramExecutable : public ScriptExecutable {
- friend class LLIntOffsetsExtractor;
public:
typedef ScriptExecutable Base;
#if ENABLE(JIT)
void jettisonOptimizedCode(JSGlobalData&);
- void jitCompile(JSGlobalData&);
#endif
ProgramCodeBlock& generatedBytecode()
class FunctionExecutable : public ScriptExecutable {
friend class JIT;
- friend class LLIntOffsetsExtractor;
public:
typedef ScriptExecutable Base;
#if ENABLE(JIT)
void jettisonOptimizedCodeForCall(JSGlobalData&);
- void jitCompileForCall(JSGlobalData&);
#endif
bool isGeneratedForCall() const
#if ENABLE(JIT)
void jettisonOptimizedCodeForConstruct(JSGlobalData&);
- void jitCompileForConstruct(JSGlobalData&);
#endif
bool isGeneratedForConstruct() const
jettisonOptimizedCodeForConstruct(globalData);
}
}
-
- void jitCompileFor(JSGlobalData& globalData, CodeSpecializationKind kind)
- {
- if (kind == CodeForCall) {
- jitCompileForCall(globalData);
- return;
- }
- ASSERT(kind == CodeForConstruct);
- jitCompileForConstruct(globalData);
- }
#endif
bool isGeneratedFor(CodeSpecializationKind kind)
+++ /dev/null
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef ExecutionHarness_h
-#define ExecutionHarness_h
-
-#include <wtf/Platform.h>
-
-#if ENABLE(JIT)
-
-#include "JITDriver.h"
-#include "LLIntEntrypoints.h"
-
-namespace JSC {
-
-template<typename CodeBlockType>
-inline bool prepareForExecution(JSGlobalData& globalData, OwnPtr<CodeBlockType>& codeBlock, JITCode& jitCode, JITCode::JITType jitType)
-{
-#if ENABLE(LLINT)
- if (JITCode::isBaselineCode(jitType)) {
- // Start off in the low level interpreter.
- LLInt::getEntrypoint(globalData, codeBlock.get(), jitCode);
- codeBlock->setJITCode(jitCode, MacroAssemblerCodePtr());
- return true;
- }
-#endif // ENABLE(LLINT)
- return jitCompileIfAppropriate(globalData, codeBlock, jitCode, jitType);
-}
-
-inline bool prepareFunctionForExecution(JSGlobalData& globalData, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType, CodeSpecializationKind kind)
-{
-#if ENABLE(LLINT)
- if (JITCode::isBaselineCode(jitType)) {
- // Start off in the low level interpreter.
- LLInt::getFunctionEntrypoint(globalData, kind, jitCode, jitCodeWithArityCheck);
- codeBlock->setJITCode(jitCode, jitCodeWithArityCheck);
- return true;
- }
-#else
- UNUSED_PARAM(kind);
-#endif // ENABLE(LLINT)
- return jitCompileFunctionIfAppropriate(globalData, codeBlock, jitCode, jitCodeWithArityCheck, symbolTable, jitType);
-}
-
-} // namespace JSC
-
-#endif // ENABLE(JIT)
-
-#endif // ExecutionHarness_h
-
namespace JSC {
class JSArray;
- class LLIntOffsetsExtractor;
struct SparseArrayEntry : public WriteBarrier<Unknown> {
typedef WriteBarrier<Unknown> Base;
};
class JSArray : public JSNonFinalObject {
- friend class LLIntOffsetsExtractor;
friend class Walker;
protected:
namespace JSC {
class JSGlobalObject;
- class LLIntOffsetsExtractor;
+ class Structure;
class PropertyDescriptor;
class PropertyNameArray;
- class Structure;
enum EnumerationMode {
ExcludeDontEnumProperties,
static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
private:
- friend class LLIntOffsetsExtractor;
-
const ClassInfo* m_classInfo;
WriteBarrier<Structure> m_structure;
};
class FunctionPrototype;
class JSActivation;
class JSGlobalObject;
- class LLIntOffsetsExtractor;
class NativeExecutable;
class SourceCode;
namespace DFG {
static void visitChildren(JSCell*, SlotVisitor&);
private:
- friend class LLIntOffsetsExtractor;
-
JS_EXPORT_PRIVATE bool isHostFunctionNonInline() const;
static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&);
#include "DebuggerActivation.h"
#include "FunctionConstructor.h"
#include "GetterSetter.h"
-#include "HostCallReturnValue.h"
#include "Interpreter.h"
#include "JSActivation.h"
#include "JSAPIValueWrapper.h"
, keywords(adoptPtr(new Keywords(this)))
, interpreter(0)
, heap(this, heapSize)
- , jsArrayClassInfo(&JSArray::s_info)
- , jsFinalObjectClassInfo(&JSFinalObject::s_info)
#if ENABLE(DFG_JIT)
, sizeOfLastScratchBuffer(0)
#endif
jitStubs = adoptPtr(new JITThunks(this));
#endif
- interpreter->initialize(&llintData, this->canUseJIT());
-
- initializeHostCallReturnValue(); // This is needed to convince the linker not to drop host call return support.
+ interpreter->initialize(this->canUseJIT());
heap.notifyIsSafeToCollect();
-
- llintData.performAssertions(*this);
}
void JSGlobalData::clearBuiltinStructures()
#define JSGlobalData_h
#include "CachedTranscendentalFunction.h"
+#include "Intrinsic.h"
#include "DateInstanceCache.h"
#include "ExecutableAllocator.h"
#include "Heap.h"
-#include "Intrinsic.h"
+#include "Strong.h"
#include "JITStubs.h"
#include "JSValue.h"
-#include "LLIntData.h"
#include "NumericStrings.h"
#include "SmallStrings.h"
-#include "Strong.h"
#include "Terminator.h"
#include "TimeoutChecker.h"
#include "WeakRandom.h"
class JSGlobalObject;
class JSObject;
class Keywords;
- class LLIntOffsetsExtractor;
class NativeExecutable;
class ParserArena;
class RegExpCache;
Heap heap;
JSValue exception;
-
- const ClassInfo* const jsArrayClassInfo;
- const ClassInfo* const jsFinalObjectClassInfo;
-
- LLInt::Data llintData;
-
+#if ENABLE(JIT)
ReturnAddressPtr exceptionLocation;
JSValue hostCallReturnValue;
CallFrame* callFrameForThrow;
return scratchBuffers.last();
}
#endif
+#endif
HashMap<OpaqueJSClass*, OwnPtr<OpaqueJSClassContextData> > opaqueJSClassData;
#undef registerTypedArrayFunction
private:
- friend class LLIntOffsetsExtractor;
-
JSGlobalData(GlobalDataType, ThreadStackType, HeapSize);
static JSGlobalData*& sharedInstanceInternal();
void createNativeThunk();
class FunctionPrototype;
class GetterSetter;
class GlobalCodeBlock;
- class LLIntOffsetsExtractor;
class NativeErrorConstructor;
class ProgramCodeBlock;
class RegExpConstructor;
JS_EXPORT_PRIVATE void addStaticGlobals(GlobalPropertyInfo*, int count);
private:
- friend class LLIntOffsetsExtractor;
-
// FIXME: Fold reset into init.
JS_EXPORT_PRIVATE void init(JSObject* thisValue);
void reset(JSValue prototype);
class GetterSetter;
class HashEntry;
class InternalFunction;
- class LLIntOffsetsExtractor;
class MarkedBlock;
class PropertyDescriptor;
class PropertyNameArray;
JSObject(JSGlobalData&, Structure*, PropertyStorage inlineStorage);
private:
- friend class LLIntOffsetsExtractor;
-
// Nobody should ever ask any of these questions on something already known to be a JSObject.
using JSCell::isAPIValueWrapper;
using JSCell::isGetterSetter;
}
private:
- friend class LLIntOffsetsExtractor;
-
explicit JSFinalObject(JSGlobalData& globalData, Structure* structure)
: JSObject(globalData, structure, m_inlineStorage)
{
class Identifier;
class JSObject;
- class LLIntOffsetsExtractor;
class JSPropertyNameIterator : public JSCell {
friend class JIT;
}
private:
- friend class LLIntOffsetsExtractor;
-
JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlot);
WriteBarrier<Structure> m_cachedStructure;
namespace JSC {
class JSString;
- class LLIntOffsetsExtractor;
JSString* jsEmptyString(JSGlobalData*);
JSString* jsEmptyString(ExecState*);
static void visitChildren(JSCell*, SlotVisitor&);
private:
- friend class LLIntOffsetsExtractor;
-
JS_EXPORT_PRIVATE void resolveRope(ExecState*) const;
void resolveRopeSlowCase8(LChar*) const;
void resolveRopeSlowCase(UChar*) const;
namespace JSC {
- class LLIntOffsetsExtractor;
-
static const unsigned MasqueradesAsUndefined = 1; // WebCore uses MasqueradesAsUndefined to make document.all undetectable.
static const unsigned ImplementsHasInstance = 1 << 1;
static const unsigned OverridesHasInstance = 1 << 2;
}
private:
- friend class LLIntOffsetsExtractor;
-
bool isSetOnFlags1(unsigned flag) const { ASSERT(flag <= (1 << 7)); return m_flags & flag; }
bool isSetOnFlags2(unsigned flag) const { ASSERT(flag >= (1 << 8)); return m_flags2 & (flag >> 8); }
char* JSValue::description()
{
- static const size_t size = 128;
+ static const size_t size = 64;
static char description[size];
if (!*this)
snprintf(description, size, "Int32: %d", asInt32());
else if (isDouble()) {
#if USE(JSVALUE64)
- snprintf(description, size, "Double: %lx, %lf", reinterpretDoubleToIntptr(asDouble()), asDouble());
+ snprintf(description, size, "Double: %lf, %lx", asDouble(), reinterpretDoubleToIntptr(asDouble()));
#else
union {
double asDouble;
uint32_t asTwoInt32s[2];
} u;
u.asDouble = asDouble();
- snprintf(description, size, "Double: %08x:%08x, %lf", u.asTwoInt32s[1], u.asTwoInt32s[0], asDouble());
+ snprintf(description, size, "Double: %lf, %08x:%08x", asDouble(), u.asTwoInt32s[1], u.asTwoInt32s[0]);
#endif
} else if (isCell())
snprintf(description, size, "Cell: %p", asCell());
class SpeculativeJIT;
}
#endif
- namespace LLInt {
- class Data;
- }
struct ClassInfo;
struct Instruction;
friend class DFG::OSRExitCompiler;
friend class DFG::SpeculativeJIT;
#endif
- friend class LLInt::Data;
public:
static EncodedJSValue encode(JSValue);
namespace JSC {
- class LLIntOffsetsExtractor;
class Register;
class JSVariableObject : public JSNonFinalObject {
friend class JIT;
- friend class LLIntOffsetsExtractor;
public:
typedef JSNonFinalObject Base;
unsigned maximumInliningDepth;
-int32_t executionCounterValueForJITAfterWarmUp;
-int32_t executionCounterValueForDontJITAnytimeSoon;
-int32_t executionCounterValueForJITSoon;
-
int32_t executionCounterValueForOptimizeAfterWarmUp;
int32_t executionCounterValueForOptimizeAfterLongWarmUp;
int32_t executionCounterValueForDontOptimizeAnytimeSoon;
SET(maximumInliningDepth, 5);
- SET(executionCounterValueForJITAfterWarmUp, -100);
- SET(executionCounterValueForDontJITAnytimeSoon, std::numeric_limits<int32_t>::min());
- SET(executionCounterValueForJITSoon, -100);
-
SET(executionCounterValueForOptimizeAfterWarmUp, -1000);
SET(executionCounterValueForOptimizeAfterLongWarmUp, -5000);
SET(executionCounterValueForDontOptimizeAnytimeSoon, std::numeric_limits<int32_t>::min());
if (cpusToUse < 1)
cpusToUse = 1;
- cpusToUse = 1;
-
SET(numberOfGCMarkers, cpusToUse);
ASSERT(executionCounterValueForDontOptimizeAnytimeSoon <= executionCounterValueForOptimizeAfterLongWarmUp);
extern unsigned maximumInliningDepth; // Depth of inline stack, so 1 = no inlining, 2 = one level, etc.
-extern int32_t executionCounterValueForJITAfterWarmUp;
-extern int32_t executionCounterValueForDontJITAnytimeSoon;
-extern int32_t executionCounterValueForJITSoon;
-
extern int32_t executionCounterValueForOptimizeAfterWarmUp;
extern int32_t executionCounterValueForOptimizeAfterLongWarmUp;
extern int32_t executionCounterValueForDontOptimizeAnytimeSoon;
class JSGlobalData;
class JSGlobalObject;
class JSObject;
- class LLIntOffsetsExtractor;
class ScopeChainIterator;
class SlotVisitor;
static JS_EXPORTDATA const ClassInfo s_info;
private:
- friend class LLIntOffsetsExtractor;
-
static const unsigned StructureFlags = OverridesVisitChildren;
};
transition->growPropertyStorageCapacity();
return transition;
}
-
+
Structure* transition = create(globalData, structure);
transition->m_cachedPrototypeChain.setMayBeNull(globalData, transition, structure->m_cachedPrototypeChain.get());
namespace JSC {
- class LLIntOffsetsExtractor;
class PropertyNameArray;
class PropertyNameArrayData;
class StructureChain;
static JS_EXPORTDATA const ClassInfo s_info;
private:
- friend class LLIntOffsetsExtractor;
-
JS_EXPORT_PRIVATE Structure(JSGlobalData&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*);
Structure(JSGlobalData&);
Structure(JSGlobalData&, const Structure*);
namespace JSC {
- class LLIntOffsetsExtractor;
class Structure;
class StructureChain : public JSCell {
}
private:
- friend class LLIntOffsetsExtractor;
-
StructureChain(JSGlobalData&, Structure*);
static void destroy(JSCell*);
OwnArrayPtr<WriteBarrier<Structure> > m_vector;
#define HIDE_SYMBOL(name)
#endif
-// FIXME: figure out how this works on all the platforms. I know that
-// on Linux, the preferred form is ".Lstuff" as opposed to "Lstuff".
-// Don't know about any of the others.
-#if PLATFORM(MAC)
-#define LOCAL_LABEL_STRING(name) "L" #name
-#endif
-
#endif // InlineASM_h
#define ENABLE_JIT 1
#endif
-/* On some of the platforms where we have a JIT, we want to also have the
- low-level interpreter. */
-#if !defined(ENABLE_LLINT) && ENABLE(JIT) && OS(DARWIN) && (CPU(X86) || CPU(ARM_THUMB2)) && USE(JSVALUE32_64)
-#define ENABLE_LLINT 1
-#endif
-
#if !defined(ENABLE_DFG_JIT) && ENABLE(JIT)
/* Enable the DFG JIT on X86 and X86_64. Only tested on Mac and GNU/Linux. */
#if (CPU(X86) || CPU(X86_64)) && (PLATFORM(MAC) || OS(LINUX))
iterator begin();
iterator end();
-
- bool isEmpty() { return begin() == end(); }
private:
RawNode m_headSentinel;
// Landing the file moves in one patch, will follow on with patches to change the namespaces.
namespace JSC {
struct IdentifierCStringTranslator;
-namespace LLInt { class Data; }
-class LLIntOffsetsExtractor;
template <typename T> struct IdentifierCharBufferTranslator;
struct IdentifierLCharFromUCharTranslator;
}
friend struct WTF::SubstringTranslator;
friend struct WTF::UCharBufferTranslator;
friend class AtomicStringImpl;
- friend class JSC::LLInt::Data;
- friend class JSC::LLIntOffsetsExtractor;
-
+
private:
enum BufferOwnership {
BufferInternal,
"${JAVASCRIPTCORE_DIR}/debugger"
"${JAVASCRIPTCORE_DIR}/interpreter"
"${JAVASCRIPTCORE_DIR}/jit"
- "${JAVASCRIPTCORE_DIR}/llint"
"${JAVASCRIPTCORE_DIR}/parser"
"${JAVASCRIPTCORE_DIR}/profiler"
"${JAVASCRIPTCORE_DIR}/runtime"
+2012-02-21 Adam Roben <aroben@apple.com>
+
+ Roll out r108309, r108323, and r108326
+
+ They broke the 32-bit Lion build.
+
+ Original bugs is <http://webkit.org/b/75812> <rdar://problem/10079694>.
+
+ * CMakeLists.txt:
+
2012-02-21 Alexander Pavlov <apavlov@chromium.org>
Web Inspector: [SuggestBox] textPrompt.css disablement displays garbled suggest box
"${JAVASCRIPTCORE_DIR}/debugger"
"${JAVASCRIPTCORE_DIR}/interpreter"
"${JAVASCRIPTCORE_DIR}/jit"
- "${JAVASCRIPTCORE_DIR}/llint"
"${JAVASCRIPTCORE_DIR}/parser"
"${JAVASCRIPTCORE_DIR}/profiler"
"${JAVASCRIPTCORE_DIR}/runtime"
+2012-02-21 Adam Roben <aroben@apple.com>
+
+ Roll out r108309, r108323, and r108326
+
+ They broke the 32-bit Lion build.
+
+ Original bugs is <http://webkit.org/b/75812> <rdar://problem/10079694>.
+
+ * CMakeLists.txt:
+
2012-02-20 Filip Pizlo <fpizlo@apple.com>
JSC should be a triple-tier VM
+2012-02-21 Adam Roben <aroben@apple.com>
+
+ Roll out r108309, r108323, and r108326
+
+ They broke the 32-bit Lion build.
+
+ Original bugs is <http://webkit.org/b/75812> <rdar://problem/10079694>.
+
+ * DumpRenderTree/efl/CMakeLists.txt:
+
2012-02-21 Andras Becsi <andras.becsi@nokia.com>
[Qt][WK2] Get rid of the dependency to QtWidgets
${JAVASCRIPTCORE_DIR}
${JAVASCRIPTCORE_DIR}/API
${JAVASCRIPTCORE_DIR}/assembler
- ${JAVASCRIPTCORE_DIR}/bytecode
${JAVASCRIPTCORE_DIR}/dfg
${JAVASCRIPTCORE_DIR}/heap
${JAVASCRIPTCORE_DIR}/interpreter
${JAVASCRIPTCORE_DIR}/jit
- ${JAVASCRIPTCORE_DIR}/llint
${JAVASCRIPTCORE_DIR}/runtime
${JAVASCRIPTCORE_DIR}/ForwardingHeaders
${JAVASCRIPTCORE_DIR}/wtf