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;