JSStack.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  14. * its contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  18. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  21. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #ifndef JSStack_h
  29. #define JSStack_h
  30. #include "ExecutableAllocator.h"
  31. #include "Register.h"
  32. #include <wtf/Noncopyable.h>
  33. #include <wtf/PageReservation.h>
  34. #include <wtf/VMTags.h>
  35. #if !defined(NDEBUG) && !defined(ENABLE_DEBUG_JSSTACK)
  36. #define ENABLE_DEBUG_JSSTACK 1
  37. #endif
  38. namespace JSC {
  39. class ConservativeRoots;
  40. class DFGCodeBlocks;
  41. class ExecState;
  42. class JITStubRoutineSet;
  43. class VM;
  44. class LLIntOffsetsExtractor;
  45. class JSStack {
  46. WTF_MAKE_NONCOPYABLE(JSStack);
  47. public:
  48. enum CallFrameHeaderEntry {
  49. CallFrameHeaderSize = 6,
  50. ArgumentCount = -6,
  51. CallerFrame = -5,
  52. Callee = -4,
  53. ScopeChain = -3,
  54. ReturnPC = -2, // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*.
  55. CodeBlock = -1,
  56. };
  57. static const size_t defaultCapacity = 512 * 1024;
  58. static const size_t commitSize = 16 * 1024;
  59. // Allow 8k of excess registers before we start trying to reap the stack
  60. static const ptrdiff_t maxExcessCapacity = 8 * 1024;
  61. JSStack(VM&, size_t capacity = defaultCapacity);
  62. ~JSStack();
  63. void gatherConservativeRoots(ConservativeRoots&);
  64. void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, DFGCodeBlocks&);
  65. Register* begin() const { return static_cast<Register*>(m_reservation.base()); }
  66. Register* end() const { return m_end; }
  67. size_t size() const { return end() - begin(); }
  68. bool grow(Register*);
  69. static size_t committedByteCount();
  70. static void initializeThreading();
  71. Register* const * addressOfEnd() const
  72. {
  73. return &m_end;
  74. }
  75. Register* getTopOfFrame(CallFrame*);
  76. Register* getStartOfFrame(CallFrame*);
  77. Register* getTopOfStack();
  78. CallFrame* pushFrame(CallFrame* callerFrame, class CodeBlock*,
  79. JSScope*, int argsCount, JSObject* callee);
  80. void popFrame(CallFrame*);
  81. void enableErrorStackReserve();
  82. void disableErrorStackReserve();
  83. #if ENABLE(DEBUG_JSSTACK)
  84. void installFence(CallFrame*, const char *function = "", int lineNo = 0);
  85. void validateFence(CallFrame*, const char *function = "", int lineNo = 0);
  86. static const int FenceSize = 4;
  87. #else // !ENABLE(DEBUG_JSSTACK)
  88. void installFence(CallFrame*, const char* = "", int = 0) { }
  89. void validateFence(CallFrame*, const char* = "", int = 0) { }
  90. #endif // !ENABLE(DEBUG_JSSTACK)
  91. private:
  92. Register* reservationEnd() const
  93. {
  94. char* base = static_cast<char*>(m_reservation.base());
  95. char* reservationEnd = base + m_reservation.size();
  96. return reinterpret_cast_ptr<Register*>(reservationEnd);
  97. }
  98. #if ENABLE(DEBUG_JSSTACK)
  99. static JSValue generateFenceValue(size_t argIndex);
  100. void installTrapsAfterFrame(CallFrame*);
  101. #else
  102. void installTrapsAfterFrame(CallFrame*) { }
  103. #endif
  104. bool growSlowCase(Register*);
  105. void shrink(Register*);
  106. void releaseExcessCapacity();
  107. void addToCommittedByteCount(long);
  108. Register* m_end;
  109. Register* m_commitEnd;
  110. Register* m_useableEnd;
  111. PageReservation m_reservation;
  112. CallFrame*& m_topCallFrame;
  113. friend class LLIntOffsetsExtractor;
  114. };
  115. inline void JSStack::shrink(Register* newEnd)
  116. {
  117. if (newEnd >= m_end)
  118. return;
  119. m_end = newEnd;
  120. if (m_end == m_reservation.base() && (m_commitEnd - begin()) >= maxExcessCapacity)
  121. releaseExcessCapacity();
  122. }
  123. inline bool JSStack::grow(Register* newEnd)
  124. {
  125. if (newEnd <= m_end)
  126. return true;
  127. return growSlowCase(newEnd);
  128. }
  129. } // namespace JSC
  130. #endif // JSStack_h