Title: [172665] trunk/Source/_javascript_Core
Revision
172665
Author
msab...@apple.com
Date
2014-08-15 18:45:40 -0700 (Fri, 15 Aug 2014)

Log Message

Change callToJavaScript and callToNativeFunction so their callFrames match the native calling conventions
https://bugs.webkit.org/show_bug.cgi?id=131578

Reviewed by Geoffrey Garen.

Renamed callToJavaScript and callToNativeFunction to vmEntryToJavaScript and vmEntryToNative,
respectively.  Eliminated the sentinel frame and replaced it with the structure VMEntryRecord
that appears in the "locals" area of a VM entry stack frame.  Changed the order that
vmEntryToJavaScript and vmEntryToNative creates their stack frames to be native calling
convention compliant.  That is to save prior frame pointer, save callee save registers, then
allocate and populate the VMEntryRecord, and finally allocate a CallFrame for the JS function
that vmEntryToJavaScript will invoke.  The top most vm entry frame pointer is saved in
VM::topVMEntryFrame.  The vmEntry functions save prior contents of VM::topVMEntryFrame
along with the VM and VM::topCallFrame in the VMEntryRecord it places on the stack.  Starting
at VM::topCallFrame, the stack can be walked using these VMEntryRecords.

Arbitrary stack unwinding is now handled either iteratively by loading VM::topVMEntryFrame
into a local variable and using CallFrame::callerFrame(VMEntryFrame*&) or by using StackVisitor.
Given that the stack is effectively a singly linked list, general stack unwinding needs to use
one of these two methods.

* _javascript_Core.vcxproj/_javascript_Core.vcxproj:
* _javascript_Core.vcxproj/_javascript_Core.vcxproj.filters:
* _javascript_Core.xcodeproj/project.pbxproj:
Addition of VMEntryRecord.h

* bytecode/BytecodeList.json:
Renaming of llint helper opcodes due to renaming callToJavaScript and callToNativeFunction.

* debugger/Debugger.cpp:
(JSC::Debugger::stepOutOfFunction):
(JSC::Debugger::returnEvent):
(JSC::Debugger::didExecuteProgram):
* jsc.cpp:
(functionDumpCallFrame):
* jit/JITOperations.cpp:
Changed unwinding to use CallFrame::callerFrame(VMEntryFrame*&).

* bytecode/CodeBlock.cpp:
(JSC::RecursionCheckFunctor::RecursionCheckFunctor):
(JSC::RecursionCheckFunctor::operator()):
(JSC::RecursionCheckFunctor::didRecurse):
(JSC::CodeBlock::noticeIncomingCall):
* debugger/DebuggerCallFrame.cpp:
(JSC::FindCallerMidStackFunctor::FindCallerMidStackFunctor):
(JSC::FindCallerMidStackFunctor::operator()):
(JSC::FindCallerMidStackFunctor::getCallerFrame):
(JSC::DebuggerCallFrame::callerFrame):
* interpreter/VMInspector.cpp:
(JSC::CountFramesFunctor::CountFramesFunctor):
(JSC::CountFramesFunctor::operator()):
(JSC::CountFramesFunctor::count):
(JSC::VMInspector::countFrames):
* runtime/VM.cpp:
(JSC::VM::VM):
(JSC::FindFirstCallerFrameWithCodeblockFunctor::FindFirstCallerFrameWithCodeblockFunctor):
(JSC::FindFirstCallerFrameWithCodeblockFunctor::operator()):
(JSC::FindFirstCallerFrameWithCodeblockFunctor::foundCallFrame):
(JSC::FindFirstCallerFrameWithCodeblockFunctor::index):
(JSC::VM::throwException):
Changed unwinding to use StackVisitor including added functor classes.

* interpreter/CallFrame.cpp:
(JSC::CallFrame::callerFrame):
Added new flavor of callerFrame() that can iteratively unwind the stack.

* interpreter/CallFrame.h:
(JSC::ExecState::callerFrame): Changed callerFrame() to use private common helper.
(JSC::ExecState::callerFrameOrVMEntryFrame): Deleted.
(JSC::ExecState::isVMEntrySentinel): Deleted.
(JSC::ExecState::vmEntrySentinelCallerFrame): Deleted.
(JSC::ExecState::initializeVMEntrySentinelFrame): Deleted.
(JSC::ExecState::callerFrameSkippingVMEntrySentinel): Deleted.
(JSC::ExecState::vmEntrySentinelCodeBlock): Deleted.

* interpreter/CallFrame.h:
(JSC::ExecState::init):
(JSC::ExecState::topOfFrame):
(JSC::ExecState::currentVPC):
(JSC::ExecState::setCurrentVPC):
Eliminated unneded checking of sentinel frame.

* interpreter/Interpreter.cpp:
(JSC::unwindCallFrame):
(JSC::Interpreter::getStackTrace): Updated for unwidning changes.
(JSC::Interpreter::unwind): Eliminated unneeded sentinel frame check.

* interpreter/Interpreter.cpp:
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
* jit/JITStubs.h:
* llint/LLIntThunks.cpp:
(JSC::callToJavaScript): Deleted.
(JSC::callToNativetion): Deleted.
(JSC::vmEntryToJavaScript):
(JSC::vmEntryToNative):
* llint/LLIntThunks.h:
Updated for vmEntryToJavaScript and vmEntryToNative name changes.

* interpreter/Interpreter.h:
(JSC::TopCallFrameSetter::TopCallFrameSetter):
(JSC::TopCallFrameSetter::~TopCallFrameSetter):
Eliminated unneeded sentinel frame check.

* interpreter/Interpreter.h:
(JSC::NativeCallFrameTracer::NativeCallFrameTracer):
Removed sentinel specific constructor.

* interpreter/StackVisitor.cpp:
(JSC::StackVisitor::StackVisitor):
(JSC::StackVisitor::readFrame):
(JSC::StackVisitor::readNonInlinedFrame):
(JSC::StackVisitor::readInlinedFrame):
(JSC::StackVisitor::Frame::print):
* interpreter/StackVisitor.h:
(JSC::StackVisitor::Frame::callerIsVMEntry):
Changes for unwinding using CallFrame::callerFrame(VMEntryFrame*&).  Also added field that
indicates when about to step over a VM entry frame.

* interpreter/VMEntryRecord.h: Added.
(JSC::VMEntryRecord::prevTopCallFrame):
(JSC::VMEntryRecord::prevTopVMEntryFrame):
New struct to record prior state of VM's notion of VM entry and top call frames.

* jit/JITCode.cpp:
(JSC::JITCode::execute):
Use new vmEntryToJavaScript and vmEntryToNative name.

* llint/LLIntOffsetsExtractor.cpp: Added include for VMEntryRecord.h.

* llint/LowLevelInterpreter.asm:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
Offline assembly implementation of creating stack frame with VMEntryRecord and well as restoring 
relevent VM fields when exiting the VM.  Added a helper that returns a VMEntryRecord given
a pointer to the VM entry frame.

* llint/LLIntThunks.cpp:
(JSC::vmEntryRecord):
* llint/LowLevelInterpreter.cpp:
(JSC::CLoop::execute):
C Loop changes to mirror the assembly changes.

* runtime/VM.h:
Added topVMEntryFrame field.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (172664 => 172665)


--- trunk/Source/_javascript_Core/ChangeLog	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/ChangeLog	2014-08-16 01:45:40 UTC (rev 172665)
@@ -1,3 +1,151 @@
+2014-08-15  Michael Saboff  <msab...@apple.com>
+
+        Change callToJavaScript and callToNativeFunction so their callFrames match the native calling conventions
+        https://bugs.webkit.org/show_bug.cgi?id=131578
+
+        Reviewed by Geoffrey Garen.
+
+        Renamed callToJavaScript and callToNativeFunction to vmEntryToJavaScript and vmEntryToNative,
+        respectively.  Eliminated the sentinel frame and replaced it with the structure VMEntryRecord
+        that appears in the "locals" area of a VM entry stack frame.  Changed the order that
+        vmEntryToJavaScript and vmEntryToNative creates their stack frames to be native calling
+        convention compliant.  That is to save prior frame pointer, save callee save registers, then
+        allocate and populate the VMEntryRecord, and finally allocate a CallFrame for the JS function
+        that vmEntryToJavaScript will invoke.  The top most vm entry frame pointer is saved in
+        VM::topVMEntryFrame.  The vmEntry functions save prior contents of VM::topVMEntryFrame
+        along with the VM and VM::topCallFrame in the VMEntryRecord it places on the stack.  Starting
+        at VM::topCallFrame, the stack can be walked using these VMEntryRecords.
+
+        Arbitrary stack unwinding is now handled either iteratively by loading VM::topVMEntryFrame
+        into a local variable and using CallFrame::callerFrame(VMEntryFrame*&) or by using StackVisitor.
+        Given that the stack is effectively a singly linked list, general stack unwinding needs to use
+        one of these two methods.
+
+        * _javascript_Core.vcxproj/_javascript_Core.vcxproj:
+        * _javascript_Core.vcxproj/_javascript_Core.vcxproj.filters:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        Addition of VMEntryRecord.h
+
+        * bytecode/BytecodeList.json:
+        Renaming of llint helper opcodes due to renaming callToJavaScript and callToNativeFunction.
+
+        * debugger/Debugger.cpp:
+        (JSC::Debugger::stepOutOfFunction):
+        (JSC::Debugger::returnEvent):
+        (JSC::Debugger::didExecuteProgram):
+        * jsc.cpp:
+        (functionDumpCallFrame):
+        * jit/JITOperations.cpp:
+        Changed unwinding to use CallFrame::callerFrame(VMEntryFrame*&).
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::RecursionCheckFunctor::RecursionCheckFunctor):
+        (JSC::RecursionCheckFunctor::operator()):
+        (JSC::RecursionCheckFunctor::didRecurse):
+        (JSC::CodeBlock::noticeIncomingCall):
+        * debugger/DebuggerCallFrame.cpp:
+        (JSC::FindCallerMidStackFunctor::FindCallerMidStackFunctor):
+        (JSC::FindCallerMidStackFunctor::operator()):
+        (JSC::FindCallerMidStackFunctor::getCallerFrame):
+        (JSC::DebuggerCallFrame::callerFrame):
+        * interpreter/VMInspector.cpp:
+        (JSC::CountFramesFunctor::CountFramesFunctor):
+        (JSC::CountFramesFunctor::operator()):
+        (JSC::CountFramesFunctor::count):
+        (JSC::VMInspector::countFrames):
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        (JSC::FindFirstCallerFrameWithCodeblockFunctor::FindFirstCallerFrameWithCodeblockFunctor):
+        (JSC::FindFirstCallerFrameWithCodeblockFunctor::operator()):
+        (JSC::FindFirstCallerFrameWithCodeblockFunctor::foundCallFrame):
+        (JSC::FindFirstCallerFrameWithCodeblockFunctor::index):
+        (JSC::VM::throwException):
+        Changed unwinding to use StackVisitor including added functor classes.
+
+        * interpreter/CallFrame.cpp:
+        (JSC::CallFrame::callerFrame):
+        Added new flavor of callerFrame() that can iteratively unwind the stack.
+
+        * interpreter/CallFrame.h:
+        (JSC::ExecState::callerFrame): Changed callerFrame() to use private common helper.
+        (JSC::ExecState::callerFrameOrVMEntryFrame): Deleted.
+        (JSC::ExecState::isVMEntrySentinel): Deleted.
+        (JSC::ExecState::vmEntrySentinelCallerFrame): Deleted.
+        (JSC::ExecState::initializeVMEntrySentinelFrame): Deleted.
+        (JSC::ExecState::callerFrameSkippingVMEntrySentinel): Deleted.
+        (JSC::ExecState::vmEntrySentinelCodeBlock): Deleted.
+
+        * interpreter/CallFrame.h:
+        (JSC::ExecState::init):
+        (JSC::ExecState::topOfFrame):
+        (JSC::ExecState::currentVPC):
+        (JSC::ExecState::setCurrentVPC):
+        Eliminated unneded checking of sentinel frame.
+
+        * interpreter/Interpreter.cpp:
+        (JSC::unwindCallFrame):
+        (JSC::Interpreter::getStackTrace): Updated for unwidning changes.
+        (JSC::Interpreter::unwind): Eliminated unneeded sentinel frame check.
+
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::executeCall):
+        (JSC::Interpreter::executeConstruct):
+        * jit/JITStubs.h:
+        * llint/LLIntThunks.cpp:
+        (JSC::callToJavaScript): Deleted.
+        (JSC::callToNativetion): Deleted.
+        (JSC::vmEntryToJavaScript):
+        (JSC::vmEntryToNative):
+        * llint/LLIntThunks.h:
+        Updated for vmEntryToJavaScript and vmEntryToNative name changes.
+
+        * interpreter/Interpreter.h:
+        (JSC::TopCallFrameSetter::TopCallFrameSetter):
+        (JSC::TopCallFrameSetter::~TopCallFrameSetter):
+        Eliminated unneeded sentinel frame check.
+
+        * interpreter/Interpreter.h:
+        (JSC::NativeCallFrameTracer::NativeCallFrameTracer):
+        Removed sentinel specific constructor.
+
+        * interpreter/StackVisitor.cpp:
+        (JSC::StackVisitor::StackVisitor):
+        (JSC::StackVisitor::readFrame):
+        (JSC::StackVisitor::readNonInlinedFrame):
+        (JSC::StackVisitor::readInlinedFrame):
+        (JSC::StackVisitor::Frame::print):
+        * interpreter/StackVisitor.h:
+        (JSC::StackVisitor::Frame::callerIsVMEntry):
+        Changes for unwinding using CallFrame::callerFrame(VMEntryFrame*&).  Also added field that
+        indicates when about to step over a VM entry frame.
+
+        * interpreter/VMEntryRecord.h: Added.
+        (JSC::VMEntryRecord::prevTopCallFrame):
+        (JSC::VMEntryRecord::prevTopVMEntryFrame):
+        New struct to record prior state of VM's notion of VM entry and top call frames.
+
+        * jit/JITCode.cpp:
+        (JSC::JITCode::execute):
+        Use new vmEntryToJavaScript and vmEntryToNative name.
+
+        * llint/LLIntOffsetsExtractor.cpp: Added include for VMEntryRecord.h.
+
+        * llint/LowLevelInterpreter.asm:
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        Offline assembly implementation of creating stack frame with VMEntryRecord and well as restoring 
+        relevent VM fields when exiting the VM.  Added a helper that returns a VMEntryRecord given
+        a pointer to the VM entry frame.
+
+        * llint/LLIntThunks.cpp:
+        (JSC::vmEntryRecord):
+        * llint/LowLevelInterpreter.cpp:
+        (JSC::CLoop::execute):
+        C Loop changes to mirror the assembly changes.
+
+        * runtime/VM.h:
+        Added topVMEntryFrame field.
+
 2014-08-15  Brian J. Burg  <b...@cs.washington.edu>
 
         Web Inspector: rewrite CodeGeneratorInspector to be modular and testable

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj (172664 => 172665)


--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj	2014-08-16 01:45:40 UTC (rev 172665)
@@ -1271,6 +1271,7 @@
     <ClInclude Include="..\interpreter\CallFrame.h" />
     <ClInclude Include="..\interpreter\CallFrameInlines.h" />
     <ClInclude Include="..\interpreter\CallFrameClosure.h" />
+    <ClInclude Include="..\interpreter\VMEntryRecord.h" />
     <ClInclude Include="..\interpreter\Interpreter.h" />
     <ClInclude Include="..\interpreter\JSStack.h" />
     <ClInclude Include="..\interpreter\JSStackInlines.h" />
@@ -1701,4 +1702,4 @@
   <ImportGroup Label="ExtensionTargets">
     <Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
   </ImportGroup>
-</Project>
\ No newline at end of file
+</Project>

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters (172664 => 172665)


--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters	2014-08-16 01:45:40 UTC (rev 172665)
@@ -2213,6 +2213,9 @@
     <ClInclude Include="..\interpreter\CallFrameClosure.h">
       <Filter>interpreter</Filter>
     </ClInclude>
+    <ClInclude Include="..\interpreter\VMEntryRecord.h">
+      <Filter>interpreter</Filter>
+    </ClInclude>
     <ClInclude Include="..\interpreter\Interpreter.h">
       <Filter>interpreter</Filter>
     </ClInclude>
@@ -4227,4 +4230,4 @@
       <Filter>jit</Filter>
     </MASM>
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (172664 => 172665)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2014-08-16 01:45:40 UTC (rev 172665)
@@ -1156,6 +1156,7 @@
 		6553A33117A1F1EE008CF6F3 /* CommonSlowPathsExceptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6553A32F17A1F1EE008CF6F3 /* CommonSlowPathsExceptions.cpp */; };
 		6553A33217A1F1EE008CF6F3 /* CommonSlowPathsExceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 6553A33017A1F1EE008CF6F3 /* CommonSlowPathsExceptions.h */; };
 		655EB29B10CE2581001A990E /* NodesCodegen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 655EB29A10CE2581001A990E /* NodesCodegen.cpp */; };
+		658D3A5619638268003C45D6 /* VMEntryRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 658D3A5519638268003C45D6 /* VMEntryRecord.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		65C02850171795E200351E35 /* ARMv7Disassembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65C0284F171795E200351E35 /* ARMv7Disassembler.cpp */; };
 		65C0285C1717966800351E35 /* ARMv7DOpcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65C0285A1717966800351E35 /* ARMv7DOpcode.cpp */; };
 		65C0285D1717966800351E35 /* ARMv7DOpcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 65C0285B1717966800351E35 /* ARMv7DOpcode.h */; };
@@ -2885,7 +2886,7 @@
 		1429D8830ED21C3D00B89619 /* SamplingTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SamplingTool.cpp; sourceTree = "<group>"; };
 		1429D8840ED21C3D00B89619 /* SamplingTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SamplingTool.h; sourceTree = "<group>"; };
 		1429D8DB0ED2205B00B89619 /* CallFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallFrame.cpp; sourceTree = "<group>"; };
-		1429D8DC0ED2205B00B89619 /* CallFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallFrame.h; sourceTree = "<group>"; };
+		1429D8DC0ED2205B00B89619 /* CallFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = CallFrame.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
 		1429D92D0ED22D7000B89619 /* JIT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JIT.cpp; sourceTree = "<group>"; };
 		1429D92E0ED22D7000B89619 /* JIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JIT.h; sourceTree = "<group>"; };
 		142D3938103E4560007DCB52 /* NumericStrings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NumericStrings.h; sourceTree = "<group>"; };
@@ -3071,6 +3072,7 @@
 		65621E6B089E859700760F35 /* PropertySlot.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PropertySlot.cpp; sourceTree = "<group>"; tabWidth = 8; };
 		65621E6C089E859700760F35 /* PropertySlot.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = PropertySlot.h; sourceTree = "<group>"; tabWidth = 8; };
 		65860177185A8F5E00030EEE /* MaxFrameExtentForSlowPathCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MaxFrameExtentForSlowPathCall.h; sourceTree = "<group>"; };
+		658D3A5519638268003C45D6 /* VMEntryRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = VMEntryRecord.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
 		65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSRExitCompilationInfo.h; path = dfg/DFGOSRExitCompilationInfo.h; sourceTree = "<group>"; };
 		65987F2F16828A7E003C2F8D /* UnusedPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnusedPointer.h; sourceTree = "<group>"; };
 		65C0284F171795E200351E35 /* ARMv7Disassembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ARMv7Disassembler.cpp; path = disassembler/ARMv7Disassembler.cpp; sourceTree = "<group>"; };
@@ -3113,7 +3115,7 @@
 		860161E20F3A83C100F84710 /* MacroAssemblerX86Common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerX86Common.h; sourceTree = "<group>"; };
 		8603CEF214C7546400AE59E3 /* CodeProfiling.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeProfiling.cpp; sourceTree = "<group>"; };
 		8603CEF314C7546400AE59E3 /* CodeProfiling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeProfiling.h; sourceTree = "<group>"; };
-		8604F4F2143A6C4400B295F5 /* ChangeLog */ = {isa = PBXFileReference; lastKnownFileType = text; path = ChangeLog; sourceTree = "<group>"; };
+		8604F4F2143A6C4400B295F5 /* ChangeLog */ = {isa = PBXFileReference; lastKnownFileType = text; lineEnding = 0; path = ChangeLog; sourceTree = "<group>"; };
 		8606DDE918DA44AB00A383D0 /* IdentifierInlines..h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IdentifierInlines.h; sourceTree = "<group>"; };
 		8612E4CB1522918400C836BE /* MatchResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MatchResult.h; sourceTree = "<group>"; };
 		86158AB2155C8B3F00B45C9C /* PropertyName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PropertyName.h; sourceTree = "<group>"; };
@@ -3142,8 +3144,8 @@
 		868916A9155F285400CB2B9A /* PrivateName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrivateName.h; sourceTree = "<group>"; };
 		869EBCB60E8C6D4A008722CC /* ResultType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResultType.h; sourceTree = "<group>"; };
 		86A054461556451B00445157 /* LowLevelInterpreter.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; name = LowLevelInterpreter.asm; path = llint/LowLevelInterpreter.asm; sourceTree = "<group>"; };
-		86A054471556451B00445157 /* LowLevelInterpreter32_64.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; name = LowLevelInterpreter32_64.asm; path = llint/LowLevelInterpreter32_64.asm; sourceTree = "<group>"; };
-		86A054481556451B00445157 /* LowLevelInterpreter64.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; name = LowLevelInterpreter64.asm; path = llint/LowLevelInterpreter64.asm; sourceTree = "<group>"; };
+		86A054471556451B00445157 /* LowLevelInterpreter32_64.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; lineEnding = 0; name = LowLevelInterpreter32_64.asm; path = llint/LowLevelInterpreter32_64.asm; sourceTree = "<group>"; };
+		86A054481556451B00445157 /* LowLevelInterpreter64.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; lineEnding = 0; name = LowLevelInterpreter64.asm; path = llint/LowLevelInterpreter64.asm; sourceTree = "<group>"; };
 		86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITArithmetic.cpp; sourceTree = "<group>"; };
 		86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMv7Assembler.h; sourceTree = "<group>"; };
 		86ADD1440FDDEA980006EEC2 /* MacroAssemblerARMv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerARMv7.h; sourceTree = "<group>"; };
@@ -3532,7 +3534,7 @@
 		A7C1E8C8112E701C00A37F98 /* JITPropertyAccess32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITPropertyAccess32_64.cpp; sourceTree = "<group>"; };
 		A7C1EAEA17987AB600299DB2 /* CallFrameInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallFrameInlines.h; sourceTree = "<group>"; };
 		A7C1EAEB17987AB600299DB2 /* JSStackInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStackInlines.h; sourceTree = "<group>"; };
-		A7C1EAEC17987AB600299DB2 /* StackVisitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StackVisitor.cpp; sourceTree = "<group>"; };
+		A7C1EAEC17987AB600299DB2 /* StackVisitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = StackVisitor.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
 		A7C1EAED17987AB600299DB2 /* StackVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StackVisitor.h; sourceTree = "<group>"; };
 		A7C225CC139981F100FF1662 /* KeywordLookupGenerator.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = KeywordLookupGenerator.py; sourceTree = "<group>"; };
 		A7C225CD1399849C00FF1662 /* KeywordLookup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeywordLookup.h; sourceTree = "<group>"; };
@@ -3754,8 +3756,8 @@
 		E124A8F60E555775003091F1 /* OpaqueJSString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpaqueJSString.cpp; sourceTree = "<group>"; };
 		E178633F0D9BEC0000D74E75 /* InitializeThreading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InitializeThreading.h; sourceTree = "<group>"; };
 		E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InitializeThreading.cpp; sourceTree = "<group>"; };
-		E18E3A560DF9278C00D90B34 /* VM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VM.h; sourceTree = "<group>"; };
-		E18E3A570DF9278C00D90B34 /* VM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VM.cpp; sourceTree = "<group>"; };
+		E18E3A560DF9278C00D90B34 /* VM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = VM.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
+		E18E3A570DF9278C00D90B34 /* VM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = VM.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
 		E49DC14912EF261A00184A1F /* SourceProviderCacheItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SourceProviderCacheItem.h; sourceTree = "<group>"; };
 		E49DC15112EF272200184A1F /* SourceProviderCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SourceProviderCache.h; sourceTree = "<group>"; };
 		E49DC15512EF277200184A1F /* SourceProviderCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SourceProviderCache.cpp; sourceTree = "<group>"; };
@@ -4175,6 +4177,7 @@
 		1429D77A0ED20D7300B89619 /* interpreter */ = {
 			isa = PBXGroup;
 			children = (
+				658D3A5519638268003C45D6 /* VMEntryRecord.h */,
 				0F55F0F114D1063600AC7649 /* AbstractPC.cpp */,
 				0F55F0F214D1063600AC7649 /* AbstractPC.h */,
 				A7F8690E0F9584A100558697 /* CachedCall.h */,
@@ -6017,6 +6020,7 @@
 				0F6B1CB91861244C00845D97 /* ArityCheckMode.h in Headers */,
 				A1A009C11831A26E00CF8711 /* ARM64Assembler.h in Headers */,
 				86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */,
+				658D3A5619638268003C45D6 /* VMEntryRecord.h in Headers */,
 				2AD2EDFB19799E38004D6478 /* EnumerationMode.h in Headers */,
 				147B83AC0E6DB8C9004775A4 /* BatchedTransitionOptimizer.h in Headers */,
 				2A111246192FCE79005EE18D /* CustomGetterSetter.h in Headers */,

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.json (172664 => 172665)


--- trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2014-08-16 01:45:40 UTC (rev 172665)
@@ -139,8 +139,8 @@
             { "name" : "llint_entry" },
             { "name" : "getHostCallReturnValue" },
             { "name" : "llint_return_to_host" },
-            { "name" : "llint_call_to_javascript" },
-            { "name" : "llint_call_to_native_function" },
+            { "name" : "llint_vm_entry_to_javascript" },
+            { "name" : "llint_vm_entry_to_native" },
             { "name" : "llint_cloop_did_return_from_js_1" },
             { "name" : "llint_cloop_did_return_from_js_2" },
             { "name" : "llint_cloop_did_return_from_js_3" },

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (172664 => 172665)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2014-08-16 01:45:40 UTC (rev 172665)
@@ -59,6 +59,7 @@
 #include "Repatch.h"
 #include "RepatchBuffer.h"
 #include "SlotVisitorInlines.h"
+#include "StackVisitor.h"
 #include "UnlinkedInstructionStream.h"
 #include <wtf/BagToHashMap.h>
 #include <wtf/CommaPrinter.h>
@@ -3159,6 +3160,46 @@
     return jsCast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())->eitherCodeBlock()->globalObject();
 }
 
+class RecursionCheckFunctor {
+public:
+    RecursionCheckFunctor(CallFrame* startCallFrame, CodeBlock* codeBlock, unsigned depthToCheck)
+        : m_startCallFrame(startCallFrame)
+        , m_codeBlock(codeBlock)
+        , m_depthToCheck(depthToCheck)
+        , m_foundStartCallFrame(false)
+        , m_didRecurse(false)
+    { }
+
+    StackVisitor::Status operator()(StackVisitor& visitor)
+    {
+        CallFrame* currentCallFrame = visitor->callFrame();
+
+        if (currentCallFrame == m_startCallFrame)
+            m_foundStartCallFrame = true;
+
+        if (m_foundStartCallFrame) {
+            if (visitor->callFrame()->codeBlock() == m_codeBlock) {
+                m_didRecurse = true;
+                return StackVisitor::Done;
+            }
+
+            if (!m_depthToCheck--)
+                return StackVisitor::Done;
+        }
+
+        return StackVisitor::Continue;
+    }
+
+    bool didRecurse() const { return m_didRecurse; }
+
+private:
+    CallFrame* m_startCallFrame;
+    CodeBlock* m_codeBlock;
+    unsigned m_depthToCheck;
+    bool m_foundStartCallFrame;
+    bool m_didRecurse;
+};
+
 void CodeBlock::noticeIncomingCall(ExecState* callerFrame)
 {
     CodeBlock* callerCodeBlock = callerFrame->codeBlock();
@@ -3206,20 +3247,18 @@
             dataLog("    Clearing SABI because caller is not a function.\n");
         return;
     }
-    
-    ExecState* frame = callerFrame;
-    for (unsigned i = Options::maximumInliningDepth(); i--; frame = frame->callerFrame()) {
-        if (frame->isVMEntrySentinel())
-            break;
-        if (frame->codeBlock() == this) {
-            // Recursive calls won't be inlined.
-            if (Options::verboseCallLink())
-                dataLog("    Clearing SABI because recursion was detected.\n");
-            m_shouldAlwaysBeInlined = false;
-            return;
-        }
+
+    // Recursive calls won't be inlined.
+    RecursionCheckFunctor functor(callerFrame, this, Options::maximumInliningDepth());
+    vm()->topCallFrame->iterate(functor);
+
+    if (functor.didRecurse()) {
+        if (Options::verboseCallLink())
+            dataLog("    Clearing SABI because recursion was detected.\n");
+        m_shouldAlwaysBeInlined = false;
+        return;
     }
-    
+
     RELEASE_ASSERT(callerCodeBlock->m_capabilityLevelState != DFG::CapabilityLevelNotSet);
     
     if (canCompile(callerCodeBlock->m_capabilityLevelState))

Modified: trunk/Source/_javascript_Core/debugger/Debugger.cpp (172664 => 172665)


--- trunk/Source/_javascript_Core/debugger/Debugger.cpp	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/debugger/Debugger.cpp	2014-08-16 01:45:40 UTC (rev 172665)
@@ -607,7 +607,8 @@
     if (!m_isPaused)
         return;
 
-    m_pauseOnCallFrame = m_currentCallFrame ? m_currentCallFrame->callerFrameSkippingVMEntrySentinel() : 0;
+    VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame;
+    m_pauseOnCallFrame = m_currentCallFrame ? m_currentCallFrame->callerFrame(topVMEntryFrame) : 0;
     notifyDoneProcessingDebuggerEvents();
 }
 
@@ -723,10 +724,13 @@
         return;
 
     // Treat stepping over a return statement like stepping out.
-    if (m_currentCallFrame == m_pauseOnCallFrame)
-        m_pauseOnCallFrame = m_currentCallFrame->callerFrameSkippingVMEntrySentinel();
+    if (m_currentCallFrame == m_pauseOnCallFrame) {
+        VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame;
+        m_pauseOnCallFrame = m_currentCallFrame->callerFrame(topVMEntryFrame);
+    }
 
-    m_currentCallFrame = m_currentCallFrame->callerFrameSkippingVMEntrySentinel();
+    VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame;
+    m_currentCallFrame = m_currentCallFrame->callerFrame(topVMEntryFrame);
 }
 
 void Debugger::willExecuteProgram(CallFrame* callFrame)
@@ -756,11 +760,13 @@
     if (!m_currentCallFrame)
         return;
     if (m_currentCallFrame == m_pauseOnCallFrame) {
-        m_pauseOnCallFrame = m_currentCallFrame->callerFrameSkippingVMEntrySentinel();
+        VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame;
+        m_pauseOnCallFrame = m_currentCallFrame->callerFrame(topVMEntryFrame);
         if (!m_currentCallFrame)
             return;
     }
-    m_currentCallFrame = m_currentCallFrame->callerFrameSkippingVMEntrySentinel();
+    VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame;
+    m_currentCallFrame = m_currentCallFrame->callerFrame(topVMEntryFrame);
 }
 
 void Debugger::didReachBreakpoint(CallFrame* callFrame)

Modified: trunk/Source/_javascript_Core/debugger/DebuggerCallFrame.cpp (172664 => 172665)


--- trunk/Source/_javascript_Core/debugger/DebuggerCallFrame.cpp	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/debugger/DebuggerCallFrame.cpp	2014-08-16 01:45:40 UTC (rev 172665)
@@ -55,6 +55,29 @@
     unsigned m_column;
 };
 
+class FindCallerMidStackFunctor {
+public:
+    FindCallerMidStackFunctor(CallFrame* callFrame)
+        : m_callFrame(callFrame)
+        , m_callerFrame(nullptr)
+    { }
+
+    StackVisitor::Status operator()(StackVisitor& visitor)
+    {
+        if (visitor->callFrame() == m_callFrame) {
+            m_callerFrame = visitor->callerFrame();
+            return StackVisitor::Done;
+        }
+        return StackVisitor::Continue;
+    }
+
+    CallFrame* getCallerFrame() const { return m_callerFrame; }
+
+private:
+    CallFrame* m_callFrame;
+    CallFrame* m_callerFrame;
+};
+
 DebuggerCallFrame::DebuggerCallFrame(CallFrame* callFrame)
     : m_callFrame(callFrame)
 {
@@ -70,7 +93,10 @@
     if (m_caller)
         return m_caller;
 
-    CallFrame* callerFrame = m_callFrame->callerFrameSkippingVMEntrySentinel();
+    FindCallerMidStackFunctor functor(m_callFrame);
+    m_callFrame->vm().topCallFrame->iterate(functor);
+
+    CallFrame* callerFrame = functor.getCallerFrame();
     if (!callerFrame)
         return 0;
 

Modified: trunk/Source/_javascript_Core/interpreter/CallFrame.cpp (172664 => 172665)


--- trunk/Source/_javascript_Core/interpreter/CallFrame.cpp	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/interpreter/CallFrame.cpp	2014-08-16 01:45:40 UTC (rev 172665)
@@ -136,6 +136,16 @@
     return vm().entryScope->globalObject();
 }
 
+CallFrame* CallFrame::callerFrame(VMEntryFrame*& currVMEntryFrame)
+{
+    if (callerFrameOrVMEntryFrame() == currVMEntryFrame) {
+        VMEntryRecord* currVMEntryRecord = vmEntryRecord(currVMEntryFrame);
+        currVMEntryFrame = currVMEntryRecord->prevTopVMEntryFrame();
+        return currVMEntryRecord->prevTopCallFrame();
+    }
+    return static_cast<CallFrame*>(callerFrameOrVMEntryFrame());
+}
+
 JSActivation* CallFrame::activation() const
 {
     CodeBlock* codeBlock = this->codeBlock();

Modified: trunk/Source/_javascript_Core/interpreter/CallFrame.h (172664 => 172665)


--- trunk/Source/_javascript_Core/interpreter/CallFrame.h	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/interpreter/CallFrame.h	2014-08-16 01:45:40 UTC (rev 172665)
@@ -29,6 +29,7 @@
 #include "MacroAssemblerCodeRef.h"
 #include "Register.h"
 #include "StackVisitor.h"
+#include "VMEntryRecord.h"
 
 namespace JSC  {
 
@@ -94,7 +95,10 @@
 
         CallFrame& operator=(const Register& r) { *static_cast<Register*>(this) = r; return *this; }
 
-        CallFrame* callerFrame() const { return callerFrameAndPC().callerFrame; }
+        CallFrame* callerFrame() const { return static_cast<CallFrame*>(callerFrameOrVMEntryFrame()); }
+
+        JS_EXPORT_PRIVATE CallFrame* callerFrame(VMEntryFrame*&);
+
         static ptrdiff_t callerFrameOffset() { return OBJECT_OFFSETOF(CallerFrameAndPC, callerFrame); }
 
         ReturnAddressPtr returnPC() const { return ReturnAddressPtr(callerFrameAndPC().pc); }
@@ -161,7 +165,7 @@
 
         Register* topOfFrame()
         {
-            if (isVMEntrySentinel() || !codeBlock())
+            if (!codeBlock())
                 return registers();
             return topOfFrameInternal();
         }
@@ -169,12 +173,10 @@
 #if USE(JSVALUE32_64)
         Instruction* currentVPC() const
         {
-            ASSERT(!isVMEntrySentinel());
             return bitwise_cast<Instruction*>(this[JSStack::ArgumentCount].tag());
         }
         void setCurrentVPC(Instruction* vpc)
         {
-            ASSERT(!isVMEntrySentinel());
             this[JSStack::ArgumentCount].tag() = bitwise_cast<int32_t>(vpc);
         }
 #else
@@ -189,7 +191,7 @@
         ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, JSScope* scope,
             CallFrame* callerFrame, int argc, JSObject* callee)
         {
-            ASSERT(callerFrame == noCaller() || callerFrame->isVMEntrySentinel() || callerFrame->stack()->containsAddress(this));
+            ASSERT(callerFrame == noCaller() || callerFrame->stack()->containsAddress(this));
 
             setCodeBlock(codeBlock);
             setScope(scope);
@@ -245,35 +247,6 @@
 
         static CallFrame* noCaller() { return 0; }
 
-        bool isVMEntrySentinel() const
-        {
-            return !!this && codeBlock() == vmEntrySentinelCodeBlock();
-        }
-
-        CallFrame* vmEntrySentinelCallerFrame() const
-        {
-            ASSERT(isVMEntrySentinel());
-            return this[JSStack::ScopeChain].callFrame();
-        }
-
-        void initializeVMEntrySentinelFrame(CallFrame* callFrame)
-        {
-            setCallerFrame(noCaller());
-            setReturnPC(0);
-            setCodeBlock(vmEntrySentinelCodeBlock());
-            static_cast<Register*>(this)[JSStack::ScopeChain] = callFrame;
-            setCallee(0);
-            setArgumentCountIncludingThis(0);
-        }
-
-        CallFrame* callerFrameSkippingVMEntrySentinel()
-        {
-            CallFrame* caller = callerFrame();
-            if (caller->isVMEntrySentinel())
-                return caller->vmEntrySentinelCallerFrame();
-            return caller;
-        }
-
         void setArgumentCountIncludingThis(int count) { static_cast<Register*>(this)[JSStack::ArgumentCount].payload() = count; }
         void setCallee(JSObject* callee) { static_cast<Register*>(this)[JSStack::Callee] = Register::withCallee(callee); }
         void setCodeBlock(CodeBlock* codeBlock) { static_cast<Register*>(this)[JSStack::CodeBlock] = codeBlock; }
@@ -291,7 +264,6 @@
         JS_EXPORT_PRIVATE const char* describeFrame();
 
     private:
-        static const intptr_t s_VMEntrySentinel = 1;
 
 #ifndef NDEBUG
         JSStack* stack();
@@ -330,11 +302,11 @@
             return this[argumentOffset(argIndex)].jsValue();
         }
 
+        void* callerFrameOrVMEntryFrame() const { return callerFrameAndPC().callerFrame; }
+
         CallerFrameAndPC& callerFrameAndPC() { return *reinterpret_cast<CallerFrameAndPC*>(this); }
         const CallerFrameAndPC& callerFrameAndPC() const { return *reinterpret_cast<const CallerFrameAndPC*>(this); }
 
-        static CodeBlock* vmEntrySentinelCodeBlock() { return reinterpret_cast<CodeBlock*>(s_VMEntrySentinel); }
-
         friend class JSStack;
         friend class VMInspector;
     };

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (172664 => 172665)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2014-08-16 01:45:40 UTC (rev 172665)
@@ -479,8 +479,7 @@
         }
     }
 
-    CallFrame* callerFrame = callFrame->callerFrame();
-    return !callerFrame->isVMEntrySentinel();
+    return !visitor->callerIsVMEntryFrame();
 }
 
 static StackFrameCodeType getStackFrameCodeType(StackVisitor& visitor)
@@ -597,7 +596,6 @@
 void Interpreter::getStackTrace(Vector<StackFrame>& results, size_t maxStackSize)
 {
     VM& vm = m_vm;
-    ASSERT(!vm.topCallFrame->isVMEntrySentinel());
     CallFrame* callFrame = vm.topCallFrame;
     if (!callFrame)
         return;
@@ -683,15 +681,6 @@
 
 NEVER_INLINE HandlerInfo* Interpreter::unwind(CallFrame*& callFrame, JSValue& exceptionValue)
 {
-    if (callFrame->isVMEntrySentinel()) {
-        // This happens when we throw stack overflow in a function that is called
-        // directly from callToJavaScript. Stack overflow throws the exception in the
-        // context of the caller. In that case the caller is the sentinel frame. The
-        // right thing to do is to pretend that the exception is uncaught so that we
-        // go to the uncaught exception handler, which returns through callToJavaScript.
-        return 0;
-    }
-    
     CodeBlock* codeBlock = callFrame->codeBlock();
     ASSERT(codeBlock);
     bool isTermination = false;
@@ -996,7 +985,7 @@
         if (isJSCall)
             result = callData.js.functionExecutable->generatedJITCodeForCall()->execute(&vm, &protoCallFrame);
         else {
-            result = JSValue::decode(callToNativeFunction(reinterpret_cast<void*>(callData.native.function), &vm, &protoCallFrame));
+            result = JSValue::decode(vmEntryToNative(reinterpret_cast<void*>(callData.native.function), &vm, &protoCallFrame));
             if (callFrame->hadException())
                 result = jsNull();
         }
@@ -1064,7 +1053,7 @@
         if (isJSConstruct)
             result = constructData.js.functionExecutable->generatedJITCodeForConstruct()->execute(&vm, &protoCallFrame);
         else {
-            result = JSValue::decode(callToNativeFunction(reinterpret_cast<void*>(constructData.native.function), &vm, &protoCallFrame));
+            result = JSValue::decode(vmEntryToNative(reinterpret_cast<void*>(constructData.native.function), &vm, &protoCallFrame));
 
             if (!callFrame->hadException())
                 RELEASE_ASSERT(result.isObject());

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.h (172664 => 172665)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.h	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.h	2014-08-16 01:45:40 UTC (rev 172665)
@@ -157,13 +157,11 @@
             : vm(currentVM)
             , oldCallFrame(currentVM.topCallFrame) 
         {
-            ASSERT(!callFrame->isVMEntrySentinel());
             currentVM.topCallFrame = callFrame;
         }
         
         ~TopCallFrameSetter() 
         {
-            ASSERT(!oldCallFrame->isVMEntrySentinel());
             vm.topCallFrame = oldCallFrame;
         }
     private:
@@ -177,18 +175,8 @@
         {
             ASSERT(vm);
             ASSERT(callFrame);
-            ASSERT(!callFrame->isVMEntrySentinel());
             vm->topCallFrame = callFrame;
         }
-        
-        enum VMEntrySentinelOKTag { VMEntrySentinelOK };
-        ALWAYS_INLINE NativeCallFrameTracer(VM* vm, CallFrame* callFrame, VMEntrySentinelOKTag)
-        {
-            ASSERT(vm);
-            ASSERT(callFrame);
-            if (!callFrame->isVMEntrySentinel())
-                vm->topCallFrame = callFrame;
-        }
     };
 
     class Interpreter {

Modified: trunk/Source/_javascript_Core/interpreter/StackVisitor.cpp (172664 => 172665)


--- trunk/Source/_javascript_Core/interpreter/StackVisitor.cpp	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/interpreter/StackVisitor.cpp	2014-08-16 01:45:40 UTC (rev 172665)
@@ -38,6 +38,11 @@
 StackVisitor::StackVisitor(CallFrame* startFrame)
 {
     m_frame.m_index = 0;
+    if (startFrame)
+        m_frame.m_VMEntryFrame = startFrame->vm().topVMEntryFrame;
+    else
+        m_frame.m_VMEntryFrame = 0;
+    m_frame.m_callerIsVMEntryFrame = false;
     readFrame(startFrame);
 }
 
@@ -56,7 +61,6 @@
 
 void StackVisitor::readFrame(CallFrame* callFrame)
 {
-    ASSERT(!callFrame->isVMEntrySentinel());
     if (!callFrame) {
         m_frame.setToEnd();
         return;
@@ -104,7 +108,9 @@
 {
     m_frame.m_callFrame = callFrame;
     m_frame.m_argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
-    m_frame.m_callerFrame = callFrame->callerFrameSkippingVMEntrySentinel();
+    VMEntryFrame* currentVMEntryFrame = m_frame.m_VMEntryFrame;
+    m_frame.m_callerFrame = callFrame->callerFrame(m_frame.m_VMEntryFrame);
+    m_frame.m_callerIsVMEntryFrame = currentVMEntryFrame != m_frame.m_VMEntryFrame;
     m_frame.m_callee = callFrame->callee();
     m_frame.m_scope = callFrame->scope();
     m_frame.m_codeBlock = callFrame->codeBlock();
@@ -127,7 +133,6 @@
 void StackVisitor::readInlinedFrame(CallFrame* callFrame, CodeOrigin* codeOrigin)
 {
     ASSERT(codeOrigin);
-    ASSERT(!callFrame->isVMEntrySentinel());
 
     int frameOffset = inlinedFrameOffset(codeOrigin);
     bool isInlined = !!frameOffset;
@@ -380,7 +385,6 @@
 
     printif(i, "   name '%s'\n", functionName().utf8().data());
     printif(i, "   sourceURL '%s'\n", sourceURL().utf8().data());
-    printif(i, "   isVMEntrySentinel %d\n", callerFrame->isVMEntrySentinel());
 
 #if ENABLE(DFG_JIT)
     printif(i, "   isInlinedFrame %d\n", isInlinedFrame());

Modified: trunk/Source/_javascript_Core/interpreter/StackVisitor.h (172664 => 172665)


--- trunk/Source/_javascript_Core/interpreter/StackVisitor.h	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/interpreter/StackVisitor.h	2014-08-16 01:45:40 UTC (rev 172665)
@@ -26,6 +26,7 @@
 #ifndef StackVisitor_h
 #define StackVisitor_h
 
+#include "VMEntryRecord.h"
 #include <wtf/text/WTFString.h>
 
 namespace JSC {
@@ -56,6 +57,7 @@
 
         size_t index() const { return m_index; }
         size_t argumentCountIncludingThis() const { return m_argumentCountIncludingThis; }
+        bool callerIsVMEntryFrame() const { return m_callerIsVMEntryFrame; }
         CallFrame* callerFrame() const { return m_callerFrame; }
         JSObject* callee() const { return m_callee; }
         JSScope* scope() const { return m_scope; }
@@ -94,11 +96,13 @@
 
         size_t m_index;
         size_t m_argumentCountIncludingThis;
+        VMEntryFrame* m_VMEntryFrame;
         CallFrame* m_callerFrame;
         JSObject* m_callee;
         JSScope* m_scope;
         CodeBlock* m_codeBlock;
         unsigned m_bytecodeOffset;
+        bool m_callerIsVMEntryFrame;
 #if ENABLE(DFG_JIT)
         InlineCallFrame* m_inlineCallFrame;
 #endif

Added: trunk/Source/_javascript_Core/interpreter/VMEntryRecord.h (0 => 172665)


--- trunk/Source/_javascript_Core/interpreter/VMEntryRecord.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/interpreter/VMEntryRecord.h	2014-08-16 01:45:40 UTC (rev 172665)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef VMEntryRecord_h
+#define VMEntryRecord_h
+
+namespace JSC {
+
+typedef void VMEntryFrame;
+
+class ExecState;
+class VM;
+
+struct VMEntryRecord {
+    /*
+     * This record stored in a vmEntryTo{_javascript_,Host} allocated frame. It is allocated on the stack
+     * after callee save registers where local variables would go.
+     */
+    VM* m_vm;
+    ExecState* m_prevTopCallFrame;
+    VMEntryFrame* m_prevTopVMEntryFrame;
+
+    ExecState* prevTopCallFrame() { return m_prevTopCallFrame; }
+
+    VMEntryFrame* prevTopVMEntryFrame() { return m_prevTopVMEntryFrame; }
+};
+
+extern "C" VMEntryRecord* vmEntryRecord(VMEntryFrame*);
+
+} // namespace JSC
+
+#endif // VMEntryRecord_h

Modified: trunk/Source/_javascript_Core/interpreter/VMInspector.cpp (172664 => 172665)


--- trunk/Source/_javascript_Core/interpreter/VMInspector.cpp	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/interpreter/VMInspector.cpp	2014-08-16 01:45:40 UTC (rev 172665)
@@ -29,6 +29,7 @@
 #if ENABLE(VMINSPECTOR)
 
 #include "JSCInlines.h"
+#include "StackVisitor.h"
 #include <wtf/ASCIICType.h>
 #include <wtf/text/WTFString.h>
 
@@ -99,14 +100,30 @@
     printf("\n");
 }
 
+class CountFramesFunctor {
+public:
+    CountFramesFunctor()
+        : m_count(-1)
+    { }
+
+    StackVisitor::Status operator()(StackVisitor& visitor)
+    {
+        m_count++;
+        return StackVisitor::Continue;
+    }
+
+    int count() const { return m_count; }
+
+private:
+    unsigned m_count;
+};
+
 int VMInspector::countFrames(CallFrame* frame)
 {
-    int count = -1;
-    while (frame && !frame->isVMEntrySentinel()) {
-        count++;
-        frame = frame->callerFrame();
-    }
-    return count;
+    CountFramesFunctor functor();
+    StackVisitor::visit(frame, functor);
+
+    return functor.count();
 }
 
 

Modified: trunk/Source/_javascript_Core/jit/JITCode.cpp (172664 => 172665)


--- trunk/Source/_javascript_Core/jit/JITCode.cpp	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/jit/JITCode.cpp	2014-08-16 01:45:40 UTC (rev 172665)
@@ -44,7 +44,7 @@
 
 JSValue JITCode::execute(VM* vm, ProtoCallFrame* protoCallFrame)
 {
-    JSValue result = JSValue::decode(callToJavaScript(executableAddress(), vm, protoCallFrame));
+    JSValue result = JSValue::decode(vmEntryToJavaScript(executableAddress(), vm, protoCallFrame));
     return vm->exception() ? jsNull() : result;
 }
 

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (172664 => 172665)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2014-08-16 01:45:40 UTC (rev 172665)
@@ -80,7 +80,9 @@
 {
     // We pass in our own code block, because the callframe hasn't been populated.
     VM* vm = codeBlock->vm();
-    CallFrame* callerFrame = exec->callerFrameSkippingVMEntrySentinel();
+
+    VMEntryFrame* topVMEntryFrame = vm->topVMEntryFrame;
+    CallFrame* callerFrame = exec->callerFrame(topVMEntryFrame);
     if (!callerFrame)
         callerFrame = exec;
 
@@ -92,7 +94,8 @@
 int32_t JIT_OPERATION operationCallArityCheck(ExecState* exec)
 {
     VM* vm = &exec->vm();
-    CallFrame* callerFrame = exec->callerFrameSkippingVMEntrySentinel();
+    VMEntryFrame* topVMEntryFrame = vm->topVMEntryFrame;
+    CallFrame* callerFrame = exec->callerFrame(topVMEntryFrame);
     NativeCallFrameTracer tracer(vm, callerFrame);
 
     JSStack& stack = vm->interpreter->stack();
@@ -107,7 +110,8 @@
 int32_t JIT_OPERATION operationConstructArityCheck(ExecState* exec)
 {
     VM* vm = &exec->vm();
-    CallFrame* callerFrame = exec->callerFrameSkippingVMEntrySentinel();
+    VMEntryFrame* topVMEntryFrame = vm->topVMEntryFrame;
+    CallFrame* callerFrame = exec->callerFrame(topVMEntryFrame);
     NativeCallFrameTracer tracer(vm, callerFrame);
 
     JSStack& stack = vm->interpreter->stack();
@@ -1823,7 +1827,7 @@
 
 void JIT_OPERATION lookupExceptionHandler(VM* vm, ExecState* exec)
 {
-    NativeCallFrameTracer tracer(vm, exec, NativeCallFrameTracer::VMEntrySentinelOK);
+    NativeCallFrameTracer tracer(vm, exec);
 
     JSValue exceptionValue = vm->exception();
     ASSERT(exceptionValue);
@@ -1837,7 +1841,6 @@
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
 
-    ASSERT(!exec->isVMEntrySentinel());
     genericUnwind(vm, exec, vm->exception());
 }
 

Modified: trunk/Source/_javascript_Core/jit/JITStubs.h (172664 => 172665)


--- trunk/Source/_javascript_Core/jit/JITStubs.h	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/jit/JITStubs.h	2014-08-16 01:45:40 UTC (rev 172665)
@@ -41,8 +41,8 @@
 class VM;
 
 extern "C" {
-    EncodedJSValue callToJavaScript(void*, VM*, ProtoCallFrame*);
-    EncodedJSValue callToNativeFunction(void*, VM*, ProtoCallFrame*);
+    EncodedJSValue vmEntryToJavaScript(void*, VM*, ProtoCallFrame*);
+    EncodedJSValue vmEntryToNative(void*, VM*, ProtoCallFrame*);
 }
 #endif
 

Modified: trunk/Source/_javascript_Core/jsc.cpp (172664 => 172665)


--- trunk/Source/_javascript_Core/jsc.cpp	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/jsc.cpp	2014-08-16 01:45:40 UTC (rev 172665)
@@ -687,8 +687,10 @@
 #ifndef NDEBUG
 EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec)
 {
-    if (!exec->callerFrame()->isVMEntrySentinel())
-        exec->vm().interpreter->dumpCallFrame(exec->callerFrame());
+    VMEntryFrame* topVMEntryFrame = exec->vm().topVMEntryFrame;
+    ExecState* callerFrame = exec->callerFrame(topVMEntryFrame);
+    if (callerFrame)
+        exec->vm().interpreter->dumpCallFrame(callerFrame);
     return JSValue::encode(jsUndefined());
 }
 #endif

Modified: trunk/Source/_javascript_Core/llint/LLIntOffsetsExtractor.cpp (172664 => 172665)


--- trunk/Source/_javascript_Core/llint/LLIntOffsetsExtractor.cpp	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/llint/LLIntOffsetsExtractor.cpp	2014-08-16 01:45:40 UTC (rev 172665)
@@ -49,6 +49,7 @@
 #include "ProtoCallFrame.h"
 #include "Structure.h"
 #include "StructureChain.h"
+#include "VMEntryRecord.h"
 #include "ValueProfile.h"
 #include <wtf/text/StringImpl.h>
 

Modified: trunk/Source/_javascript_Core/llint/LLIntThunks.cpp (172664 => 172665)


--- trunk/Source/_javascript_Core/llint/LLIntThunks.cpp	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/llint/LLIntThunks.cpp	2014-08-16 01:45:40 UTC (rev 172665)
@@ -37,6 +37,7 @@
 #include "LinkBuffer.h"
 #include "LowLevelInterpreter.h"
 #include "ProtoCallFrame.h"
+#include "StackAlignment.h"
 #include "VM.h"
 
 namespace JSC {
@@ -93,18 +94,27 @@
 
 // Non-JIT (i.e. C Loop LLINT) case:
 
-EncodedJSValue callToJavaScript(void* executableAddress, VM* vm, ProtoCallFrame* protoCallFrame)
+EncodedJSValue vmEntryToJavaScript(void* executableAddress, VM* vm, ProtoCallFrame* protoCallFrame)
 {
-    JSValue result = CLoop::execute(llint_call_to_javascript, executableAddress, vm, protoCallFrame);
+    JSValue result = CLoop::execute(llint_vm_entry_to_javascript, executableAddress, vm, protoCallFrame);
     return JSValue::encode(result);
 }
 
-EncodedJSValue callToNativeFunction(void* executableAddress, VM* vm, ProtoCallFrame* protoCallFrame)
+EncodedJSValue vmEntryToNative(void* executableAddress, VM* vm, ProtoCallFrame* protoCallFrame)
 {
-    JSValue result = CLoop::execute(llint_call_to_native_function, executableAddress, vm, protoCallFrame);
+    JSValue result = CLoop::execute(llint_vm_entry_to_native, executableAddress, vm, protoCallFrame);
     return JSValue::encode(result);
 }
 
+extern "C" VMEntryRecord* vmEntryRecord(VMEntryFrame* entryFrame)
+{
+    // The C Loop doesn't have any callee save registers, so the VMEntryRecord is allocated at the base of the frame.
+    intptr_t stackAlignment = stackAlignmentBytes();
+    intptr_t VMEntryTotalFrameSize = (sizeof(VMEntryRecord) + (stackAlignment - 1)) & ~(stackAlignment - 1);
+    return reinterpret_cast<VMEntryRecord*>(static_cast<char*>(entryFrame) - VMEntryTotalFrameSize);
+}
+
+
 #endif // ENABLE(JIT)
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/llint/LLIntThunks.h (172664 => 172665)


--- trunk/Source/_javascript_Core/llint/LLIntThunks.h	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/llint/LLIntThunks.h	2014-08-16 01:45:40 UTC (rev 172665)
@@ -34,8 +34,8 @@
 struct ProtoCallFrame;
 
 extern "C" {
-    EncodedJSValue callToJavaScript(void*, VM*, ProtoCallFrame*);
-    EncodedJSValue callToNativeFunction(void*, VM*, ProtoCallFrame*);
+    EncodedJSValue vmEntryToJavaScript(void*, VM*, ProtoCallFrame*);
+    EncodedJSValue vmEntryToNative(void*, VM*, ProtoCallFrame*);
 }
 
 namespace LLInt {

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (172664 => 172665)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2014-08-16 01:45:40 UTC (rev 172665)
@@ -42,6 +42,9 @@
 end
 const SlotSize = 8
 
+const StackAlignment = 16
+const StackAlignmentMask = StackAlignment - 1
+
 const CallerFrameAndPCSize = 2 * PtrSize
 
 const CallerFrame = 0
@@ -235,9 +238,9 @@
         if ARM or ARMv7 or ARMv7_TRADITIONAL
             # ARM can't do logical ops with the sp as a source
             move sp, tempReg
-            andp 0xf, tempReg
+            andp StackAlignmentMask, tempReg
         else
-            andp sp, 0xf, tempReg
+            andp sp, StackAlignmentMask, tempReg
         end
         btpz tempReg, .stackPointerOkay
         move location, tempReg
@@ -246,6 +249,26 @@
     end
 end
 
+if C_LOOP
+    const CalleeSaveRegisterCount = 0
+elsif ARM or ARMv7_TRADITIONAL or ARMv7
+    const CalleeSaveRegisterCount = 7
+elsif ARM64 or MIPS
+    const CalleeSaveRegisterCount = 10
+elsif SH4 or X86_64
+    const CalleeSaveRegisterCount = 5
+elsif X86 or X86_WIN
+    const CalleeSaveRegisterCount = 3
+elsif X86_64_WIN
+    const CalleeSaveRegisterCount = 7
+end
+
+const CalleeRegisterSaveSize = CalleeSaveRegisterCount * PtrSize
+
+# VMEntryTotalFrameSize includes the space for struct VMEntryRecord and the
+# callee save registers rounded up to keep the stack aligned
+const VMEntryTotalFrameSize = (CalleeRegisterSaveSize + sizeof VMEntryRecord + StackAlignment - 1) & ~StackAlignmentMask
+
 macro pushCalleeSaves()
     if C_LOOP
     elsif ARM or ARMv7_TRADITIONAL
@@ -417,75 +440,10 @@
     end
 end
 
-macro callToJavaScriptPrologue()
-    if X86_64 or X86_64_WIN
-        push cfr
-        push t0
-    elsif X86 or X86_WIN
-        push cfr
-    elsif ARM64
-        push cfr, lr
-    elsif C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
-        push lr
-        push cfr
-    end
-    pushCalleeSaves()
-    if X86
-        subp 12, sp
-    elsif X86_WIN
-        subp 16, sp
-        move sp, t4
-        move t4, t0
-        move t4, t2
-        andp 0xf, t2
-        andp 0xfffffff0, t0
-        move t0, sp
-        storep t4, [sp]
-    elsif ARM or ARMv7 or ARMv7_TRADITIONAL
-        subp 4, sp
-        move sp, t4
-        clrbp t4, 0xf, t5
-        move t5, sp
-        storep t4, [sp]
-    end
+macro vmEntryRecord(entryFramePointer, resultReg)
+    subp entryFramePointer, VMEntryTotalFrameSize, resultReg
 end
 
-macro callToJavaScriptEpilogue()
-    if ARMv7
-        addp CallFrameHeaderSlots * 8, cfr, t4
-        move t4, sp
-    else
-        addp CallFrameHeaderSlots * 8, cfr, sp
-    end
-
-    loadp CallerFrame[cfr], cfr
-
-    if X86
-        addp 12, sp
-    elsif X86_WIN
-        pop t4
-        move t4, sp
-        addp 16, sp
-    elsif ARM or ARMv7 or ARMv7_TRADITIONAL
-        pop t4
-        move t4, sp
-        addp 4, sp
-    end
-
-    popCalleeSaves()
-    if X86_64 or X86_64_WIN
-        pop t2
-        pop cfr
-    elsif X86 or X86_WIN
-        pop cfr
-    elsif ARM64
-        pop lr, cfr
-    elsif C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
-        pop cfr
-        pop lr
-    end
-end
-
 macro moveStackPointerForCodeBlock(codeBlock, scratch)
     loadi CodeBlock::m_numCalleeRegisters[codeBlock], scratch
     lshiftp 3, scratch
@@ -728,25 +686,25 @@
 end
 
 # stub to call into _javascript_ or Native functions
-# EncodedJSValue callToJavaScript(void* code, ExecState** vmTopCallFrame, ProtoCallFrame* protoFrame)
-# EncodedJSValue callToNativeFunction(void* code, ExecState** vmTopCallFrame, ProtoCallFrame* protoFrame)
+# EncodedJSValue vmEntryToJavaScript(void* code, VM* vm, ProtoCallFrame* protoFrame)
+# EncodedJSValue vmEntryToNativeFunction(void* code, VM* vm, ProtoCallFrame* protoFrame)
 
 if C_LOOP
-_llint_call_to_javascript:
+_llint_vm_entry_to_javascript:
 else
-global _callToJavaScript
-_callToJavaScript:
+global _vmEntryToJavaScript
+_vmEntryToJavaScript:
 end
-    doCallToJavaScript(makeJavaScriptCall)
+    doVMEntry(makeJavaScriptCall)
 
 
 if C_LOOP
-_llint_call_to_native_function:
+_llint_vm_entry_to_native:
 else
-global _callToNativeFunction
-_callToNativeFunction:
+global _vmEntryToNative
+_vmEntryToNative:
 end
-    doCallToJavaScript(makeHostFunctionCall)
+    doVMEntry(makeHostFunctionCall)
 
 
 if C_LOOP
@@ -789,9 +747,32 @@
     move sp, address
     storep address, VM::m_lastStackTop[vm]
     ret
-end
 
+if C_LOOP
+else
+# VMEntryRecord* vmEntryRecord(const VMEntryFrame* entryFrame)
+global _vmEntryRecord
+_vmEntryRecord:
+    if X86_64
+        const entryFrame = t4
+        const result = t0
+    elsif X86 or X86_WIN
+        const entryFrame = t2
+        const result = t0
+    else
+        const entryFrame = a0
+        const result = t0
+    end
 
+    if X86 or X86_WIN
+        loadp 4[sp], entryFrame
+    end
+
+    vmEntryRecord(entryFrame, result)
+    ret
+end
+end
+
 if C_LOOP
 # Dummy entry point the C Loop uses to initialize.
 _llint_entry:

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.cpp (172664 => 172665)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.cpp	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.cpp	2014-08-16 01:45:40 UTC (rev 172665)
@@ -338,7 +338,7 @@
     CallFrame* startCFR = cfr.callFrame;
 #endif
 
-    // Initialize the incoming args for doCallToJavaScript:
+    // Initialize the incoming args for doVMEntryToJavaScript:
     t0.vp = executableAddress;
     t1.vm = vm;
     t2.protoCallFrame = protoCallFrame;

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (172664 => 172665)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2014-08-16 01:45:40 UTC (rev 172665)
@@ -155,16 +155,14 @@
     move t0, PC
 end
 
-macro doCallToJavaScript(makeCall)
+macro doVMEntry(makeCall)
     if X86 or X86_WIN
         const entry = t4
         const vm = t3
         const protoCallFrame = t5
 
-        const previousCFR = t0
-        const previousPC = t1
-        const temp1 = t0 # Same as previousCFR
-        const temp2 = t1 # Same as previousPC
+        const temp1 = t0
+        const temp2 = t1
         const temp3 = t2
         const temp4 = t3 # same as vm
     elsif ARM or ARMv7 or ARMv7_TRADITIONAL or C_LOOP
@@ -172,9 +170,7 @@
         const vm = a1
         const protoCallFrame = a2
 
-        const previousCFR = t3
-        const previousPC = lr
-        const temp1 = t3 # Same as previousCFR
+        const temp1 = t3
         const temp2 = t4
         const temp3 = t5
         const temp4 = t4 # Same as temp2
@@ -184,8 +180,6 @@
         const protoCallFrame = a2
         const topOfStack = a3
 
-        const previousCFR = t2
-        const previousPC = lr
         const temp1 = t3
         const temp2 = t5
         const temp3 = t4
@@ -195,71 +189,53 @@
         const vm = a1
         const protoCallFrame = a2
 
-        const previousCFR = t3
-        const previousPC = lr
-        const temp1 = t3 # Same as previousCFR
+        const temp1 = t3
         const temp2 = a3
         const temp3 = t8
         const temp4 = t9
     end
 
-    callToJavaScriptPrologue()
+    functionPrologue()
+    pushCalleeSaves()
 
-    if X86
-        loadp 36[sp], vm
-        loadp 32[sp], entry
-    elsif X86_WIN
-        loadp 40[sp, temp3], vm
-        loadp 36[sp, temp3], entry
-    else
-        move cfr, previousCFR
+    if X86 or X86_WIN
+        loadp 12[cfr], vm
+        loadp 8[cfr], entry
     end
 
-    checkStackPointerAlignment(temp2, 0xbad0dc01)
+    vmEntryRecord(cfr, sp)
 
-    # The stack reserved zone ensures that we have adequate space for the
-    # VMEntrySentinelFrame. Proceed with allocating and initializing the
-    # sentinel frame.
-    move sp, cfr
-    subp CallFrameHeaderSlots * 8, cfr
-    storep 0, ArgumentCount[cfr]
-    storep vm, Callee[cfr]
+    storep vm, VMEntryRecord::m_vm[sp]
     loadp VM::topCallFrame[vm], temp2
-    storep temp2, ScopeChain[cfr]
-    storep 1, CodeBlock[cfr]
-    if X86
-        loadp 28[sp], previousPC
-        loadp 24[sp], previousCFR
-    elsif X86_WIN
-        loadp 32[sp, temp3], previousPC
-        loadp 28[sp, temp3], previousCFR
+    storep temp2, VMEntryRecord::m_prevTopCallFrame[sp]
+    loadp VM::topVMEntryFrame[vm], temp2
+    storep temp2, VMEntryRecord::m_prevTopVMEntryFrame[sp]
+
+    # Align stack pointer
+    if X86_WIN
+        addp CallFrameAlignSlots * SlotSize, sp, temp1
+        andp ~StackAlignmentMask, temp1
+        subp temp1, CallFrameAlignSlots * SlotSize, sp
+    elsif ARM or ARMv7 or ARMv7_TRADITIONAL
+        addp CallFrameAlignSlots * SlotSize, sp, temp1
+        clrbp temp1, StackAlignmentMask, temp1
+        subp temp1, CallFrameAlignSlots * SlotSize, sp
     end
-    storep previousPC, ReturnPC[cfr]
-    storep previousCFR, CallerFrame[cfr]
 
-    if X86
-        loadp 40[sp], protoCallFrame
-    elsif X86_WIN
-        loadp 44[sp, temp3], protoCallFrame
+    if X86 or X86_WIN
+        loadp 16[cfr], protoCallFrame
     end
 
     loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp2
     addp CallFrameHeaderSlots, temp2, temp2
     lshiftp 3, temp2
-    subp cfr, temp2, temp1
+    subp sp, temp2, temp1
 
     # Ensure that we have enough additional stack capacity for the incoming args,
     # and the frame for the JS code we're executing. We need to do this check
     # before we start copying the args from the protoCallFrame below.
     bpaeq temp1, VM::m_jsStackLimit[vm], .stackHeightOK
 
-    if ARMv7
-        subp cfr, 8, temp2
-        move temp2, sp
-    else
-        subp cfr, 8, sp
-    end
-
     if C_LOOP
         move entry, temp2
         move vm, temp3
@@ -275,7 +251,19 @@
     end
 
     cCall2(_llint_throw_stack_overflow_error, vm, protoCallFrame)
-    callToJavaScriptEpilogue()
+
+    vmEntryRecord(cfr, sp)
+
+    loadp VMEntryRecord::m_vm[sp], temp3
+    loadp VMEntryRecord::m_prevTopCallFrame[sp], temp4
+    storep temp4, VM::topCallFrame[temp3]
+    loadp VMEntryRecord::m_prevTopVMEntryFrame[sp], temp4
+    storep temp4, VM::topVMEntryFrame[temp3]
+
+    subp cfr, CalleeRegisterSaveSize, sp
+
+    popCalleeSaves()
+    functionEpilogue()
     ret
 
 .stackHeightOK:
@@ -316,18 +304,22 @@
 
 .copyArgsDone:
     storep sp, VM::topCallFrame[vm]
+    storep cfr, VM::topVMEntryFrame[vm]
 
     makeCall(entry, temp1, temp2)
 
-    bpeq CodeBlock[cfr], 1, .calleeFramePopped
-    loadp CallerFrame[cfr], cfr
+    vmEntryRecord(cfr, sp)
 
-.calleeFramePopped:
-    loadp Callee[cfr], temp3 # VM
-    loadp ScopeChain[cfr], temp4 # previous topCallFrame
+    loadp VMEntryRecord::m_vm[sp], temp3
+    loadp VMEntryRecord::m_prevTopCallFrame[sp], temp4
     storep temp4, VM::topCallFrame[temp3]
+    loadp VMEntryRecord::m_prevTopVMEntryFrame[sp], temp4
+    storep temp4, VM::topVMEntryFrame[temp3]
 
-    callToJavaScriptEpilogue()
+    subp cfr, CalleeRegisterSaveSize, sp
+
+    popCalleeSaves()
+    functionEpilogue()
     ret
 end
 
@@ -378,19 +370,20 @@
     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
     loadp VM::callFrameForThrow[t3], cfr
 
-    # So far, we've unwound the stack to the frame just below the sentinel frame, except
-    # in the case of stack overflow in the first function called from callToJavaScript.
-    # Check if we need to pop to the sentinel frame and do the necessary clean up for
-    # returning to the caller C frame.
-    bpeq CodeBlock[cfr], 1, .handleUncaughtExceptionAlreadyIsSentinel
     loadp CallerFrame + PayloadOffset[cfr], cfr
-.handleUncaughtExceptionAlreadyIsSentinel:
 
-    loadp Callee + PayloadOffset[cfr], t3 # VM
-    loadp ScopeChain + PayloadOffset[cfr], t5 # previous topCallFrame
+    vmEntryRecord(cfr, sp)
+
+    loadp VMEntryRecord::m_vm[sp], t3
+    loadp VMEntryRecord::m_prevTopCallFrame[sp], t5
     storep t5, VM::topCallFrame[t3]
+    loadp VMEntryRecord::m_prevTopVMEntryFrame[sp], t5
+    storep t5, VM::topVMEntryFrame[t3]
 
-    callToJavaScriptEpilogue()
+    subp cfr, CalleeRegisterSaveSize, sp
+
+    popCalleeSaves()
+    functionEpilogue()
     ret
 
 macro doReturnFromHostFunction(extraStackSpace)

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (172664 => 172665)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2014-08-16 01:45:40 UTC (rev 172665)
@@ -138,7 +138,7 @@
     end
 end
 
-macro doCallToJavaScript(makeCall)
+macro doVMEntry(makeCall)
     if X86_64
         const entry = t4
         const vm = t5
@@ -171,47 +171,29 @@
         const temp3 = t6
     end
 
-    callToJavaScriptPrologue()
+    functionPrologue()
+    pushCalleeSaves()
 
-    if X86_64
-        loadp 7*8[sp], previousPC
-        move 6*8[sp], previousCFR
-    elsif X86_64_WIN
-        # Win64 pushes two more registers
-        loadp 9*8[sp], previousPC
-        move 8*8[sp], previousCFR
-    elsif ARM64
-        move cfr, previousCFR
-    end
+    vmEntryRecord(cfr, sp)
 
     checkStackPointerAlignment(temp2, 0xbad0dc01)
 
-    # The stack reserved zone ensures that we have adequate space for the
-    # VMEntrySentinelFrame. Proceed with allocating and initializing the
-    # sentinel frame.
-    move sp, cfr
-    subp CallFrameHeaderSlots * 8, cfr
-    storep 0, ArgumentCount[cfr]
-    storep vm, Callee[cfr]
+    storep vm, VMEntryRecord::m_vm[sp]
     loadp VM::topCallFrame[vm], temp2
-    storep temp2, ScopeChain[cfr]
-    storep 1, CodeBlock[cfr]
+    storep temp2, VMEntryRecord::m_prevTopCallFrame[sp]
+    loadp VM::topVMEntryFrame[vm], temp2
+    storep temp2, VMEntryRecord::m_prevTopVMEntryFrame[sp]
 
-    storep previousPC, ReturnPC[cfr]
-    storep previousCFR, CallerFrame[cfr]
-
     loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp2
     addp CallFrameHeaderSlots, temp2, temp2
     lshiftp 3, temp2
-    subp cfr, temp2, temp1
+    subp sp, temp2, temp1
 
     # Ensure that we have enough additional stack capacity for the incoming args,
     # and the frame for the JS code we're executing. We need to do this check
     # before we start copying the args from the protoCallFrame below.
     bpaeq temp1, VM::m_jsStackLimit[vm], .stackHeightOK
 
-    move cfr, sp
-
     if C_LOOP
         move entry, temp2
         move vm, temp3
@@ -227,7 +209,19 @@
     end
 
     cCall2(_llint_throw_stack_overflow_error, vm, protoCallFrame)
-    callToJavaScriptEpilogue()
+
+    vmEntryRecord(cfr, temp2)
+
+    loadp VMEntryRecord::m_vm[temp2], vm
+    loadp VMEntryRecord::m_prevTopCallFrame[temp2], temp3
+    storep temp3, VM::topCallFrame[vm]
+    loadp VMEntryRecord::m_prevTopVMEntryFrame[temp2], temp3
+    storep temp3, VM::topVMEntryFrame[vm]
+
+    subp cfr, CalleeRegisterSaveSize, sp
+
+    popCalleeSaves()
+    functionEpilogue()
     ret
 
 .stackHeightOK:
@@ -269,6 +263,7 @@
     else
         storep sp, VM::topCallFrame[vm]
     end
+    storep cfr, VM::topVMEntryFrame[vm]
 
     move 0xffff000000000000, csr1
     addp 2, csr1, csr2
@@ -279,20 +274,18 @@
 
     checkStackPointerAlignment(temp3, 0xbad0dc03)
 
-    bpeq CodeBlock[cfr], 1, .calleeFramePopped
-    loadp CallerFrame[cfr], cfr
+    vmEntryRecord(cfr, temp2)
 
-.calleeFramePopped:
-    loadp Callee[cfr], temp2 # VM
-    loadp ScopeChain[cfr], temp3 # previous topCallFrame
-    storep temp3, VM::topCallFrame[temp2]
+    loadp VMEntryRecord::m_vm[temp2], vm
+    loadp VMEntryRecord::m_prevTopCallFrame[temp2], temp3
+    storep temp3, VM::topCallFrame[vm]
+    loadp VMEntryRecord::m_prevTopVMEntryFrame[temp2], temp3
+    storep temp3, VM::topVMEntryFrame[vm]
 
-    checkStackPointerAlignment(temp3, 0xbad0dc04)
+    subp cfr, CalleeRegisterSaveSize, sp
 
-    if X86_64 or X86_64_WIN
-        pop t5
-    end
-    callToJavaScriptEpilogue()
+    popCalleeSaves()
+    functionEpilogue()
 
     ret
 end
@@ -346,19 +339,19 @@
     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
     loadp VM::callFrameForThrow[t3], cfr
 
-    # So far, we've unwound the stack to the frame just below the sentinel frame, except
-    # in the case of stack overflow in the first function called from callToJavaScript.
-    # Check if we need to pop to the sentinel frame and do the necessary clean up for
-    # returning to the caller C frame.
-    bpeq CodeBlock[cfr], 1, .handleUncaughtExceptionAlreadyIsSentinel
     loadp CallerFrame[cfr], cfr
-.handleUncaughtExceptionAlreadyIsSentinel:
+    vmEntryRecord(cfr, t2)
 
-    loadp Callee[cfr], t3 # VM
-    loadp ScopeChain[cfr], t5 # previous topCallFrame
+    loadp VMEntryRecord::m_vm[t2], t3
+    loadp VMEntryRecord::m_prevTopCallFrame[t2], t5
     storep t5, VM::topCallFrame[t3]
+    loadp VMEntryRecord::m_prevTopVMEntryFrame[t2], t5
+    storep t5, VM::topVMEntryFrame[t3]
 
-    callToJavaScriptEpilogue()
+    subp cfr, CalleeRegisterSaveSize, sp
+
+    popCalleeSaves()
+    functionEpilogue()
     ret
 
 

Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (172664 => 172665)


--- trunk/Source/_javascript_Core/runtime/VM.cpp	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp	2014-08-16 01:45:40 UTC (rev 172665)
@@ -80,6 +80,7 @@
 #include "RegExpObject.h"
 #include "SimpleTypedArrayController.h"
 #include "SourceProviderCache.h"
+#include "StackVisitor.h"
 #include "StrictEvalActivation.h"
 #include "StrongInlines.h"
 #include "StructureInlines.h"
@@ -149,6 +150,7 @@
     , heap(this, heapType)
     , vmType(vmType)
     , clientData(0)
+    , topVMEntryFrame(nullptr)
     , topCallFrame(CallFrame::noCaller())
     , m_atomicStringTable(vmType == Default ? wtfThreadData().atomicStringTable() : new AtomicStringTable)
     , propertyNames(nullptr)
@@ -593,7 +595,42 @@
     
     exception->putDirect(*vm, vm->propertyNames->message, jsString(vm, message));
 }
-    
+
+class FindFirstCallerFrameWithCodeblockFunctor {
+public:
+    FindFirstCallerFrameWithCodeblockFunctor(CallFrame* startCallFrame)
+        : m_startCallFrame(startCallFrame)
+        , m_foundCallFrame(nullptr)
+        , m_foundStartCallFrame(false)
+        , m_index(0)
+    { }
+
+    StackVisitor::Status operator()(StackVisitor& visitor)
+    {
+        if (!m_foundStartCallFrame && (visitor->callFrame() == m_startCallFrame))
+            m_foundStartCallFrame = true;
+
+        if (m_foundStartCallFrame) {
+            if (visitor->callFrame()->codeBlock()) {
+                m_foundCallFrame = visitor->callFrame();
+                return StackVisitor::Done;
+            }
+            m_index++;
+        }
+
+        return StackVisitor::Continue;
+    }
+
+    CallFrame* foundCallFrame() const { return m_foundCallFrame; }
+    unsigned index() const { return m_index; }
+
+private:
+    CallFrame* m_startCallFrame;
+    CallFrame* m_foundCallFrame;
+    bool m_foundStartCallFrame;
+    unsigned m_index;
+};
+
 JSValue VM::throwException(ExecState* exec, JSValue error)
 {
     if (Options::breakOnThrow()) {
@@ -631,12 +668,11 @@
             exception->putDirect(*this, Identifier(this, "sourceURL"), jsString(this, stackFrame.sourceURL), ReadOnly | DontDelete);
     }
     if (exception->isErrorInstance() && static_cast<ErrorInstance*>(exception)->appendSourceToMessage()) {
-        unsigned stackIndex = 0;
-        CallFrame* callFrame;
-        for (callFrame = exec; callFrame && !callFrame->codeBlock(); ) {
-            stackIndex++;
-            callFrame = callFrame->callerFrameSkippingVMEntrySentinel();
-        }
+        FindFirstCallerFrameWithCodeblockFunctor functor(exec);
+        topCallFrame->iterate(functor);
+        CallFrame* callFrame = functor.foundCallFrame();
+        unsigned stackIndex = functor.index();
+
         if (callFrame && callFrame->codeBlock()) {
             stackFrame = stackTrace.at(stackIndex);
             bytecodeOffset = stackFrame.bytecodeOffset;

Modified: trunk/Source/_javascript_Core/runtime/VM.h (172664 => 172665)


--- trunk/Source/_javascript_Core/runtime/VM.h	2014-08-16 01:39:04 UTC (rev 172664)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2014-08-16 01:45:40 UTC (rev 172665)
@@ -47,6 +47,7 @@
 #include "ThunkGenerators.h"
 #include "TypedArrayController.h"
 #include "TypeLocation.h"
+#include "VMEntryRecord.h"
 #include "Watchdog.h"
 #include "Watchpoint.h"
 #include "WeakRandom.h"
@@ -235,6 +236,7 @@
 
         VMType vmType;
         ClientData* clientData;
+        VMEntryFrame* topVMEntryFrame;
         ExecState* topCallFrame;
         std::unique_ptr<Watchdog> watchdog;
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to