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

Generated by: LCOV version 1.10