LCOV - code coverage report
Current view: top level - src - execution.h (source / functions) Hit Total Coverage
Test: app.info Lines: 6 6 100.0 %
Date: 2017-04-26 Functions: 1 1 100.0 %

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_EXECUTION_H_
       6             : #define V8_EXECUTION_H_
       7             : 
       8             : #include "src/allocation.h"
       9             : #include "src/base/atomicops.h"
      10             : #include "src/globals.h"
      11             : #include "src/utils.h"
      12             : 
      13             : namespace v8 {
      14             : namespace internal {
      15             : 
      16             : template <typename T>
      17             : class Handle;
      18             : 
      19             : class Execution final : public AllStatic {
      20             :  public:
      21             :   // Whether to report pending messages, or keep them pending on the isolate.
      22             :   enum class MessageHandling { kReport, kKeepPending };
      23             : 
      24             :   // Call a function, the caller supplies a receiver and an array
      25             :   // of arguments.
      26             :   //
      27             :   // When the function called is not in strict mode, receiver is
      28             :   // converted to an object.
      29             :   //
      30             :   V8_EXPORT_PRIVATE MUST_USE_RESULT static MaybeHandle<Object> Call(
      31             :       Isolate* isolate, Handle<Object> callable, Handle<Object> receiver,
      32             :       int argc, Handle<Object> argv[]);
      33             : 
      34             :   // Construct object from function, the caller supplies an array of
      35             :   // arguments.
      36             :   MUST_USE_RESULT static MaybeHandle<Object> New(Handle<JSFunction> constructor,
      37             :                                                  int argc,
      38             :                                                  Handle<Object> argv[]);
      39             :   MUST_USE_RESULT static MaybeHandle<Object> New(Isolate* isolate,
      40             :                                                  Handle<Object> constructor,
      41             :                                                  Handle<Object> new_target,
      42             :                                                  int argc,
      43             :                                                  Handle<Object> argv[]);
      44             : 
      45             :   // Call a function, just like Call(), but handle don't report exceptions
      46             :   // externally.
      47             :   // The return value is either the result of calling the function (if no
      48             :   // exception occurred), or an empty handle.
      49             :   // If message_handling is MessageHandling::kReport, exceptions (except for
      50             :   // termination exceptions) will be stored in exception_out (if not a
      51             :   // nullptr).
      52             :   static MaybeHandle<Object> TryCall(Isolate* isolate, Handle<Object> callable,
      53             :                                      Handle<Object> receiver, int argc,
      54             :                                      Handle<Object> argv[],
      55             :                                      MessageHandling message_handling,
      56             :                                      MaybeHandle<Object>* exception_out);
      57             : };
      58             : 
      59             : 
      60             : class ExecutionAccess;
      61             : class PostponeInterruptsScope;
      62             : 
      63             : 
      64             : // StackGuard contains the handling of the limits that are used to limit the
      65             : // number of nested invocations of JavaScript and the stack size used in each
      66             : // invocation.
      67             : class V8_EXPORT_PRIVATE StackGuard final {
      68             :  public:
      69             :   // Pass the address beyond which the stack should not grow.  The stack
      70             :   // is assumed to grow downwards.
      71             :   void SetStackLimit(uintptr_t limit);
      72             : 
      73             :   // The simulator uses a separate JS stack. Limits on the JS stack might have
      74             :   // to be adjusted in order to reflect overflows of the C stack, because we
      75             :   // cannot rely on the interleaving of frames on the simulator.
      76             :   void AdjustStackLimitForSimulator();
      77             : 
      78             :   // Threading support.
      79             :   char* ArchiveStackGuard(char* to);
      80             :   char* RestoreStackGuard(char* from);
      81             :   static int ArchiveSpacePerThread() { return sizeof(ThreadLocal); }
      82             :   void FreeThreadResources();
      83             :   // Sets up the default stack guard for this thread if it has not
      84             :   // already been set up.
      85             :   void InitThread(const ExecutionAccess& lock);
      86             :   // Clears the stack guard for this thread so it does not look as if
      87             :   // it has been set up.
      88             :   void ClearThread(const ExecutionAccess& lock);
      89             : 
      90             : #define INTERRUPT_LIST(V)                       \
      91             :   V(DEBUGBREAK, DebugBreak, 0)                  \
      92             :   V(TERMINATE_EXECUTION, TerminateExecution, 1) \
      93             :   V(GC_REQUEST, GC, 2)                          \
      94             :   V(INSTALL_CODE, InstallCode, 3)               \
      95             :   V(API_INTERRUPT, ApiInterrupt, 4)             \
      96             :   V(DEOPT_MARKED_ALLOCATION_SITES, DeoptMarkedAllocationSites, 5)
      97             : 
      98             : #define V(NAME, Name, id)                                          \
      99             :   inline bool Check##Name() { return CheckInterrupt(NAME); }  \
     100             :   inline void Request##Name() { RequestInterrupt(NAME); }     \
     101             :   inline void Clear##Name() { ClearInterrupt(NAME); }
     102      113580 :   INTERRUPT_LIST(V)
     103             : #undef V
     104             : 
     105             :   // Flag used to set the interrupt causes.
     106             :   enum InterruptFlag {
     107             :   #define V(NAME, Name, id) NAME = (1 << id),
     108             :     INTERRUPT_LIST(V)
     109             :   #undef V
     110             :   #define V(NAME, Name, id) NAME |
     111             :     ALL_INTERRUPTS = INTERRUPT_LIST(V) 0
     112             :   #undef V
     113             :   };
     114             : 
     115             :   uintptr_t climit() { return thread_local_.climit(); }
     116             :   uintptr_t jslimit() { return thread_local_.jslimit(); }
     117             :   // This provides an asynchronous read of the stack limits for the current
     118             :   // thread.  There are no locks protecting this, but it is assumed that you
     119             :   // have the global V8 lock if you are using multiple V8 threads.
     120             :   uintptr_t real_climit() {
     121             :     return thread_local_.real_climit_;
     122             :   }
     123             :   uintptr_t real_jslimit() {
     124             :     return thread_local_.real_jslimit_;
     125             :   }
     126             :   Address address_of_jslimit() {
     127             :     return reinterpret_cast<Address>(&thread_local_.jslimit_);
     128             :   }
     129             :   Address address_of_real_jslimit() {
     130             :     return reinterpret_cast<Address>(&thread_local_.real_jslimit_);
     131             :   }
     132             : 
     133             :   // If the stack guard is triggered, but it is not an actual
     134             :   // stack overflow, then handle the interruption accordingly.
     135             :   Object* HandleInterrupts();
     136             :   void HandleGCInterrupt();
     137             : 
     138             :  private:
     139             :   StackGuard();
     140             : 
     141             :   bool CheckInterrupt(InterruptFlag flag);
     142             :   void RequestInterrupt(InterruptFlag flag);
     143             :   void ClearInterrupt(InterruptFlag flag);
     144             :   bool CheckAndClearInterrupt(InterruptFlag flag);
     145             : 
     146             :   // You should hold the ExecutionAccess lock when calling this method.
     147             :   bool has_pending_interrupts(const ExecutionAccess& lock) {
     148             :     return thread_local_.interrupt_flags_ != 0;
     149             :   }
     150             : 
     151             :   // You should hold the ExecutionAccess lock when calling this method.
     152             :   inline void set_interrupt_limits(const ExecutionAccess& lock);
     153             : 
     154             :   // Reset limits to actual values. For example after handling interrupt.
     155             :   // You should hold the ExecutionAccess lock when calling this method.
     156             :   inline void reset_limits(const ExecutionAccess& lock);
     157             : 
     158             :   // Enable or disable interrupts.
     159             :   void EnableInterrupts();
     160             :   void DisableInterrupts();
     161             : 
     162             : #if V8_TARGET_ARCH_64_BIT
     163             :   static const uintptr_t kInterruptLimit = V8_UINT64_C(0xfffffffffffffffe);
     164             :   static const uintptr_t kIllegalLimit = V8_UINT64_C(0xfffffffffffffff8);
     165             : #else
     166             :   static const uintptr_t kInterruptLimit = 0xfffffffe;
     167             :   static const uintptr_t kIllegalLimit = 0xfffffff8;
     168             : #endif
     169             : 
     170             :   void PushPostponeInterruptsScope(PostponeInterruptsScope* scope);
     171             :   void PopPostponeInterruptsScope();
     172             : 
     173             :   class ThreadLocal final {
     174             :    public:
     175       83356 :     ThreadLocal() { Clear(); }
     176             :     // You should hold the ExecutionAccess lock when you call Initialize or
     177             :     // Clear.
     178             :     void Clear();
     179             : 
     180             :     // Returns true if the heap's stack limits should be set, false if not.
     181             :     bool Initialize(Isolate* isolate);
     182             : 
     183             :     // The stack limit is split into a JavaScript and a C++ stack limit. These
     184             :     // two are the same except when running on a simulator where the C++ and
     185             :     // JavaScript stacks are separate. Each of the two stack limits have two
     186             :     // values. The one eith the real_ prefix is the actual stack limit
     187             :     // set for the VM. The one without the real_ prefix has the same value as
     188             :     // the actual stack limit except when there is an interruption (e.g. debug
     189             :     // break or preemption) in which case it is lowered to make stack checks
     190             :     // fail. Both the generated code and the runtime system check against the
     191             :     // one without the real_ prefix.
     192             :     uintptr_t real_jslimit_;  // Actual JavaScript stack limit set for the VM.
     193             :     uintptr_t real_climit_;  // Actual C++ stack limit set for the VM.
     194             : 
     195             :     // jslimit_ and climit_ can be read without any lock.
     196             :     // Writing requires the ExecutionAccess lock.
     197             :     base::AtomicWord jslimit_;
     198             :     base::AtomicWord climit_;
     199             : 
     200             :     uintptr_t jslimit() {
     201     7644327 :       return bit_cast<uintptr_t>(base::NoBarrier_Load(&jslimit_));
     202             :     }
     203             :     void set_jslimit(uintptr_t limit) {
     204             :       return base::NoBarrier_Store(&jslimit_,
     205     7558970 :                                    static_cast<base::AtomicWord>(limit));
     206             :     }
     207             :     uintptr_t climit() {
     208    69416012 :       return bit_cast<uintptr_t>(base::NoBarrier_Load(&climit_));
     209             :     }
     210             :     void set_climit(uintptr_t limit) {
     211             :       return base::NoBarrier_Store(&climit_,
     212     7558970 :                                    static_cast<base::AtomicWord>(limit));
     213             :     }
     214             : 
     215             :     PostponeInterruptsScope* postpone_interrupts_;
     216             :     int interrupt_flags_;
     217             :   };
     218             : 
     219             :   // TODO(isolates): Technically this could be calculated directly from a
     220             :   //                 pointer to StackGuard.
     221             :   Isolate* isolate_;
     222             :   ThreadLocal thread_local_;
     223             : 
     224             :   friend class Isolate;
     225             :   friend class StackLimitCheck;
     226             :   friend class PostponeInterruptsScope;
     227             : 
     228             :   DISALLOW_COPY_AND_ASSIGN(StackGuard);
     229             : };
     230             : 
     231             : }  // namespace internal
     232             : }  // namespace v8
     233             : 
     234             : #endif  // V8_EXECUTION_H_

Generated by: LCOV version 1.10