Changeset 189884 in webkit


Ignore:
Timestamp:
Sep 16, 2015 4:40:35 PM (9 years ago)
Author:
msaboff@apple.com
Message:

[ES6] Implement tail calls in the LLInt and Baseline JIT
https://bugs.webkit.org/show_bug.cgi?id=148661

Fix for the breakage of Speedometer/Full.html (https://bugs.webkit.org/show_bug.cgi?id=149162).

Reviewed by Filip Pizlo.
Changed SetupVarargsFrame.cpp::emitSetVarargsFrame to align the callframe size to be a
multiple of stackAlignmentRegisters() in addition to the location of the new frame.

Fixed Reviewed by Filip Pizlo.

  • CMakeLists.txt:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • assembler/AbortReason.h:
  • assembler/AbstractMacroAssembler.h:

(JSC::AbstractMacroAssembler::Call::Call):
(JSC::AbstractMacroAssembler::repatchNearCall):
(JSC::AbstractMacroAssembler::repatchCompact):

  • assembler/CodeLocation.h:

(JSC::CodeLocationNearCall::CodeLocationNearCall):
(JSC::CodeLocationNearCall::callMode):
(JSC::CodeLocationCommon::callAtOffset):
(JSC::CodeLocationCommon::nearCallAtOffset):
(JSC::CodeLocationCommon::dataLabelPtrAtOffset):

  • assembler/LinkBuffer.h:

(JSC::LinkBuffer::locationOfNearCall):
(JSC::LinkBuffer::locationOf):

  • assembler/MacroAssemblerARM.h:

(JSC::MacroAssemblerARM::nearCall):
(JSC::MacroAssemblerARM::nearTailCall):
(JSC::MacroAssemblerARM::call):
(JSC::MacroAssemblerARM::linkCall):

  • assembler/MacroAssemblerARM64.h:

(JSC::MacroAssemblerARM64::nearCall):
(JSC::MacroAssemblerARM64::nearTailCall):
(JSC::MacroAssemblerARM64::ret):
(JSC::MacroAssemblerARM64::linkCall):

  • assembler/MacroAssemblerARMv7.h:

(JSC::MacroAssemblerARMv7::nearCall):
(JSC::MacroAssemblerARMv7::nearTailCall):
(JSC::MacroAssemblerARMv7::call):
(JSC::MacroAssemblerARMv7::linkCall):

  • assembler/MacroAssemblerMIPS.h:

(JSC::MacroAssemblerMIPS::nearCall):
(JSC::MacroAssemblerMIPS::nearTailCall):
(JSC::MacroAssemblerMIPS::call):
(JSC::MacroAssemblerMIPS::linkCall):
(JSC::MacroAssemblerMIPS::repatchCall):

  • assembler/MacroAssemblerSH4.h:

(JSC::MacroAssemblerSH4::call):
(JSC::MacroAssemblerSH4::nearTailCall):
(JSC::MacroAssemblerSH4::nearCall):
(JSC::MacroAssemblerSH4::linkCall):
(JSC::MacroAssemblerSH4::repatchCall):

  • assembler/MacroAssemblerX86.h:

(JSC::MacroAssemblerX86::linkCall):

  • assembler/MacroAssemblerX86Common.h:

(JSC::MacroAssemblerX86Common::breakpoint):
(JSC::MacroAssemblerX86Common::nearTailCall):
(JSC::MacroAssemblerX86Common::nearCall):

  • assembler/MacroAssemblerX86_64.h:

(JSC::MacroAssemblerX86_64::linkCall):

  • bytecode/BytecodeList.json:
  • bytecode/BytecodeUseDef.h:

(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):

  • bytecode/CallLinkInfo.h:

(JSC::CallLinkInfo::callTypeFor):
(JSC::CallLinkInfo::isVarargsCallType):
(JSC::CallLinkInfo::CallLinkInfo):
(JSC::CallLinkInfo::specializationKind):
(JSC::CallLinkInfo::callModeFor):
(JSC::CallLinkInfo::callMode):
(JSC::CallLinkInfo::isTailCall):
(JSC::CallLinkInfo::isVarargs):
(JSC::CallLinkInfo::registerPreservationMode):

  • bytecode/CallLinkStatus.cpp:

(JSC::CallLinkStatus::computeFromLLInt):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::CodeBlock):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitCallInTailPosition):
(JSC::BytecodeGenerator::emitCallEval):
(JSC::BytecodeGenerator::emitCall):
(JSC::BytecodeGenerator::emitCallVarargsInTailPosition):
(JSC::BytecodeGenerator::emitConstructVarargs):

  • bytecompiler/NodesCodegen.cpp:

(JSC::CallArguments::CallArguments):
(JSC::LabelNode::emitBytecode):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::addCallWithoutSettingResult):

  • ftl/FTLLowerDFGToLLVM.cpp:

(JSC::FTL::DFG::LowerDFGToLLVM::compileCallOrConstruct):

  • interpreter/Interpreter.h:

(JSC::Interpreter::isCallBytecode):
(JSC::calleeFrameForVarargs):

  • jit/CCallHelpers.h:

(JSC::CCallHelpers::jumpToExceptionHandler):
(JSC::CCallHelpers::prepareForTailCallSlow):

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):

  • jit/JIT.h:
  • jit/JITCall.cpp:

(JSC::JIT::compileOpCall):
(JSC::JIT::compileOpCallSlowCase):
(JSC::JIT::emit_op_call):
(JSC::JIT::emit_op_tail_call):
(JSC::JIT::emit_op_call_eval):
(JSC::JIT::emit_op_call_varargs):
(JSC::JIT::emit_op_tail_call_varargs):
(JSC::JIT::emit_op_construct_varargs):
(JSC::JIT::emitSlow_op_call):
(JSC::JIT::emitSlow_op_tail_call):
(JSC::JIT::emitSlow_op_call_eval):
(JSC::JIT::emitSlow_op_call_varargs):
(JSC::JIT::emitSlow_op_tail_call_varargs):
(JSC::JIT::emitSlow_op_construct_varargs):

  • jit/JITCall32_64.cpp:

(JSC::JIT::emitSlow_op_call):
(JSC::JIT::emitSlow_op_tail_call):
(JSC::JIT::emitSlow_op_call_eval):
(JSC::JIT::emitSlow_op_call_varargs):
(JSC::JIT::emitSlow_op_tail_call_varargs):
(JSC::JIT::emitSlow_op_construct_varargs):
(JSC::JIT::emit_op_call):
(JSC::JIT::emit_op_tail_call):
(JSC::JIT::emit_op_call_eval):
(JSC::JIT::emit_op_call_varargs):
(JSC::JIT::emit_op_tail_call_varargs):
(JSC::JIT::emit_op_construct_varargs):
(JSC::JIT::compileOpCall):
(JSC::JIT::compileOpCallSlowCase):

  • jit/JITInlines.h:

(JSC::JIT::emitNakedCall):
(JSC::JIT::emitNakedTailCall):
(JSC::JIT::updateTopCallFrame):

  • jit/JITOperations.cpp:
  • jit/JITOperations.h:
  • jit/Repatch.cpp:

(JSC::linkVirtualFor):
(JSC::linkPolymorphicCall):

  • jit/SetupVarargsFrame.cpp:

(JSC::emitSetVarargsFrame):

  • jit/ThunkGenerators.cpp:

(JSC::throwExceptionFromCallSlowPathGenerator):
(JSC::slowPathFor):
(JSC::linkCallThunkGenerator):
(JSC::virtualThunkFor):
(JSC::arityFixupGenerator):
(JSC::unreachableGenerator):
(JSC::baselineGetterReturnThunkGenerator):

  • jit/ThunkGenerators.h:
  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/CommonSlowPaths.h:

(JSC::CommonSlowPaths::arityCheckFor):
(JSC::CommonSlowPaths::opIn):

Location:
trunk/Source/JavaScriptCore
Files:
43 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r189848 r189884  
    8181    bytecode/CallLinkInfo.cpp
    8282    bytecode/CallLinkStatus.cpp
     83    bytecode/CallMode.cpp
    8384    bytecode/CallVariant.cpp
    8485    bytecode/CodeBlock.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r189848 r189884  
     12015-09-16  Michael Saboff  <msaboff@apple.com>
     2
     3        [ES6] Implement tail calls in the LLInt and Baseline JIT
     4        https://bugs.webkit.org/show_bug.cgi?id=148661
     5
     6        Fix for the breakage of Speedometer/Full.html (https://bugs.webkit.org/show_bug.cgi?id=149162).
     7
     8        Reviewed by Filip Pizlo.
     9        Changed SetupVarargsFrame.cpp::emitSetVarargsFrame to align the callframe size to be a
     10        multiple of stackAlignmentRegisters() in addition to the location of the new frame.
     11
     12        Fixed Reviewed by Filip Pizlo.
     13
     14        * CMakeLists.txt:
     15        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
     16        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
     17        * JavaScriptCore.xcodeproj/project.pbxproj:
     18        * assembler/AbortReason.h:
     19        * assembler/AbstractMacroAssembler.h:
     20        (JSC::AbstractMacroAssembler::Call::Call):
     21        (JSC::AbstractMacroAssembler::repatchNearCall):
     22        (JSC::AbstractMacroAssembler::repatchCompact):
     23        * assembler/CodeLocation.h:
     24        (JSC::CodeLocationNearCall::CodeLocationNearCall):
     25        (JSC::CodeLocationNearCall::callMode):
     26        (JSC::CodeLocationCommon::callAtOffset):
     27        (JSC::CodeLocationCommon::nearCallAtOffset):
     28        (JSC::CodeLocationCommon::dataLabelPtrAtOffset):
     29        * assembler/LinkBuffer.h:
     30        (JSC::LinkBuffer::locationOfNearCall):
     31        (JSC::LinkBuffer::locationOf):
     32        * assembler/MacroAssemblerARM.h:
     33        (JSC::MacroAssemblerARM::nearCall):
     34        (JSC::MacroAssemblerARM::nearTailCall):
     35        (JSC::MacroAssemblerARM::call):
     36        (JSC::MacroAssemblerARM::linkCall):
     37        * assembler/MacroAssemblerARM64.h:
     38        (JSC::MacroAssemblerARM64::nearCall):
     39        (JSC::MacroAssemblerARM64::nearTailCall):
     40        (JSC::MacroAssemblerARM64::ret):
     41        (JSC::MacroAssemblerARM64::linkCall):
     42        * assembler/MacroAssemblerARMv7.h:
     43        (JSC::MacroAssemblerARMv7::nearCall):
     44        (JSC::MacroAssemblerARMv7::nearTailCall):
     45        (JSC::MacroAssemblerARMv7::call):
     46        (JSC::MacroAssemblerARMv7::linkCall):
     47        * assembler/MacroAssemblerMIPS.h:
     48        (JSC::MacroAssemblerMIPS::nearCall):
     49        (JSC::MacroAssemblerMIPS::nearTailCall):
     50        (JSC::MacroAssemblerMIPS::call):
     51        (JSC::MacroAssemblerMIPS::linkCall):
     52        (JSC::MacroAssemblerMIPS::repatchCall):
     53        * assembler/MacroAssemblerSH4.h:
     54        (JSC::MacroAssemblerSH4::call):
     55        (JSC::MacroAssemblerSH4::nearTailCall):
     56        (JSC::MacroAssemblerSH4::nearCall):
     57        (JSC::MacroAssemblerSH4::linkCall):
     58        (JSC::MacroAssemblerSH4::repatchCall):
     59        * assembler/MacroAssemblerX86.h:
     60        (JSC::MacroAssemblerX86::linkCall):
     61        * assembler/MacroAssemblerX86Common.h:
     62        (JSC::MacroAssemblerX86Common::breakpoint):
     63        (JSC::MacroAssemblerX86Common::nearTailCall):
     64        (JSC::MacroAssemblerX86Common::nearCall):
     65        * assembler/MacroAssemblerX86_64.h:
     66        (JSC::MacroAssemblerX86_64::linkCall):
     67        * bytecode/BytecodeList.json:
     68        * bytecode/BytecodeUseDef.h:
     69        (JSC::computeUsesForBytecodeOffset):
     70        (JSC::computeDefsForBytecodeOffset):
     71        * bytecode/CallLinkInfo.h:
     72        (JSC::CallLinkInfo::callTypeFor):
     73        (JSC::CallLinkInfo::isVarargsCallType):
     74        (JSC::CallLinkInfo::CallLinkInfo):
     75        (JSC::CallLinkInfo::specializationKind):
     76        (JSC::CallLinkInfo::callModeFor):
     77        (JSC::CallLinkInfo::callMode):
     78        (JSC::CallLinkInfo::isTailCall):
     79        (JSC::CallLinkInfo::isVarargs):
     80        (JSC::CallLinkInfo::registerPreservationMode):
     81        * bytecode/CallLinkStatus.cpp:
     82        (JSC::CallLinkStatus::computeFromLLInt):
     83        * bytecode/CodeBlock.cpp:
     84        (JSC::CodeBlock::dumpBytecode):
     85        (JSC::CodeBlock::CodeBlock):
     86        * bytecompiler/BytecodeGenerator.cpp:
     87        (JSC::BytecodeGenerator::BytecodeGenerator):
     88        (JSC::BytecodeGenerator::emitCallInTailPosition):
     89        (JSC::BytecodeGenerator::emitCallEval):
     90        (JSC::BytecodeGenerator::emitCall):
     91        (JSC::BytecodeGenerator::emitCallVarargsInTailPosition):
     92        (JSC::BytecodeGenerator::emitConstructVarargs):
     93        * bytecompiler/NodesCodegen.cpp:
     94        (JSC::CallArguments::CallArguments):
     95        (JSC::LabelNode::emitBytecode):
     96        * dfg/DFGByteCodeParser.cpp:
     97        (JSC::DFG::ByteCodeParser::addCallWithoutSettingResult):
     98        * ftl/FTLLowerDFGToLLVM.cpp:
     99        (JSC::FTL::DFG::LowerDFGToLLVM::compileCallOrConstruct):
     100        * interpreter/Interpreter.h:
     101        (JSC::Interpreter::isCallBytecode):
     102        (JSC::calleeFrameForVarargs):
     103        * jit/CCallHelpers.h:
     104        (JSC::CCallHelpers::jumpToExceptionHandler):
     105        (JSC::CCallHelpers::prepareForTailCallSlow):
     106        * jit/JIT.cpp:
     107        (JSC::JIT::privateCompileMainPass):
     108        (JSC::JIT::privateCompileSlowCases):
     109        * jit/JIT.h:
     110        * jit/JITCall.cpp:
     111        (JSC::JIT::compileOpCall):
     112        (JSC::JIT::compileOpCallSlowCase):
     113        (JSC::JIT::emit_op_call):
     114        (JSC::JIT::emit_op_tail_call):
     115        (JSC::JIT::emit_op_call_eval):
     116        (JSC::JIT::emit_op_call_varargs):
     117        (JSC::JIT::emit_op_tail_call_varargs):
     118        (JSC::JIT::emit_op_construct_varargs):
     119        (JSC::JIT::emitSlow_op_call):
     120        (JSC::JIT::emitSlow_op_tail_call):
     121        (JSC::JIT::emitSlow_op_call_eval):
     122        (JSC::JIT::emitSlow_op_call_varargs):
     123        (JSC::JIT::emitSlow_op_tail_call_varargs):
     124        (JSC::JIT::emitSlow_op_construct_varargs):
     125        * jit/JITCall32_64.cpp:
     126        (JSC::JIT::emitSlow_op_call):
     127        (JSC::JIT::emitSlow_op_tail_call):
     128        (JSC::JIT::emitSlow_op_call_eval):
     129        (JSC::JIT::emitSlow_op_call_varargs):
     130        (JSC::JIT::emitSlow_op_tail_call_varargs):
     131        (JSC::JIT::emitSlow_op_construct_varargs):
     132        (JSC::JIT::emit_op_call):
     133        (JSC::JIT::emit_op_tail_call):
     134        (JSC::JIT::emit_op_call_eval):
     135        (JSC::JIT::emit_op_call_varargs):
     136        (JSC::JIT::emit_op_tail_call_varargs):
     137        (JSC::JIT::emit_op_construct_varargs):
     138        (JSC::JIT::compileOpCall):
     139        (JSC::JIT::compileOpCallSlowCase):
     140        * jit/JITInlines.h:
     141        (JSC::JIT::emitNakedCall):
     142        (JSC::JIT::emitNakedTailCall):
     143        (JSC::JIT::updateTopCallFrame):
     144        * jit/JITOperations.cpp:
     145        * jit/JITOperations.h:
     146        * jit/Repatch.cpp:
     147        (JSC::linkVirtualFor):
     148        (JSC::linkPolymorphicCall):
     149        * jit/SetupVarargsFrame.cpp:
     150        (JSC::emitSetVarargsFrame):
     151        * jit/ThunkGenerators.cpp:
     152        (JSC::throwExceptionFromCallSlowPathGenerator):
     153        (JSC::slowPathFor):
     154        (JSC::linkCallThunkGenerator):
     155        (JSC::virtualThunkFor):
     156        (JSC::arityFixupGenerator):
     157        (JSC::unreachableGenerator):
     158        (JSC::baselineGetterReturnThunkGenerator):
     159        * jit/ThunkGenerators.h:
     160        * llint/LowLevelInterpreter.asm:
     161        * llint/LowLevelInterpreter32_64.asm:
     162        * llint/LowLevelInterpreter64.asm:
     163        * runtime/CommonSlowPaths.h:
     164        (JSC::CommonSlowPaths::arityCheckFor):
     165        (JSC::CommonSlowPaths::opIn):
     166
    11672015-09-15  Michael Saboff  <msaboff@apple.com>
    2168
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj

    r189848 r189884  
    320320    <ClCompile Include="..\bytecode\CallLinkInfo.cpp" />
    321321    <ClCompile Include="..\bytecode\CallLinkStatus.cpp" />
     322    <ClCompile Include="..\bytecode\CallMode.cpp" />
    322323    <ClCompile Include="..\bytecode\CallVariant.cpp" />
    323324    <ClCompile Include="..\bytecode\CodeBlock.cpp" />
     
    10131014    <ClInclude Include="..\bytecode\CallLinkInfo.h" />
    10141015    <ClInclude Include="..\bytecode\CallLinkStatus.h" />
     1016    <ClInclude Include="..\bytecode\CallMode.h" />
    10151017    <ClInclude Include="..\bytecode\CallReturnOffsetToBytecodeOffset.h" />
    10161018    <ClInclude Include="..\bytecode\CallVariant.h" />
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters

    r189848 r189884  
    163163      <Filter>bytecode</Filter>
    164164    </ClCompile>
     165    <ClCompile Include="..\bytecode\CallMode.cpp">
     166      <Filter>bytecode</Filter>
     167    </ClCompile>
    165168    <ClCompile Include="..\bytecode\CodeBlock.cpp">
    166169      <Filter>bytecode</Filter>
     
    20332036    </ClInclude>
    20342037    <ClInclude Include="..\bytecode\CallLinkStatus.h">
     2038      <Filter>bytecode</Filter>
     2039    </ClInclude>
     2040    <ClInclude Include="..\bytecode\CallMode.h">
    20352041      <Filter>bytecode</Filter>
    20362042    </ClInclude>
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r189848 r189884  
    970970                5DE6E5B30E1728EC00180407 /* create_hash_table in Headers */ = {isa = PBXBuildFile; fileRef = F692A8540255597D01FF60F7 /* create_hash_table */; settings = {ATTRIBUTES = (); }; };
    971971                623A37EC1B87A7C000754209 /* RegisterMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 623A37EB1B87A7BD00754209 /* RegisterMap.h */; };
     972                627673231B680C1E00FD9F2E /* CallMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 627673211B680C1E00FD9F2E /* CallMode.cpp */; };
     973                627673241B680C1E00FD9F2E /* CallMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 627673221B680C1E00FD9F2E /* CallMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
    972974                62D2D38F1ADF103F000206C1 /* FunctionRareData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 62D2D38D1ADF103F000206C1 /* FunctionRareData.cpp */; };
    973975                62D2D3901ADF103F000206C1 /* FunctionRareData.h in Headers */ = {isa = PBXBuildFile; fileRef = 62D2D38E1ADF103F000206C1 /* FunctionRareData.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    27732775                5DE3D0F40DD8DDFB00468714 /* WebKitAvailability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitAvailability.h; sourceTree = "<group>"; };
    27742776                623A37EB1B87A7BD00754209 /* RegisterMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterMap.h; sourceTree = "<group>"; };
     2777                627673211B680C1E00FD9F2E /* CallMode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallMode.cpp; sourceTree = "<group>"; };
     2778                627673221B680C1E00FD9F2E /* CallMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallMode.h; sourceTree = "<group>"; };
    27752779                62A9A29E1B0BED4800BD54CA /* DFGLazyNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGLazyNode.cpp; path = dfg/DFGLazyNode.cpp; sourceTree = "<group>"; };
    27762780                62A9A29F1B0BED4800BD54CA /* DFGLazyNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGLazyNode.h; path = dfg/DFGLazyNode.h; sourceTree = "<group>"; };
     
    55395543                                0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */,
    55405544                                0F93329414CA7DC10085F3C6 /* CallLinkStatus.h */,
     5545                                627673211B680C1E00FD9F2E /* CallMode.cpp */,
     5546                                627673221B680C1E00FD9F2E /* CallMode.h */,
    55415547                                0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */,
    55425548                                0F3B7E2419A11B8000D9BC56 /* CallVariant.cpp */,
     
    61916197                                A7D89CFE17A0B8CC00773AD8 /* DFGOSRAvailabilityAnalysisPhase.h in Headers */,
    61926198                                0FD82E57141DAF1000179C94 /* DFGOSREntry.h in Headers */,
     6199                                627673241B680C1E00FD9F2E /* CallMode.h in Headers */,
    61936200                                0FD8A32617D51F5700CA2C40 /* DFGOSREntrypointCreationPhase.h in Headers */,
    61946201                                62F2AA381B0BEDE300610C7A /* DFGLazyNode.h in Headers */,
     
    79727979                                9335F24D12E6765B002B5553 /* StringRecursionChecker.cpp in Sources */,
    79737980                                BCDE3B430E6C832D001453A7 /* Structure.cpp in Sources */,
     7981                                627673231B680C1E00FD9F2E /* CallMode.cpp in Sources */,
    79747982                                7E4EE70F0EBB7A5B005934AA /* StructureChain.cpp in Sources */,
    79757983                                C2F0F2D116BAEEE900187C19 /* StructureRareData.cpp in Sources */,
  • trunk/Source/JavaScriptCore/assembler/AbortReason.h

    r189848 r189884  
    5959    DFGUnreasonableOSREntryJumpDestination            = 230,
    6060    DFGVarargsThrowingPathDidNotThrow                 = 235,
     61    JITDidReturnFromTailCall                          = 237,
    6162    JITDivOperandsAreNotNumbers                       = 240,
    6263    JITGetByValResultIsNotEmpty                       = 250,
  • trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h

    r189848 r189884  
    508508            Linkable = 0x1,
    509509            Near = 0x2,
     510            Tail = 0x4,
    510511            LinkableNear = 0x3,
     512            LinkableNearTail = 0x7,
    511513        };
    512514
     
    963965    static void repatchNearCall(CodeLocationNearCall nearCall, CodeLocationLabel destination)
    964966    {
    965         AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
     967        switch (nearCall.callMode()) {
     968        case NearCallMode::Tail:
     969            AssemblerType::relinkJump(nearCall.dataLocation(), destination.executableAddress());
     970            return;
     971        case NearCallMode::Regular:
     972            AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
     973            return;
     974        }
     975        RELEASE_ASSERT_NOT_REACHED();
    966976    }
    967977
  • trunk/Source/JavaScriptCore/assembler/CodeLocation.h

    r189848 r189884  
    3333namespace JSC {
    3434
     35enum NearCallMode { Regular, Tail };
     36
    3537class CodeLocationInstruction;
    3638class CodeLocationLabel;
     
    6062    CodeLocationJump jumpAtOffset(int offset);
    6163    CodeLocationCall callAtOffset(int offset);
    62     CodeLocationNearCall nearCallAtOffset(int offset);
     64    CodeLocationNearCall nearCallAtOffset(int offset, NearCallMode);
    6365    CodeLocationDataLabelPtr dataLabelPtrAtOffset(int offset);
    6466    CodeLocationDataLabel32 dataLabel32AtOffset(int offset);
     
    116118public:
    117119    CodeLocationNearCall() {}
    118     explicit CodeLocationNearCall(MacroAssemblerCodePtr location)
    119         : CodeLocationCommon(location) {}
    120     explicit CodeLocationNearCall(void* location)
    121         : CodeLocationCommon(MacroAssemblerCodePtr(location)) {}
     120    explicit CodeLocationNearCall(MacroAssemblerCodePtr location, NearCallMode callMode)
     121        : CodeLocationCommon(location), m_callMode(callMode) { }
     122    explicit CodeLocationNearCall(void* location, NearCallMode callMode)
     123        : CodeLocationCommon(MacroAssemblerCodePtr(location)), m_callMode(callMode) { }
     124    NearCallMode callMode() { return m_callMode; }
     125private:
     126    NearCallMode m_callMode = NearCallMode::Regular;
    122127};
    123128
     
    182187}
    183188
    184 inline CodeLocationNearCall CodeLocationCommon::nearCallAtOffset(int offset)
    185 {
    186     ASSERT_VALID_CODE_OFFSET(offset);
    187     return CodeLocationNearCall(reinterpret_cast<char*>(dataLocation()) + offset);
     189inline CodeLocationNearCall CodeLocationCommon::nearCallAtOffset(int offset, NearCallMode callMode)
     190{
     191    ASSERT_VALID_CODE_OFFSET(offset);
     192    return CodeLocationNearCall(reinterpret_cast<char*>(dataLocation()) + offset, callMode);
    188193}
    189194
  • trunk/Source/JavaScriptCore/assembler/LinkBuffer.h

    r189848 r189884  
    181181        ASSERT(call.isFlagSet(Call::Linkable));
    182182        ASSERT(call.isFlagSet(Call::Near));
    183         return CodeLocationNearCall(MacroAssembler::getLinkerAddress(code(), applyOffset(call.m_label)));
     183        return CodeLocationNearCall(MacroAssembler::getLinkerAddress(code(), applyOffset(call.m_label)),
     184            call.isFlagSet(Call::Tail) ? NearCallMode::Tail : NearCallMode::Regular);
    184185    }
    185186
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM.h

    r189848 r189884  
    905905    }
    906906
     907    Call nearTailCall()
     908    {
     909        return Call(m_assembler.jmp(), Call::LinkableNearTail);
     910    }
     911
    907912    Call call(RegisterID target)
    908913    {
     
    14891494    static void linkCall(void* code, Call call, FunctionPtr function)
    14901495    {
    1491         ARMAssembler::linkCall(code, call.m_label, function.value());
     1496        if (call.isFlagSet(Call::Tail))
     1497            ARMAssembler::linkJump(code, call.m_label, function.value());
     1498        else
     1499            ARMAssembler::linkCall(code, call.m_label, function.value());
    14921500    }
    14931501
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h

    r189848 r189884  
    22052205    }
    22062206
     2207    ALWAYS_INLINE Call nearTailCall()
     2208    {
     2209        AssemblerLabel label = m_assembler.label();
     2210        m_assembler.b();
     2211        return Call(label, Call::LinkableNearTail);
     2212    }
     2213
    22072214    ALWAYS_INLINE void ret()
    22082215    {
     
    28832890    static void linkCall(void* code, Call call, FunctionPtr function)
    28842891    {
    2885         if (call.isFlagSet(Call::Near))
     2892        if (!call.isFlagSet(Call::Near))
     2893            ARM64Assembler::linkPointer(code, call.m_label.labelAtOffset(REPATCH_OFFSET_CALL_TO_POINTER), function.value());
     2894        else if (call.isFlagSet(Call::Tail))
     2895            ARM64Assembler::linkJump(code, call.m_label, function.value());
     2896        else
    28862897            ARM64Assembler::linkCall(code, call.m_label, function.value());
    2887         else
    2888             ARM64Assembler::linkPointer(code, call.m_label.labelAtOffset(REPATCH_OFFSET_CALL_TO_POINTER), function.value());
    28892898    }
    28902899
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h

    r189848 r189884  
    16781678    }
    16791679
     1680    ALWAYS_INLINE Call nearTailCall()
     1681    {
     1682        moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister);
     1683        return Call(m_assembler.bx(dataTempRegister), Call::LinkableNearTail);
     1684    }
     1685
    16801686    ALWAYS_INLINE Call call()
    16811687    {
     
    20132019    static void linkCall(void* code, Call call, FunctionPtr function)
    20142020    {
    2015         ARMv7Assembler::linkCall(code, call.m_label, function.value());
     2021        if (call.isFlagSet(Call::Tail))
     2022            ARMv7Assembler::linkJump(code, call.m_label, function.value());
     2023        else
     2024            ARMv7Assembler::linkCall(code, call.m_label, function.value());
    20162025    }
    20172026
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h

    r189848 r189884  
    19741974        m_assembler.nop();
    19751975        return Call(m_assembler.label(), Call::LinkableNear);
     1976    }
     1977
     1978    Call nearTailCall()
     1979    {
     1980        m_assembler.nop();
     1981        m_assembler.nop();
     1982        m_assembler.beq(MIPSRegisters::zero, MIPSRegisters::zero, 0);
     1983        m_assembler.nop();
     1984        insertRelaxationWords();
     1985        return Call(m_assembler.label(), Call::LinkableNearTail);
    19761986    }
    19771987
     
    28012811    static void linkCall(void* code, Call call, FunctionPtr function)
    28022812    {
    2803         MIPSAssembler::linkCall(code, call.m_label, function.value());
     2813        if (call.isFlagSet(Call::Tail))
     2814            MIPSAssembler::linkJump(code, call.m_label, function.value());
     2815        else
     2816            MIPSAssembler::linkCall(code, call.m_label, function.value());
    28042817    }
    28052818
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h

    r189848 r189884  
    24042404    }
    24052405
     2406    Call nearTailCall()
     2407    {
     2408        return Call(m_assembler.jump(), Call::LinkableNearTail);
     2409    }
     2410
    24062411    Call nearCall()
    24072412    {
     
    26092614    static void linkCall(void* code, Call call, FunctionPtr function)
    26102615    {
    2611         SH4Assembler::linkCall(code, call.m_label, function.value());
     2616        if (call.isFlagSet(Call::Tail))
     2617            SH4Assembler::linkJump(code, call.m_label, function.value());
     2618        else
     2619            SH4Assembler::linkCall(code, call.m_label, function.value());
    26122620    }
    26132621
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86.h

    r189848 r189884  
    362362    static void linkCall(void* code, Call call, FunctionPtr function)
    363363    {
    364         X86Assembler::linkCall(code, call.m_label, function.value());
     364        if (call.isFlagSet(Call::Tail))
     365            X86Assembler::linkJump(code, call.m_label, function.value());
     366        else
     367            X86Assembler::linkCall(code, call.m_label, function.value());
    365368    }
    366369};
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h

    r189848 r189884  
    14021402    {
    14031403        m_assembler.int3();
     1404    }
     1405
     1406    Call nearTailCall()
     1407    {
     1408        return Call(m_assembler.jmp(), Call::LinkableNearTail);
    14041409    }
    14051410
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h

    r189848 r189884  
    873873        if (!call.isFlagSet(Call::Near))
    874874            X86Assembler::linkPointer(code, call.m_label.labelAtOffset(-REPATCH_OFFSET_CALL_R11), function.value());
     875        else if (call.isFlagSet(Call::Tail))
     876            X86Assembler::linkJump(code, call.m_label, function.value());
    875877        else
    876878            X86Assembler::linkCall(code, call.m_label, function.value());
  • trunk/Source/JavaScriptCore/bytecode/BytecodeList.json

    r189848 r189884  
    9393            { "name" : "op_new_arrow_func_exp", "length" : 5 },
    9494            { "name" : "op_call", "length" : 9 },
     95            { "name" : "op_tail_call", "length" : 9 },
    9596            { "name" : "op_call_eval", "length" : 9 },
    9697            { "name" : "op_call_varargs", "length" : 9 },
     98            { "name" : "op_tail_call_varargs", "length" : 9 },
    9799            { "name" : "op_ret", "length" : 2 },
    98100            { "name" : "op_construct", "length" : 9 },
     
    145147            { "name" : "llint_cloop_did_return_from_js_6" },
    146148            { "name" : "llint_cloop_did_return_from_js_7" },
    147             { "name" : "llint_cloop_did_return_from_js_8" }
     149            { "name" : "llint_cloop_did_return_from_js_8" },
     150            { "name" : "llint_cloop_did_return_from_js_9" },
     151            { "name" : "llint_cloop_did_return_from_js_10" },
     152            { "name" : "llint_cloop_did_return_from_js_11" }
    148153        ]
    149154    },
  • trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h

    r189848 r189884  
    192192    case op_has_structure_property:
    193193    case op_construct_varargs:
    194     case op_call_varargs: {
     194    case op_call_varargs:
     195    case op_tail_call_varargs: {
    195196        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
    196197        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
     
    221222    case op_construct:
    222223    case op_call_eval:
    223     case op_call: {
     224    case op_call:
     225    case op_tail_call: {
    224226        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
    225227        int argCount = instruction[3].u.operand;
     
    312314    case op_new_arrow_func_exp:
    313315    case op_call_varargs:
     316    case op_tail_call_varargs:
    314317    case op_construct_varargs:
    315318    case op_get_from_scope:
    316319    case op_call:
     320    case op_tail_call:
    317321    case op_call_eval:
    318322    case op_construct:
  • trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h

    r189848 r189884  
    2727#define CallLinkInfo_h
    2828
     29#include "CallMode.h"
    2930#include "CodeLocation.h"
    3031#include "CodeSpecializationKind.h"
     
    4243class CallLinkInfo : public BasicRawSentinelNode<CallLinkInfo> {
    4344public:
    44     enum CallType { None, Call, CallVarargs, Construct, ConstructVarargs };
     45    enum CallType { None, Call, CallVarargs, Construct, ConstructVarargs, TailCall, TailCallVarargs };
    4546    static CallType callTypeFor(OpcodeID opcodeID)
    4647    {
    4748        if (opcodeID == op_call || opcodeID == op_call_eval)
    4849            return Call;
     50        if (opcodeID == op_call_varargs)
     51            return CallVarargs;
    4952        if (opcodeID == op_construct)
    5053            return Construct;
    5154        if (opcodeID == op_construct_varargs)
    5255            return ConstructVarargs;
    53         ASSERT(opcodeID == op_call_varargs);
    54         return CallVarargs;
    55     }
    56    
     56        if (opcodeID == op_tail_call)
     57            return TailCall;
     58        ASSERT(opcodeID == op_tail_call_varargs);
     59        return TailCallVarargs;
     60    }
     61
     62    static bool isVarargsCallType(CallType callType)
     63    {
     64        switch (callType) {
     65        case CallVarargs:
     66        case ConstructVarargs:
     67        case TailCallVarargs:
     68            return true;
     69
     70        default:
     71            return false;
     72        }
     73    }
     74
    5775    CallLinkInfo()
    5876        : m_registerPreservationMode(static_cast<unsigned>(RegisterPreservationNotRequired))
     
    82100    {
    83101        return specializationKindFor(static_cast<CallType>(m_callType));
     102    }
     103
     104    static CallMode callModeFor(CallType callType)
     105    {
     106        switch (callType) {
     107        case Call:
     108        case CallVarargs:
     109            return CallMode::Regular;
     110        case TailCall:
     111        case TailCallVarargs:
     112            return CallMode::Tail;
     113        case Construct:
     114        case ConstructVarargs:
     115            return CallMode::Construct;
     116        case None:
     117            RELEASE_ASSERT_NOT_REACHED();
     118        }
     119
     120        RELEASE_ASSERT_NOT_REACHED();
     121    }
     122
     123    CallMode callMode() const
     124    {
     125        return callModeFor(static_cast<CallType>(m_callType));
     126    }
     127
     128    bool isTailCall() const
     129    {
     130        return callMode() == CallMode::Tail;
     131    }
     132
     133    bool isVarargs() const
     134    {
     135        return isVarargsCallType(static_cast<CallType>(m_callType));
    84136    }
    85137
  • trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp

    r189848 r189884  
    7070    Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
    7171    OpcodeID op = vm.interpreter->getOpcodeID(instruction[0].u.opcode);
    72     if (op != op_call && op != op_construct)
     72    if (op != op_call && op != op_construct && op != op_tail_call)
    7373        return CallLinkStatus();
    7474   
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r189848 r189884  
    12491249            break;
    12501250        }
     1251        case op_tail_call: {
     1252            printCallOp(out, exec, location, it, "tail_call", DumpCaches, hasPrintedProfiling, callLinkInfos);
     1253            break;
     1254        }
    12511255        case op_call_eval: {
    12521256            printCallOp(out, exec, location, it, "call_eval", DontDumpCaches, hasPrintedProfiling, callLinkInfos);
     
    12551259           
    12561260        case op_construct_varargs:
    1257         case op_call_varargs: {
     1261        case op_call_varargs:
     1262        case op_tail_call_varargs: {
    12581263            int result = (++it)->u.operand;
    12591264            int callee = (++it)->u.operand;
     
    12631268            int varArgOffset = (++it)->u.operand;
    12641269            ++it;
    1265             printLocationAndOp(out, exec, location, it, opcode == op_call_varargs ? "call_varargs" : "construct_varargs");
     1270            printLocationAndOp(out, exec, location, it, opcode == op_call_varargs ? "call_varargs" : opcode == op_construct_varargs ? "construct_varargs" : "tail_call_varargs");
    12661271            out.printf("%s, %s, %s, %s, %d, %d", registerName(result).data(), registerName(callee).data(), registerName(thisValue).data(), registerName(arguments).data(), firstFreeRegister, varArgOffset);
    12671272            dumpValueProfiling(out, it, hasPrintedProfiling);
     
    18301835        }
    18311836        case op_call_varargs:
     1837        case op_tail_call_varargs:
    18321838        case op_construct_varargs:
    18331839        case op_get_by_val: {
     
    18791885
    18801886        case op_call:
     1887        case op_tail_call:
    18811888        case op_call_eval: {
    18821889            ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand];
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r189848 r189884  
    194194    , m_isBuiltinFunction(codeBlock->isBuiltinFunction())
    195195    , m_usesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode())
    196     , m_inTailPosition(Options::enableTailCalls() && constructorKind() == ConstructorKind::None && isStrictMode())
     196    // FIXME: We should be able to have tail call elimination with the profiler
     197    // enabled. This is currently not possible because the profiler expects
     198    // op_will_call / op_did_call pairs before and after a call, which are not
     199    // compatible with tail calls (we have no way of emitting op_did_call).
     200    // https://bugs.webkit.org/show_bug.cgi?id=148819
     201    , m_inTailPosition(Options::enableTailCalls() && constructorKind() == ConstructorKind::None && isStrictMode() && !m_shouldEmitProfileHooks)
    197202{
    198203    for (auto& constantRegister : m_linkTimeConstantRegisters)
     
    25142519RegisterID* BytecodeGenerator::emitCallInTailPosition(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
    25152520{
    2516     // FIXME: We should be emitting a new op_tail_call here when
    2517     // m_inTailPosition is false
    2518     // https://bugs.webkit.org/show_bug.cgi?id=148661
    2519     return emitCall(op_call, dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd);
     2521    return emitCall(m_inTailPosition ? op_tail_call : op_call, dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd);
    25202522}
    25212523
     
    26022604RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
    26032605{
    2604     ASSERT(opcodeID == op_call || opcodeID == op_call_eval);
     2606    ASSERT(opcodeID == op_call || opcodeID == op_call_eval || opcodeID == op_tail_call);
    26052607    ASSERT(func->refCount());
    26062608
     
    26182620            argumentRegister = expression->emitBytecode(*this, callArguments.argumentRegister(0));
    26192621            RefPtr<RegisterID> thisRegister = emitMove(newTemporary(), callArguments.thisRegister());
    2620             return emitCallVarargs(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, callArguments.profileHookRegister(), divot, divotStart, divotEnd);
     2622            return emitCallVarargs(opcodeID == op_tail_call ? op_tail_call_varargs : op_call_varargs, dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, callArguments.profileHookRegister(), divot, divotStart, divotEnd);
    26212623        }
    26222624        for (; n; n = n->m_next)
     
    26712673RegisterID* BytecodeGenerator::emitCallVarargsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
    26722674{
    2673     // FIXME: We should be emitting a new op_tail_call here when
    2674     // m_inTailPosition is false
    2675     // https://bugs.webkit.org/show_bug.cgi?id=148661
    2676     return emitCallVarargs(op_call_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
     2675    return emitCallVarargs(m_inTailPosition ? op_tail_call_varargs : op_call_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
    26772676}
    26782677
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r189848 r189884  
    678678        m_argv[i] = generator.newTemporary();
    679679        ASSERT(static_cast<size_t>(i) == m_argv.size() - 1 || m_argv[i]->index() == m_argv[i + 1]->index() - 1);
     680    }
     681
     682    // We need to ensure that the frame size is stack-aligned
     683    while ((JSStack::CallFrameHeaderSize + m_argv.size()) % stackAlignmentRegisters()) {
     684        m_argv.insert(0, generator.newTemporary());
     685        m_padding++;
    680686    }
    681687   
     
    27872793
    27882794    LabelScopePtr scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
    2789     generator.emitNode(dst, m_statement);
     2795    generator.emitNodeInTailPosition(dst, m_statement);
    27902796
    27912797    generator.emitLabel(scope->breakTarget());
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r189848 r189884  
    742742    {
    743743        addVarArgChild(callee);
    744         size_t parameterSlots = JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize + argCount;
     744        size_t frameSize = JSStack::CallFrameHeaderSize + argCount;
     745        size_t alignedFrameSize = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), frameSize);
     746        size_t parameterSlots = alignedFrameSize - JSStack::CallerFrameAndPCSize;
     747
    745748        if (parameterSlots > m_parameterSlots)
    746749            m_parameterSlots = parameterSlots;
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp

    r189848 r189884  
    43304330    void compileCallOrConstruct()
    43314331    {
    4332         int numPassedArgs = m_node->numChildren() - 1;
    4333         int numArgs = numPassedArgs;
     4332        int numArgs = m_node->numChildren() - 1;
    43344333
    43354334        LValue jsCallee = lowJSValue(m_graph.varArgChild(m_node, 0));
    43364335
    43374336        unsigned stackmapID = m_stackmapIDs++;
    4338        
     4337
     4338        unsigned frameSize = JSStack::CallFrameHeaderSize + numArgs;
     4339        unsigned alignedFrameSize = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), frameSize);
     4340        unsigned padding = alignedFrameSize - frameSize;
     4341
    43394342        Vector<LValue> arguments;
    43404343        arguments.append(m_out.constInt64(stackmapID));
    43414344        arguments.append(m_out.constInt32(sizeOfCall()));
    43424345        arguments.append(constNull(m_out.ref8));
    4343         arguments.append(m_out.constInt32(1 + JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize + numArgs));
     4346        arguments.append(m_out.constInt32(1 + alignedFrameSize - JSStack::CallerFrameAndPCSize));
    43444347        arguments.append(jsCallee); // callee -> %rax
    43454348        arguments.append(getUndef(m_out.int64)); // code block
    43464349        arguments.append(jsCallee); // callee -> stack
    43474350        arguments.append(m_out.constInt64(numArgs)); // argument count and zeros for the tag
    4348         for (int i = 0; i < numPassedArgs; ++i)
     4351        for (int i = 0; i < numArgs; ++i)
    43494352            arguments.append(lowJSValue(m_graph.varArgChild(m_node, 1 + i)));
     4353        for (unsigned i = 0; i < padding; ++i)
     4354            arguments.append(getUndef(m_out.int64));
    43504355       
    43514356        callPreflight();
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.h

    r189848 r189884  
    254254        void dumpRegisters(CallFrame*);
    255255       
    256         bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval); }
     256        bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval) || opcode == getOpcode(op_tail_call); }
    257257
    258258        void enableSampler();
     
    278278    inline CallFrame* calleeFrameForVarargs(CallFrame* callFrame, unsigned numUsedStackSlots, unsigned argumentCountIncludingThis)
    279279    {
     280#if 1
     281        // We want the new frame to be allocated on a stack aligned offset with a stack
     282        // aligned size. Align the size here.
     283        argumentCountIncludingThis = WTF::roundUpToMultipleOf(
     284            stackAlignmentRegisters(),
     285            argumentCountIncludingThis + JSStack::CallFrameHeaderSize) - JSStack::CallFrameHeaderSize;
     286
     287        // Align the frame offset here.
     288#endif
    280289        unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(
    281290            stackAlignmentRegisters(),
  • trunk/Source/JavaScriptCore/jit/CCallHelpers.h

    r189848 r189884  
    3131#include "AssemblyHelpers.h"
    3232#include "GPRInfo.h"
     33#include "StackAlignment.h"
    3334
    3435namespace JSC {
     
    20832084        jump(GPRInfo::regT1);
    20842085    }
     2086
     2087    void prepareForTailCallSlow(GPRReg calleeGPR = InvalidGPRReg)
     2088    {
     2089        GPRReg temp1 = calleeGPR == GPRInfo::regT0 ? GPRInfo::regT3 : GPRInfo::regT0;
     2090        GPRReg temp2 = calleeGPR == GPRInfo::regT1 ? GPRInfo::regT3 : GPRInfo::regT1;
     2091        GPRReg temp3 = calleeGPR == GPRInfo::regT2 ? GPRInfo::regT3 : GPRInfo::regT2;
     2092
     2093        GPRReg newFramePointer = temp1;
     2094        GPRReg newFrameSizeGPR = temp2;
     2095        {
     2096            // The old frame size is its number of arguments (or number of
     2097            // parameters in case of arity fixup), plus the frame header size,
     2098            // aligned
     2099            GPRReg oldFrameSizeGPR = temp2;
     2100            {
     2101                GPRReg argCountGPR = oldFrameSizeGPR;
     2102                load32(Address(framePointerRegister, JSStack::ArgumentCount * static_cast<int>(sizeof(Register)) + PayloadOffset), argCountGPR);
     2103
     2104                {
     2105                    GPRReg numParametersGPR = temp1;
     2106                    {
     2107                        GPRReg codeBlockGPR = numParametersGPR;
     2108                        loadPtr(Address(framePointerRegister, JSStack::CodeBlock * static_cast<int>(sizeof(Register))), codeBlockGPR);
     2109                        load32(Address(codeBlockGPR, CodeBlock::offsetOfNumParameters()), numParametersGPR);
     2110                    }
     2111
     2112                    ASSERT(numParametersGPR != argCountGPR);
     2113                    Jump argumentCountWasNotFixedUp = branch32(BelowOrEqual, numParametersGPR, argCountGPR);
     2114                    move(numParametersGPR, argCountGPR);
     2115                    argumentCountWasNotFixedUp.link(this);
     2116                }
     2117
     2118                add32(TrustedImm32(stackAlignmentRegisters() + JSStack::CallFrameHeaderSize - 1), argCountGPR, oldFrameSizeGPR);
     2119                and32(TrustedImm32(-stackAlignmentRegisters()), oldFrameSizeGPR);
     2120                // We assume < 2^28 arguments
     2121                mul32(TrustedImm32(sizeof(Register)), oldFrameSizeGPR, oldFrameSizeGPR);
     2122            }
     2123
     2124            // The new frame pointer is at framePointer + oldFrameSize - newFrameSize
     2125            ASSERT(newFramePointer != oldFrameSizeGPR);
     2126            move(framePointerRegister, newFramePointer);
     2127            addPtr(oldFrameSizeGPR, newFramePointer);
     2128
     2129            // The new frame size is just the number of arguments plus the
     2130            // frame header size, aligned
     2131            ASSERT(newFrameSizeGPR != newFramePointer);
     2132            load32(Address(stackPointerRegister, JSStack::ArgumentCount * static_cast<int>(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC)),
     2133                newFrameSizeGPR);
     2134            add32(TrustedImm32(stackAlignmentRegisters() + JSStack::CallFrameHeaderSize - 1), newFrameSizeGPR);
     2135            and32(TrustedImm32(-stackAlignmentRegisters()), newFrameSizeGPR);
     2136            // We assume < 2^28 arguments
     2137            mul32(TrustedImm32(sizeof(Register)), newFrameSizeGPR, newFrameSizeGPR);
     2138        }
     2139
     2140        GPRReg tempGPR = temp3;
     2141        ASSERT(tempGPR != newFramePointer && tempGPR != newFrameSizeGPR);
     2142
     2143        // We don't need the current frame beyond this point. Masquerade as our
     2144        // caller.
     2145#if CPU(ARM) || CPU(SH4) || CPU(ARM64)
     2146        loadPtr(Address(framePointerRegister, sizeof(void*)), linkRegister);
     2147        subPtr(TrustedImm32(2 * sizeof(void*)), newFrameSizeGPR);
     2148#elif CPU(MIPS)
     2149        loadPtr(Address(framePointerRegister, sizeof(void*)), returnAddressRegister);
     2150        subPtr(TrustedImm32(2 * sizeof(void*)), newFrameSizeGPR);
     2151#elif CPU(X86) || CPU(X86_64)
     2152        loadPtr(Address(framePointerRegister, sizeof(void*)), tempGPR);
     2153        push(tempGPR);
     2154        subPtr(TrustedImm32(sizeof(void*)), newFrameSizeGPR);
     2155#else
     2156        UNREACHABLE_FOR_PLATFORM();
     2157#endif
     2158        subPtr(newFrameSizeGPR, newFramePointer);
     2159        loadPtr(Address(framePointerRegister), framePointerRegister);
     2160
     2161
     2162        // We need to move the newFrameSizeGPR slots above the stack pointer by
     2163        // newFramePointer registers. We use pointer-sized chunks.
     2164        MacroAssembler::Label copyLoop(label());
     2165
     2166        subPtr(TrustedImm32(sizeof(void*)), newFrameSizeGPR);
     2167        loadPtr(BaseIndex(stackPointerRegister, newFrameSizeGPR, TimesOne), tempGPR);
     2168        storePtr(tempGPR, BaseIndex(newFramePointer, newFrameSizeGPR, TimesOne));
     2169
     2170        branchTest32(MacroAssembler::NonZero, newFrameSizeGPR).linkTo(copyLoop, this);
     2171
     2172        // Ready for a jump!
     2173        move(newFramePointer, stackPointerRegister);
     2174    }
    20852175};
    20862176
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r189848 r189884  
    198198        DEFINE_OP(op_bitxor)
    199199        DEFINE_OP(op_call)
     200        DEFINE_OP(op_tail_call)
    200201        DEFINE_OP(op_call_eval)
    201202        DEFINE_OP(op_call_varargs)
     203        DEFINE_OP(op_tail_call_varargs)
    202204        DEFINE_OP(op_construct_varargs)
    203205        DEFINE_OP(op_catch)
     
    372374        DEFINE_SLOWCASE_OP(op_bitxor)
    373375        DEFINE_SLOWCASE_OP(op_call)
     376        DEFINE_SLOWCASE_OP(op_tail_call)
    374377        DEFINE_SLOWCASE_OP(op_call_eval)
    375378        DEFINE_SLOWCASE_OP(op_call_varargs)
     379        DEFINE_SLOWCASE_OP(op_tail_call_varargs)
    376380        DEFINE_SLOWCASE_OP(op_construct_varargs)
    377381        DEFINE_SLOWCASE_OP(op_construct)
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r189848 r189884  
    488488        void emit_op_bitxor(Instruction*);
    489489        void emit_op_call(Instruction*);
     490        void emit_op_tail_call(Instruction*);
    490491        void emit_op_call_eval(Instruction*);
    491492        void emit_op_call_varargs(Instruction*);
     493        void emit_op_tail_call_varargs(Instruction*);
    492494        void emit_op_construct_varargs(Instruction*);
    493495        void emit_op_catch(Instruction*);
     
    601603        void emitSlow_op_bitxor(Instruction*, Vector<SlowCaseEntry>::iterator&);
    602604        void emitSlow_op_call(Instruction*, Vector<SlowCaseEntry>::iterator&);
     605        void emitSlow_op_tail_call(Instruction*, Vector<SlowCaseEntry>::iterator&);
    603606        void emitSlow_op_call_eval(Instruction*, Vector<SlowCaseEntry>::iterator&);
    604607        void emitSlow_op_call_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&);
     608        void emitSlow_op_tail_call_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&);
    605609        void emitSlow_op_construct_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&);
    606610        void emitSlow_op_construct(Instruction*, Vector<SlowCaseEntry>::iterator&);
     
    825829
    826830        Call emitNakedCall(CodePtr function = CodePtr());
     831        Call emitNakedTailCall(CodePtr function = CodePtr());
    827832
    828833        // Loads the character value of a single character string into dst.
  • trunk/Source/JavaScriptCore/jit/JITCall.cpp

    r189848 r189884  
    146146    COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_varargs), call_and_call_varargs_opcodes_must_be_same_length);
    147147    COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct_varargs), call_and_construct_varargs_opcodes_must_be_same_length);
     148    COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_tail_call), call_and_tail_call_opcodes_must_be_same_length);
     149    COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_tail_call_varargs), call_and_tail_call_varargs_opcodes_must_be_same_length);
    148150    CallLinkInfo* info;
    149151    if (opcodeID != op_call_eval)
    150152        info = m_codeBlock->addCallLinkInfo();
    151     if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs)
     153    if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs || opcodeID == op_tail_call_varargs)
    152154        compileSetupVarargsFrame(instruction, info);
    153155    else {
     
    173175
    174176    store64(regT0, Address(stackPointerRegister, JSStack::Callee * static_cast<int>(sizeof(Register)) - sizeof(CallerFrameAndPC)));
    175    
     177
    176178    if (opcodeID == op_call_eval) {
    177179        compileCallEval(instruction);
    178180        return;
    179181    }
     182
     183    if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs)
     184        emitRestoreCalleeSaves();
    180185
    181186    DataLabelPtr addressOfLinkedFunctionCheck;
     
    189194    m_callCompilationInfo[callLinkInfoIndex].callLinkInfo = info;
    190195
     196    if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs) {
     197        prepareForTailCallSlow();
     198        m_callCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedTailCall();
     199        return;
     200    }
     201
    191202    m_callCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall();
    192203
     
    209220
    210221    move(TrustedImmPtr(m_callCompilationInfo[callLinkInfoIndex].callLinkInfo), regT2);
     222
    211223    m_callCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm->getCTIStub(linkCallThunkGenerator).code());
     224
     225    if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs) {
     226        abortWithReason(JITDidReturnFromTailCall);
     227        return;
     228    }
    212229
    213230    addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
     
    224241}
    225242
     243void JIT::emit_op_tail_call(Instruction* currentInstruction)
     244{
     245    compileOpCall(op_tail_call, currentInstruction, m_callLinkInfoIndex++);
     246}
     247
    226248void JIT::emit_op_call_eval(Instruction* currentInstruction)
    227249{
     
    233255    compileOpCall(op_call_varargs, currentInstruction, m_callLinkInfoIndex++);
    234256}
    235    
     257
     258void JIT::emit_op_tail_call_varargs(Instruction* currentInstruction)
     259{
     260    compileOpCall(op_tail_call_varargs, currentInstruction, m_callLinkInfoIndex++);
     261}
     262
    236263void JIT::emit_op_construct_varargs(Instruction* currentInstruction)
    237264{
     
    247274{
    248275    compileOpCallSlowCase(op_call, currentInstruction, iter, m_callLinkInfoIndex++);
     276}
     277
     278void JIT::emitSlow_op_tail_call(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     279{
     280    compileOpCallSlowCase(op_tail_call, currentInstruction, iter, m_callLinkInfoIndex++);
    249281}
    250282
     
    258290    compileOpCallSlowCase(op_call_varargs, currentInstruction, iter, m_callLinkInfoIndex++);
    259291}
     292
     293void JIT::emitSlow_op_tail_call_varargs(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     294{
     295    compileOpCallSlowCase(op_tail_call_varargs, currentInstruction, iter, m_callLinkInfoIndex++);
     296}
    260297   
    261298void JIT::emitSlow_op_construct_varargs(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
  • trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp

    r189848 r189884  
    7070}
    7171
     72void JIT::emitSlow_op_tail_call(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     73{
     74    compileOpCallSlowCase(op_tail_call, currentInstruction, iter, m_callLinkInfoIndex++);
     75}
     76
    7277void JIT::emitSlow_op_call_eval(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    7378{
     
    7984    compileOpCallSlowCase(op_call_varargs, currentInstruction, iter, m_callLinkInfoIndex++);
    8085}
     86
     87void JIT::emitSlow_op_tail_call_varargs(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     88{
     89    compileOpCallSlowCase(op_tail_call_varargs, currentInstruction, iter, m_callLinkInfoIndex++);
     90}
    8191   
    8292void JIT::emitSlow_op_construct_varargs(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     
    95105}
    96106
     107void JIT::emit_op_tail_call(Instruction* currentInstruction)
     108{
     109    compileOpCall(op_tail_call, currentInstruction, m_callLinkInfoIndex++);
     110}
     111
    97112void JIT::emit_op_call_eval(Instruction* currentInstruction)
    98113{
     
    103118{
    104119    compileOpCall(op_call_varargs, currentInstruction, m_callLinkInfoIndex++);
     120}
     121
     122void JIT::emit_op_tail_call_varargs(Instruction* currentInstruction)
     123{
     124    compileOpCall(op_tail_call_varargs, currentInstruction, m_callLinkInfoIndex++);
    105125}
    106126   
     
    211231    if (opcodeID != op_call_eval)
    212232        info = m_codeBlock->addCallLinkInfo();
    213     if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs)
     233    if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs || opcodeID == op_tail_call_varargs)
    214234        compileSetupVarargsFrame(instruction, info);
    215235    else {
     
    242262    }
    243263
     264    if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs)
     265        emitRestoreCalleeSaves();
     266
    244267    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
    245268
     
    256279
    257280    checkStackPointerAlignment();
     281    if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs) {
     282        prepareForTailCallSlow();
     283        m_callCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedTailCall();
     284        return;
     285    }
     286
    258287    m_callCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall();
    259288
     
    276305
    277306    move(TrustedImmPtr(m_callCompilationInfo[callLinkInfoIndex].callLinkInfo), regT2);
     307
     308    if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs)
     309        emitRestoreCalleeSaves();
     310
    278311    m_callCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm->getCTIStub(linkCallThunkGenerator).code());
     312
     313    if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs) {
     314        abortWithReason(JITDidReturnFromTailCall);
     315        return;
     316    }
    279317
    280318    addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
  • trunk/Source/JavaScriptCore/jit/JITInlines.h

    r189848 r189884  
    126126}
    127127
     128ALWAYS_INLINE JIT::Call JIT::emitNakedTailCall(CodePtr function)
     129{
     130    ASSERT(m_bytecodeOffset != std::numeric_limits<unsigned>::max()); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
     131    Call nakedCall = nearTailCall();
     132    m_calls.append(CallRecord(nakedCall, m_bytecodeOffset, function.executableAddress()));
     133    return nakedCall;
     134}
     135
    128136ALWAYS_INLINE void JIT::updateTopCallFrame()
    129137{
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r189849 r189884  
    683683}
    684684
    685 static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializationKind kind)
     685static SlowPathReturnType handleHostCall(ExecState* execCallee, JSValue callee, CallLinkInfo* callLinkInfo)
    686686{
    687687    ExecState* exec = execCallee->callerFrame();
     
    690690    execCallee->setCodeBlock(0);
    691691
    692     if (kind == CodeForCall) {
     692    if (callLinkInfo->specializationKind() == CodeForCall) {
    693693        CallData callData;
    694694        CallType callType = getCallData(callee, callData);
     
    700700            execCallee->setCallee(asObject(callee));
    701701            vm->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
    702             if (vm->exception())
    703                 return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
    704 
    705             return reinterpret_cast<void*>(getHostCallReturnValue);
     702            if (vm->exception()) {
     703                return encodeResult(
     704                    vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
     705                    reinterpret_cast<void*>(KeepTheFrame));
     706            }
     707
     708            return encodeResult(
     709                bitwise_cast<void*>(getHostCallReturnValue),
     710                reinterpret_cast<void*>(callLinkInfo->callMode() == CallMode::Tail ? ReuseTheFrame : KeepTheFrame));
    706711        }
    707712   
    708713        ASSERT(callType == CallTypeNone);
    709714        exec->vm().throwException(exec, createNotAFunctionError(exec, callee));
    710         return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
    711     }
    712 
    713     ASSERT(kind == CodeForConstruct);
     715        return encodeResult(
     716            vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
     717            reinterpret_cast<void*>(KeepTheFrame));
     718    }
     719
     720    ASSERT(callLinkInfo->specializationKind() == CodeForConstruct);
    714721   
    715722    ConstructData constructData;
     
    722729        execCallee->setCallee(asObject(callee));
    723730        vm->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
    724         if (vm->exception())
    725             return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
    726 
    727         return reinterpret_cast<void*>(getHostCallReturnValue);
     731        if (vm->exception()) {
     732            return encodeResult(
     733                vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
     734                reinterpret_cast<void*>(KeepTheFrame));
     735        }
     736
     737        return encodeResult(bitwise_cast<void*>(getHostCallReturnValue), reinterpret_cast<void*>(KeepTheFrame));
    728738    }
    729739   
    730740    ASSERT(constructType == ConstructTypeNone);
    731741    exec->vm().throwException(exec, createNotAConstructorError(exec, callee));
    732     return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
    733 }
    734 
    735 char* JIT_OPERATION operationLinkCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
     742    return encodeResult(
     743        vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
     744        reinterpret_cast<void*>(KeepTheFrame));
     745}
     746
     747SlowPathReturnType JIT_OPERATION operationLinkCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
    736748{
    737749    ExecState* exec = execCallee->callerFrame();
     
    746758        // expensive.
    747759        // https://bugs.webkit.org/show_bug.cgi?id=144458
    748         return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind));
     760        return handleHostCall(execCallee, calleeAsValue, callLinkInfo);
    749761    }
    750762
     
    775787        if (!isCall(kind) && functionExecutable->constructAbility() == ConstructAbility::CannotConstruct) {
    776788            exec->vm().throwException(exec, createNotAConstructorError(exec, callee));
    777             return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
     789            return encodeResult(
     790                vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
     791                reinterpret_cast<void*>(KeepTheFrame));
    778792        }
    779793
     
    781795        if (error) {
    782796            exec->vm().throwException(exec, error);
    783             return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
     797            return encodeResult(
     798                vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
     799                reinterpret_cast<void*>(KeepTheFrame));
    784800        }
    785801        codeBlock = functionExecutable->codeBlockFor(kind);
    786802        ArityCheckMode arity;
    787         if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo->callType() == CallLinkInfo::CallVarargs || callLinkInfo->callType() == CallLinkInfo::ConstructVarargs)
     803        if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo->isVarargs())
    788804            arity = MustCheckArity;
    789805        else
     
    796812        linkFor(execCallee, *callLinkInfo, codeBlock, callee, codePtr);
    797813   
    798     return reinterpret_cast<char*>(codePtr.executableAddress());
    799 }
    800 
    801 inline char* virtualForWithFunction(
     814    return encodeResult(codePtr.executableAddress(), reinterpret_cast<void*>(callLinkInfo->callMode() == CallMode::Tail ? ReuseTheFrame : KeepTheFrame));
     815}
     816
     817inline SlowPathReturnType virtualForWithFunction(
    802818    ExecState* execCallee, CallLinkInfo* callLinkInfo, JSCell*& calleeAsFunctionCell)
    803819{
     
    810826    calleeAsFunctionCell = getJSFunction(calleeAsValue);
    811827    if (UNLIKELY(!calleeAsFunctionCell))
    812         return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind));
     828        return handleHostCall(execCallee, calleeAsValue, callLinkInfo);
    813829   
    814830    JSFunction* function = jsCast<JSFunction*>(calleeAsFunctionCell);
     
    825841            if (!isCall(kind) && functionExecutable->constructAbility() == ConstructAbility::CannotConstruct) {
    826842                exec->vm().throwException(exec, createNotAConstructorError(exec, function));
    827                 return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
     843                return encodeResult(
     844                    vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
     845                    reinterpret_cast<void*>(KeepTheFrame));
    828846            }
    829847
     
    831849            if (error) {
    832850                exec->vm().throwException(exec, error);
    833                 return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
     851                return encodeResult(
     852                    vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
     853                    reinterpret_cast<void*>(KeepTheFrame));
    834854            }
    835855        } else {
     
    845865        }
    846866    }
    847     return reinterpret_cast<char*>(executable->entrypointFor(
    848         *vm, kind, MustCheckArity, callLinkInfo->registerPreservationMode()).executableAddress());
    849 }
    850 
    851 char* JIT_OPERATION operationLinkPolymorphicCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
     867    return encodeResult(executable->entrypointFor(
     868        *vm, kind, MustCheckArity, callLinkInfo->registerPreservationMode()).executableAddress(),
     869        reinterpret_cast<void*>(callLinkInfo->callMode() == CallMode::Tail ? ReuseTheFrame : KeepTheFrame));
     870}
     871
     872SlowPathReturnType JIT_OPERATION operationLinkPolymorphicCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
    852873{
    853874    ASSERT(callLinkInfo->specializationKind() == CodeForCall);
    854875    JSCell* calleeAsFunctionCell;
    855     char* result = virtualForWithFunction(execCallee, callLinkInfo, calleeAsFunctionCell);
     876    SlowPathReturnType result = virtualForWithFunction(execCallee, callLinkInfo, calleeAsFunctionCell);
    856877
    857878    linkPolymorphicCall(execCallee, *callLinkInfo, CallVariant(calleeAsFunctionCell));
     
    860881}
    861882
    862 char* JIT_OPERATION operationVirtualCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
     883SlowPathReturnType JIT_OPERATION operationVirtualCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
    863884{
    864885    JSCell* calleeAsFunctionCellIgnored;
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r189848 r189884  
    238238typedef char* JIT_OPERATION (*P_JITOperation_EStZ)(ExecState*, Structure*, int32_t);
    239239typedef char* JIT_OPERATION (*P_JITOperation_EZZ)(ExecState*, int32_t, int32_t);
     240typedef SlowPathReturnType JIT_OPERATION (*Sprt_JITOperation_ECli)(ExecState*, CallLinkInfo*);
    240241typedef StringImpl* JIT_OPERATION (*T_JITOperation_EJss)(ExecState*, JSString*);
    241242typedef JSString* JIT_OPERATION (*Jss_JITOperation_EZ)(ExecState*, int32_t);
     
    279280void JIT_OPERATION operationDirectPutByValGeneric(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*) WTF_INTERNAL;
    280281EncodedJSValue JIT_OPERATION operationCallEval(ExecState*, ExecState*) WTF_INTERNAL;
    281 char* JIT_OPERATION operationLinkCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
    282 char* JIT_OPERATION operationLinkPolymorphicCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
    283 char* JIT_OPERATION operationVirtualCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
     282SlowPathReturnType JIT_OPERATION operationLinkCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
     283SlowPathReturnType JIT_OPERATION operationLinkPolymorphicCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
     284SlowPathReturnType JIT_OPERATION operationVirtualCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
    284285
    285286size_t JIT_OPERATION operationCompareLess(ExecState*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/jit/Repatch.cpp

    r189848 r189884  
    610610    CodeBlock* callerCodeBlock = exec->callerFrame()->codeBlock();
    611611    VM* vm = callerCodeBlock->vm();
    612    
     612
    613613    if (shouldShowDisassemblyFor(callerCodeBlock))
    614614        dataLog("Linking virtual call at ", *callerCodeBlock, " ", exec->callerFrame()->codeOrigin(), "\n");
     
    681681            // If we cannot handle a callee, assume that it's better for this whole thing to be a
    682682            // virtual call.
    683             if (exec->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo.callType() == CallLinkInfo::CallVarargs || callLinkInfo.callType() == CallLinkInfo::ConstructVarargs) {
     683            if (exec->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo.isVarargs()) {
    684684                linkVirtualFor(exec, callLinkInfo);
    685685                return;
     
    804804                CCallHelpers::Address(fastCountsBaseGPR, caseIndex * sizeof(uint32_t)));
    805805        }
    806         calls[caseIndex].call = stubJit.nearCall();
     806        if (callLinkInfo.isTailCall()) {
     807            stubJit.prepareForTailCallSlow();
     808            calls[caseIndex].call = stubJit.nearTailCall();
     809        } else
     810            calls[caseIndex].call = stubJit.nearCall();
    807811        calls[caseIndex].codePtr = codePtr;
    808812        done.append(stubJit.jump());
  • trunk/Source/JavaScriptCore/jit/SetupVarargsFrame.cpp

    r181993 r189884  
    3838{
    3939    jit.move(numUsedSlotsGPR, resultGPR);
     40    // We really want to make sure the size of the new call frame is a multiple of
     41    // stackAlignmentRegisters(), however it is easier to accomplish this by
     42    // rounding numUsedSlotsGPR to the next multiple of stackAlignmentRegisters().
     43    // Together with the rounding below, we will assure that the new call frame is
     44    // located on a stackAlignmentRegisters() boundary and a multiple of
     45    // stackAlignmentRegisters() in size.
     46    jit.addPtr(CCallHelpers::TrustedImm32(stackAlignmentRegisters() - 1), resultGPR);
     47    jit.andPtr(CCallHelpers::TrustedImm32(~(stackAlignmentRegisters() - 1)), resultGPR);
     48
    4049    jit.addPtr(lengthGPR, resultGPR);
    4150    jit.addPtr(CCallHelpers::TrustedImm32(JSStack::CallFrameHeaderSize + (lengthIncludesThis? 0 : 1)), resultGPR);
  • trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp

    r189848 r189884  
    8080
    8181static void slowPathFor(
    82     CCallHelpers& jit, VM* vm, P_JITOperation_ECli slowPathFunction)
     82    CCallHelpers& jit, VM* vm, Sprt_JITOperation_ECli slowPathFunction)
    8383{
    8484    jit.emitFunctionPrologue();
    8585    jit.storePtr(GPRInfo::callFrameRegister, &vm->topCallFrame);
     86#if OS(WINDOWS) && CPU(X86_64)
     87    // Windows X86_64 needs some space pointed to by arg0 for return types larger than 64 bits.
     88    // Other argument values are shift by 1. Use space on the stack for our two return values.
     89    // Moving the stack down maxFrameExtentForSlowPathCall bytes gives us room for our 3 arguments
     90    // and space for the 16 byte return area.
     91    jit.addPtr(CCallHelpers::TrustedImm32(-maxFrameExtentForSlowPathCall), CCallHelpers::stackPointerRegister);
     92    jit.move(GPRInfo::regT2, GPRInfo::argumentGPR2);
     93    jit.addPtr(CCallHelpers::TrustedImm32(32), CCallHelpers::stackPointerRegister, GPRInfo::argumentGPR0);
     94    jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
     95    jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast<void*>(slowPathFunction)), GPRInfo::nonArgGPR0);
     96    emitPointerValidation(jit, GPRInfo::nonArgGPR0);
     97    jit.call(GPRInfo::nonArgGPR0);
     98    jit.loadPtr(CCallHelpers::Address(GPRInfo::returnValueGPR, 8), GPRInfo::returnValueGPR2);
     99    jit.loadPtr(CCallHelpers::Address(GPRInfo::returnValueGPR), GPRInfo::returnValueGPR);
     100    jit.addPtr(CCallHelpers::TrustedImm32(maxFrameExtentForSlowPathCall), CCallHelpers::stackPointerRegister);
     101#else
    86102    if (maxFrameExtentForSlowPathCall)
    87103        jit.addPtr(CCallHelpers::TrustedImm32(-maxFrameExtentForSlowPathCall), CCallHelpers::stackPointerRegister);
     
    92108    if (maxFrameExtentForSlowPathCall)
    93109        jit.addPtr(CCallHelpers::TrustedImm32(maxFrameExtentForSlowPathCall), CCallHelpers::stackPointerRegister);
    94    
     110#endif
     111
    95112    // This slow call will return the address of one of the following:
    96113    // 1) Exception throwing thunk.
    97114    // 2) Host call return value returner thingy.
    98115    // 3) The function to call.
     116    // The second return value GPR will hold a non-zero value for tail calls.
     117
    99118    emitPointerValidation(jit, GPRInfo::returnValueGPR);
    100119    jit.emitFunctionEpilogue();
     120
     121    RELEASE_ASSERT(reinterpret_cast<void*>(KeepTheFrame) == reinterpret_cast<void*>(0));
     122    CCallHelpers::Jump doNotTrash = jit.branchTestPtr(CCallHelpers::Zero, GPRInfo::returnValueGPR2);
     123
     124    jit.preserveReturnAddressAfterCall(GPRInfo::nonPreservedNonReturnGPR);
     125    jit.prepareForTailCallSlow(GPRInfo::returnValueGPR);
     126
     127    doNotTrash.link(&jit);
    101128    jit.jump(GPRInfo::returnValueGPR);
    102129}
     
    109136    // to be in regT0/regT1 (payload/tag), the CallFrame to have already
    110137    // been adjusted, and all other registers to be available for use.
    111    
    112138    CCallHelpers jit(vm);
    113139   
     
    186212    // Make a tail call. This will return back to JIT code.
    187213    emitPointerValidation(jit, GPRInfo::regT4);
     214    if (callLinkInfo.isTailCall()) {
     215        jit.preserveReturnAddressAfterCall(GPRInfo::regT0);
     216        jit.prepareForTailCallSlow(GPRInfo::regT4);
     217    }
    188218    jit.jump(GPRInfo::regT4);
    189219
     
    197227    return FINALIZE_CODE(
    198228        patchBuffer,
    199         ("Virtual %s%s slow path thunk",
    200         callLinkInfo.specializationKind() == CodeForCall ? "call" : "construct",
    201         callLinkInfo.registerPreservationMode() == MustPreserveRegisters ? " that preserves registers" : ""));
     229        ("Virtual %s slow path thunk",
     230        callLinkInfo.callMode() == CallMode::Regular ? "call" : callLinkInfo.callMode() == CallMode::Tail ? "tail call" : "construct"));
    202231}
    203232
     
    368397    JSInterfaceJIT jit(vm);
    369398
    370     // We enter with fixup count, in aligned stack units, in argumentGPR0 and the return thunk in argumentGPR1
     399    // We enter with fixup count in argumentGPR0
    371400    // We have the guarantee that a0, a1, a2, t3, t4 and t5 (or t0 for Windows) are all distinct :-)
    372401#if USE(JSVALUE64)
     
    379408    jit.pop(JSInterfaceJIT::regT4);
    380409#  endif
    381     jit.lshift32(JSInterfaceJIT::TrustedImm32(logStackAlignmentRegisters()), JSInterfaceJIT::argumentGPR0);
    382     jit.neg64(JSInterfaceJIT::argumentGPR0);
    383410    jit.move(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::regT3);
    384411    jit.load32(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * sizeof(Register)), JSInterfaceJIT::argumentGPR2);
    385412    jit.add32(JSInterfaceJIT::TrustedImm32(JSStack::CallFrameHeaderSize), JSInterfaceJIT::argumentGPR2);
     413
     414    // Check to see if we have extra slots we can use
     415    jit.move(JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::argumentGPR1);
     416    jit.and32(JSInterfaceJIT::TrustedImm32(stackAlignmentRegisters() - 1), JSInterfaceJIT::argumentGPR1);
     417    JSInterfaceJIT::Jump noExtraSlot = jit.branchTest32(MacroAssembler::Zero, JSInterfaceJIT::argumentGPR1);
     418    jit.move(JSInterfaceJIT::TrustedImm64(ValueUndefined), extraTemp);
     419    JSInterfaceJIT::Label fillExtraSlots(jit.label());
     420    jit.store64(extraTemp, MacroAssembler::BaseIndex(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::argumentGPR2, JSInterfaceJIT::TimesEight));
     421    jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2);
     422    jit.branchSub32(JSInterfaceJIT::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR1).linkTo(fillExtraSlots, &jit);
     423    jit.and32(JSInterfaceJIT::TrustedImm32(-stackAlignmentRegisters()), JSInterfaceJIT::argumentGPR0);
     424    JSInterfaceJIT::Jump done = jit.branchTest32(MacroAssembler::Zero, JSInterfaceJIT::argumentGPR0);
     425    noExtraSlot.link(&jit);
     426
     427    jit.neg64(JSInterfaceJIT::argumentGPR0);
    386428
    387429    // Move current frame down argumentGPR0 number of slots
     
    392434    jit.branchSub32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2).linkTo(copyLoop, &jit);
    393435
    394     // Fill in argumentGPR0 - 1 missing arg slots with undefined
     436    // Fill in argumentGPR0 missing arg slots with undefined
    395437    jit.move(JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::argumentGPR2);
    396438    jit.move(JSInterfaceJIT::TrustedImm64(ValueUndefined), extraTemp);
    397     jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2);
    398439    JSInterfaceJIT::Label fillUndefinedLoop(jit.label());
    399440    jit.store64(extraTemp, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
     
    407448    jit.addPtr(extraTemp, JSInterfaceJIT::stackPointerRegister);
    408449
     450    done.link(&jit);
     451
    409452#  if CPU(X86_64)
    410453    jit.push(JSInterfaceJIT::regT4);
     
    415458    jit.pop(JSInterfaceJIT::regT4);
    416459#  endif
    417     jit.lshift32(JSInterfaceJIT::TrustedImm32(logStackAlignmentRegisters()), JSInterfaceJIT::argumentGPR0);
    418     jit.neg32(JSInterfaceJIT::argumentGPR0);
    419460    jit.move(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::regT3);
    420461    jit.load32(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * sizeof(Register)), JSInterfaceJIT::argumentGPR2);
    421462    jit.add32(JSInterfaceJIT::TrustedImm32(JSStack::CallFrameHeaderSize), JSInterfaceJIT::argumentGPR2);
    422463
     464    // Check to see if we have extra slots we can use
     465    jit.move(JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::argumentGPR1);
     466    jit.and32(JSInterfaceJIT::TrustedImm32(stackAlignmentRegisters() - 1), JSInterfaceJIT::argumentGPR1);
     467    JSInterfaceJIT::Jump noExtraSlot = jit.branchTest32(MacroAssembler::Zero, JSInterfaceJIT::argumentGPR1);
     468    JSInterfaceJIT::Label fillExtraSlots(jit.label());
     469    jit.move(JSInterfaceJIT::TrustedImm32(0), JSInterfaceJIT::regT5);
     470    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::argumentGPR2, JSInterfaceJIT::TimesEight, PayloadOffset));
     471    jit.move(JSInterfaceJIT::TrustedImm32(JSValue::UndefinedTag), JSInterfaceJIT::regT5);
     472    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::argumentGPR2, JSInterfaceJIT::TimesEight, TagOffset));
     473    jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2);
     474    jit.branchSub32(JSInterfaceJIT::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR1).linkTo(fillExtraSlots, &jit);
     475    jit.and32(JSInterfaceJIT::TrustedImm32(-stackAlignmentRegisters()), JSInterfaceJIT::argumentGPR0);
     476    JSInterfaceJIT::Jump done = jit.branchTest32(MacroAssembler::Zero, JSInterfaceJIT::argumentGPR0);
     477    noExtraSlot.link(&jit);
     478
     479    jit.neg32(JSInterfaceJIT::argumentGPR0);
     480
    423481    // Move current frame down argumentGPR0 number of slots
    424482    JSInterfaceJIT::Label copyLoop(jit.label());
    425     jit.load32(JSInterfaceJIT::regT3, JSInterfaceJIT::regT5);
    426     jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
    427     jit.load32(MacroAssembler::Address(JSInterfaceJIT::regT3, 4), JSInterfaceJIT::regT5);
    428     jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, 4));
     483    jit.load32(MacroAssembler::Address(JSInterfaceJIT::regT3, PayloadOffset), JSInterfaceJIT::regT5);
     484    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, PayloadOffset));
     485    jit.load32(MacroAssembler::Address(JSInterfaceJIT::regT3, TagOffset), JSInterfaceJIT::regT5);
     486    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, TagOffset));
    429487    jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3);
    430488    jit.branchSub32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2).linkTo(copyLoop, &jit);
    431489
    432     // Fill in argumentGPR0 - 1 missing arg slots with undefined
     490    // Fill in argumentGPR0 missing arg slots with undefined
    433491    jit.move(JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::argumentGPR2);
    434     jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2);
    435492    JSInterfaceJIT::Label fillUndefinedLoop(jit.label());
    436493    jit.move(JSInterfaceJIT::TrustedImm32(0), JSInterfaceJIT::regT5);
    437     jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
     494    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, PayloadOffset));
    438495    jit.move(JSInterfaceJIT::TrustedImm32(JSValue::UndefinedTag), JSInterfaceJIT::regT5);
    439     jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, 4));
     496    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, TagOffset));
    440497
    441498    jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3);
     
    448505    jit.addPtr(JSInterfaceJIT::regT5, JSInterfaceJIT::stackPointerRegister);
    449506
     507    done.link(&jit);
     508
    450509#  if CPU(X86)
    451510    jit.push(JSInterfaceJIT::regT4);
     
    456515    LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
    457516    return FINALIZE_CODE(patchBuffer, ("fixup arity"));
     517}
     518
     519MacroAssemblerCodeRef unreachableGenerator(VM* vm)
     520{
     521    JSInterfaceJIT jit(vm);
     522
     523    jit.breakpoint();
     524
     525    LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
     526    return FINALIZE_CODE(patchBuffer, ("unreachable thunk"));
    458527}
    459528
  • trunk/Source/JavaScriptCore/jit/ThunkGenerators.h

    r189848 r189884  
    3535
    3636class CallLinkInfo;
     37class CCallHelpers;
    3738
    3839MacroAssemblerCodeRef throwExceptionFromCallSlowPathGenerator(VM*);
    3940
     41MacroAssemblerCodeRef linkCallThunk(VM*, CallLinkInfo&, CodeSpecializationKind, RegisterPreservationMode);
    4042MacroAssemblerCodeRef linkCallThunkGenerator(VM*);
    4143MacroAssemblerCodeRef linkPolymorphicCallThunkGenerator(VM*);
     
    4749MacroAssemblerCodeRef nativeTailCallGenerator(VM*);
    4850MacroAssemblerCodeRef arityFixupGenerator(VM*);
     51MacroAssemblerCodeRef unreachableGenerator(VM*);
    4952
    5053MacroAssemblerCodeRef baselineGetterReturnThunkGenerator(VM* vm);
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r189848 r189884  
    168168
    169169const StackAlignment = 16
     170const StackAlignmentSlots = 2
    170171const StackAlignmentMask = StackAlignment - 1
    171172
     
    698699end
    699700
    700 macro callTargetFunction(callLinkInfo, calleeFramePtr)
    701     move calleeFramePtr, sp
     701macro callTargetFunction(callee)
    702702    if C_LOOP
    703         cloopCallJSFunction LLIntCallLinkInfo::machineCodeTarget[callLinkInfo]
     703        cloopCallJSFunction callee
    704704    else
    705         call LLIntCallLinkInfo::machineCodeTarget[callLinkInfo]
     705        call callee
    706706    end
    707707    restoreStackPointerAfterCall()
     
    709709end
    710710
    711 macro slowPathForCall(slowPath)
     711macro prepareForRegularCall(callee, temp1, temp2, temp3)
     712    addp CallerFrameAndPCSize, sp
     713end
     714
     715# sp points to the new frame
     716macro prepareForTailCall(callee, temp1, temp2, temp3)
     717    restoreCalleeSavesUsedByLLInt()
     718
     719    loadi PayloadOffset + ArgumentCount[cfr], temp2
     720    loadp CodeBlock[cfr], temp1
     721    loadp CodeBlock::m_numParameters[temp1], temp1
     722    bilteq temp1, temp2, .noArityFixup
     723    move temp1, temp2
     724
     725.noArityFixup:
     726    # We assume < 2^28 arguments
     727    muli SlotSize, temp2
     728    addi StackAlignment - 1 + CallFrameHeaderSize, temp2
     729    andi ~StackAlignmentMask, temp2
     730
     731    move cfr, temp1
     732    addp temp2, temp1
     733
     734    loadi PayloadOffset + ArgumentCount[sp], temp2
     735    # We assume < 2^28 arguments
     736    muli SlotSize, temp2
     737    addi StackAlignment - 1 + CallFrameHeaderSize, temp2
     738    andi ~StackAlignmentMask, temp2
     739
     740    if ARM or SH4 or ARM64 or C_LOOP or MIPS
     741        addp 2 * PtrSize, sp
     742        subi 2 * PtrSize, temp2
     743        loadp PtrSize[cfr], lr
     744    else
     745        addp PtrSize, sp
     746        subi PtrSize, temp2
     747        loadp PtrSize[cfr], temp3
     748        storep temp3, [sp]
     749    end
     750
     751    subp temp2, temp1
     752    loadp [cfr], cfr
     753
     754.copyLoop:
     755    subi PtrSize, temp2
     756    loadp [sp, temp2, 1], temp3
     757    storep temp3, [temp1, temp2, 1]
     758    btinz temp2, .copyLoop
     759
     760    move temp1, sp
     761    jmp callee
     762end
     763
     764macro slowPathForCall(slowPath, prepareCall)
    712765    callCallSlowPath(
    713766        slowPath,
    714         macro (callee, calleeFrame)
    715             btpz calleeFrame, .dontUpdateSP
    716             if ARMv7
    717                 addp CallerFrameAndPCSize, calleeFrame, calleeFrame
    718                 move calleeFrame, sp
    719             else
    720                 addp CallerFrameAndPCSize, calleeFrame, sp
    721             end
     767        # Those are r0 and r1
     768        macro (callee, calleeFramePtr)
     769            btpz calleeFramePtr, .dontUpdateSP
     770            move calleeFramePtr, sp
     771            prepareCall(callee, t2, t3, t4)
    722772        .dontUpdateSP:
    723             if C_LOOP
    724                 cloopCallJSFunction callee
    725             else
    726                 call callee
    727             end
    728             restoreStackPointerAfterCall()
    729             dispatchAfterCall()
     773            callTargetFunction(callee)
    730774        end)
    731775end
     
    14161460    traceExecution()
    14171461    arrayProfileForCall()
    1418     doCall(_llint_slow_path_call)
    1419 
     1462    doCall(_llint_slow_path_call, prepareForRegularCall)
     1463
     1464_llint_op_tail_call:
     1465    traceExecution()
     1466    arrayProfileForCall()
     1467    checkSwitchToJITForEpilogue()
     1468    doCall(_llint_slow_path_call, prepareForTailCall)
    14201469
    14211470_llint_op_construct:
    14221471    traceExecution()
    1423     doCall(_llint_slow_path_construct)
    1424 
    1425 
    1426 _llint_op_call_varargs:
    1427     traceExecution()
     1472    doCall(_llint_slow_path_construct, prepareForRegularCall)
     1473
     1474macro doCallVarargs(slowPath, prepareCall)
    14281475    callSlowPath(_llint_slow_path_size_frame_for_varargs)
    14291476    branchIfException(_llint_throw_from_slow_path_trampoline)
     
    14401487        end
    14411488    end
    1442     slowPathForCall(_llint_slow_path_call_varargs)
     1489    slowPathForCall(slowPath, prepareCall)
     1490end
     1491
     1492_llint_op_call_varargs:
     1493    traceExecution()
     1494    doCallVarargs(_llint_slow_path_call_varargs, prepareForRegularCall)
     1495
     1496_llint_op_tail_call_varargs:
     1497    traceExecution()
     1498    checkSwitchToJITForEpilogue()
     1499    # We lie and perform the tail call instead of preparing it since we can't
     1500    # prepare the frame for a call opcode
     1501    doCallVarargs(_llint_slow_path_call_varargs, prepareForTailCall)
    14431502
    14441503_llint_op_construct_varargs:
    14451504    traceExecution()
    1446     callSlowPath(_llint_slow_path_size_frame_for_varargs)
    1447     branchIfException(_llint_throw_from_slow_path_trampoline)
    1448     # calleeFrame in r1
    1449     if JSVALUE64
    1450         move r1, sp
    1451     else
    1452         # The calleeFrame is not stack aligned, move down by CallerFrameAndPCSize to align
    1453         if ARMv7
    1454             subp r1, CallerFrameAndPCSize, t2
    1455             move t2, sp
    1456         else
    1457             subp r1, CallerFrameAndPCSize, sp
    1458         end
    1459     end
    1460     slowPathForCall(_llint_slow_path_construct_varargs)
     1505    doCallVarargs(_llint_slow_path_construct_varargs, prepareForRegularCall)
    14611506
    14621507
     
    14971542    # returns the JS value that the eval returned.
    14981543   
    1499     slowPathForCall(_llint_slow_path_call_eval)
     1544    slowPathForCall(_llint_slow_path_call_eval, prepareForRegularCall)
    15001545
    15011546
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r189848 r189884  
    603603    loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[r1], t1
    604604    btiz t1, .continue
    605 
    606     // Move frame up "t1 * 2" slots
    607     lshiftp 1, t1
     605    loadi PayloadOffset + ArgumentCount[cfr], t2
     606    addi CallFrameHeaderSlots, t2
     607
     608    // Check if there are some unaligned slots we can use
     609    move t1, t3
     610    andi StackAlignmentSlots - 1, t3
     611    btiz t3, .noExtraSlot
     612.fillExtraSlots:
     613    move 0, t0
     614    storei t0, PayloadOffset[cfr, t2, 8]
     615    move UndefinedTag, t0
     616    storei t0, TagOffset[cfr, t2, 8]
     617    addi 1, t2
     618    bsubinz 1, t3, .fillExtraSlots
     619    andi ~(StackAlignmentSlots - 1), t1
     620    btiz t1, .continue
     621
     622.noExtraSlot:
     623    // Move frame up t1 slots
    608624    negi t1
    609625    move cfr, t3
    610     loadi PayloadOffset + ArgumentCount[cfr], t2
    611     addi CallFrameHeaderSlots, t2
    612626.copyLoop:
    613627    loadi PayloadOffset[t3], t0
     
    17651779end
    17661780
    1767 macro doCall(slowPath)
     1781macro doCall(slowPath, prepareCall)
    17681782    loadi 8[PC], t0
    17691783    loadi 20[PC], t1
     
    17801794    storei t2, ArgumentCount + PayloadOffset[t3]
    17811795    storei CellTag, Callee + TagOffset[t3]
    1782     addp CallerFrameAndPCSize, t3
    1783     callTargetFunction(t1, t3)
     1796    move t3, sp
     1797    prepareCall(LLIntCallLinkInfo::machineCodeTarget[t1], t2, t3, t4)
     1798    callTargetFunction(LLIntCallLinkInfo::machineCodeTarget[t1])
    17841799
    17851800.opCallSlow:
    1786     slowPathForCall(slowPath)
    1787 end
    1788 
     1801    slowPathForCall(slowPath, prepareCall)
     1802end
    17891803
    17901804_llint_op_ret:
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r189848 r189884  
    511511    loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[r1], t1
    512512    btiz t1, .continue
    513 
    514     // Move frame up "t1 * 2" slots
    515     lshiftp 1, t1
     513    loadi PayloadOffset + ArgumentCount[cfr], t2
     514    addi CallFrameHeaderSlots, t2
     515
     516    // Check if there are some unaligned slots we can use
     517    move t1, t3
     518    andi StackAlignmentSlots - 1, t3
     519    btiz t3, .noExtraSlot
     520    move ValueUndefined, t0
     521.fillExtraSlots:
     522    storeq t0, [cfr, t2, 8]
     523    addi 1, t2
     524    bsubinz 1, t3, .fillExtraSlots
     525    andi ~(StackAlignmentSlots - 1), t1
     526    btiz t1, .continue
     527
     528.noExtraSlot:
     529    // Move frame up t1 slots
    516530    negq t1
    517531    move cfr, t3
    518532    subp CalleeSaveSpaceAsVirtualRegisters * 8, t3
    519     loadi PayloadOffset + ArgumentCount[cfr], t2
    520     addi CallFrameHeaderSlots + CalleeSaveSpaceAsVirtualRegisters, t2
     533    addi CalleeSaveSpaceAsVirtualRegisters, t2
    521534.copyLoop:
    522535    loadq [t3], t0
     
    16541667end
    16551668
    1656 macro doCall(slowPath)
     1669macro doCall(slowPath, prepareCall)
    16571670    loadisFromInstruction(2, t0)
    16581671    loadpFromInstruction(5, t1)
     
    16681681    storei PC, ArgumentCount + TagOffset[cfr]
    16691682    storei t2, ArgumentCount + PayloadOffset[t3]
    1670     addp CallerFrameAndPCSize, t3
    1671     callTargetFunction(t1, t3)
     1683    move t3, sp
     1684    prepareCall(LLIntCallLinkInfo::machineCodeTarget[t1], t2, t3, t4)
     1685    callTargetFunction(LLIntCallLinkInfo::machineCodeTarget[t1])
    16721686
    16731687.opCallSlow:
    1674     slowPathForCall(slowPath)
    1675 end
    1676 
     1688    slowPathForCall(slowPath, prepareCall)
     1689end
    16771690
    16781691_llint_op_ret:
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h

    r189848 r189884  
    6060   
    6161    ASSERT(argumentCountIncludingThis < newCodeBlock->numParameters());
    62     int missingArgumentCount = newCodeBlock->numParameters() - argumentCountIncludingThis;
    63     int neededStackSpace = missingArgumentCount + 1; // Allow space to save the original return PC.
    64     int paddedStackSpace = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), neededStackSpace);
    65 
    66     if (!stack->ensureCapacityFor(exec->registers() - paddedStackSpace))
     62    int frameSize = argumentCountIncludingThis + JSStack::CallFrameHeaderSize;
     63    int alignedFrameSizeForParameters = WTF::roundUpToMultipleOf(stackAlignmentRegisters(),
     64        newCodeBlock->numParameters() + JSStack::CallFrameHeaderSize);
     65    int paddedStackSpace = alignedFrameSizeForParameters - frameSize;
     66
     67    if (!stack->ensureCapacityFor(exec->registers() - paddedStackSpace % stackAlignmentRegisters()))
    6768        return -1;
    68     return paddedStackSpace / stackAlignmentRegisters();
     69    return paddedStackSpace;
    6970}
    7071
Note: See TracChangeset for help on using the changeset viewer.