LCOV - code coverage report
Current view: top level - js/src/vm - Initialization.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 41 62 66.1 %
Date: 2017-07-14 16:53:18 Functions: 6 7 85.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /* SpiderMonkey initialization and shutdown code. */
       8             : 
       9             : #include "js/Initialization.h"
      10             : 
      11             : #include "mozilla/Assertions.h"
      12             : 
      13             : #include <ctype.h>
      14             : 
      15             : #include "jstypes.h"
      16             : 
      17             : #include "builtin/AtomicsObject.h"
      18             : #include "ds/MemoryProtectionExceptionHandler.h"
      19             : #include "gc/Statistics.h"
      20             : #include "jit/ExecutableAllocator.h"
      21             : #include "jit/Ion.h"
      22             : #include "jit/JitCommon.h"
      23             : #include "js/Utility.h"
      24             : #if ENABLE_INTL_API
      25             : #include "unicode/uclean.h"
      26             : #include "unicode/utypes.h"
      27             : #endif // ENABLE_INTL_API
      28             : #include "vm/DateTime.h"
      29             : #include "vm/HelperThreads.h"
      30             : #include "vm/Runtime.h"
      31             : #include "vm/Time.h"
      32             : #include "vm/TraceLogging.h"
      33             : #include "vtune/VTuneWrapper.h"
      34             : #include "wasm/WasmBuiltins.h"
      35             : #include "wasm/WasmInstance.h"
      36             : 
      37             : using JS::detail::InitState;
      38             : using JS::detail::libraryInitState;
      39             : using js::FutexThread;
      40             : 
      41             : InitState JS::detail::libraryInitState;
      42             : 
      43             : #ifdef DEBUG
      44             : static unsigned
      45        1491 : MessageParameterCount(const char* format)
      46             : {
      47        1491 :     unsigned numfmtspecs = 0;
      48       63168 :     for (const char* fmt = format; *fmt != '\0'; fmt++) {
      49       61677 :         if (*fmt == '{' && isdigit(fmt[1]))
      50         657 :             ++numfmtspecs;
      51             :     }
      52        1491 :     return numfmtspecs;
      53             : }
      54             : 
      55             : static void
      56           3 : CheckMessageParameterCounts()
      57             : {
      58             :     // Assert that each message format has the correct number of braced
      59             :     // parameters.
      60             : # define MSG_DEF(name, count, exception, format)           \
      61             :         MOZ_ASSERT(MessageParameterCount(format) == count);
      62             : # include "js.msg"
      63             : # undef MSG_DEF
      64           3 : }
      65             : #endif /* DEBUG */
      66             : 
      67             : #define RETURN_IF_FAIL(code) do { if (!code) return #code " failed"; } while (0)
      68             : 
      69             : JS_PUBLIC_API(const char*)
      70           3 : JS::detail::InitWithFailureDiagnostic(bool isDebugBuild)
      71             : {
      72             :     // Verify that our DEBUG setting matches the caller's.
      73             : #ifdef DEBUG
      74           3 :     MOZ_RELEASE_ASSERT(isDebugBuild);
      75             : #else
      76             :     MOZ_RELEASE_ASSERT(!isDebugBuild);
      77             : #endif
      78             : 
      79           3 :     MOZ_ASSERT(libraryInitState == InitState::Uninitialized,
      80             :                "must call JS_Init once before any JSAPI operation except "
      81             :                "JS_SetICUMemoryFunctions");
      82           3 :     MOZ_ASSERT(!JSRuntime::hasLiveRuntimes(),
      83             :                "how do we have live runtimes before JS_Init?");
      84             : 
      85           3 :     PRMJ_NowInit();
      86             : 
      87             :     // The first invocation of `ProcessCreation` creates a temporary thread
      88             :     // and crashes if that fails, i.e. because we're out of memory. To prevent
      89             :     // that from happening at some later time, get it out of the way during
      90             :     // startup.
      91           3 :     mozilla::TimeStamp::ProcessCreation();
      92             : 
      93             : #ifdef DEBUG
      94           3 :     CheckMessageParameterCounts();
      95             : #endif
      96             : 
      97           3 :     RETURN_IF_FAIL(js::TlsContext.init());
      98             : 
      99             : #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
     100           3 :     RETURN_IF_FAIL(js::oom::InitThreadType());
     101           3 :     js::oom::SetThreadType(js::oom::THREAD_TYPE_COOPERATING);
     102             : #endif
     103             : 
     104           3 :     RETURN_IF_FAIL(js::Mutex::Init());
     105             : 
     106           3 :     RETURN_IF_FAIL(js::wasm::InitInstanceStaticData());
     107             : 
     108           3 :     js::gc::InitMemorySubsystem(); // Ensure gc::SystemPageSize() works.
     109           3 :     RETURN_IF_FAIL(js::gc::InitializeStaticData());
     110             : 
     111           3 :     RETURN_IF_FAIL(js::jit::InitProcessExecutableMemory());
     112             : 
     113           3 :     MOZ_ALWAYS_TRUE(js::MemoryProtectionExceptionHandler::install());
     114             : 
     115           3 :     RETURN_IF_FAIL(js::jit::InitializeIon());
     116             : 
     117           3 :     RETURN_IF_FAIL(js::InitDateTimeState());
     118             : 
     119             : #ifdef MOZ_VTUNE
     120           3 :     RETURN_IF_FAIL(js::vtune::Initialize());
     121             : #endif
     122             : 
     123             : #if EXPOSE_INTL_API
     124           3 :     UErrorCode err = U_ZERO_ERROR;
     125           3 :     u_init(&err);
     126           3 :     if (U_FAILURE(err))
     127           0 :         return "u_init() failed";
     128             : #endif // EXPOSE_INTL_API
     129             : 
     130           3 :     RETURN_IF_FAIL(js::CreateHelperThreadsState());
     131           3 :     RETURN_IF_FAIL(FutexThread::initialize());
     132           3 :     RETURN_IF_FAIL(js::gcstats::Statistics::initialize());
     133             : 
     134             : #ifdef JS_SIMULATOR
     135             :     RETURN_IF_FAIL(js::jit::SimulatorProcess::initialize());
     136             : #endif
     137             : 
     138           3 :     libraryInitState = InitState::Running;
     139           3 :     return nullptr;
     140             : }
     141             : 
     142             : #undef RETURN_IF_FAIL
     143             : 
     144             : JS_PUBLIC_API(void)
     145           0 : JS_ShutDown(void)
     146             : {
     147           0 :     MOZ_ASSERT(libraryInitState == InitState::Running,
     148             :                "JS_ShutDown must only be called after JS_Init and can't race with it");
     149             : #ifdef DEBUG
     150           0 :     if (JSRuntime::hasLiveRuntimes()) {
     151             :         // Gecko is too buggy to assert this just yet.
     152             :         fprintf(stderr,
     153             :                 "WARNING: YOU ARE LEAKING THE WORLD (at least one JSRuntime "
     154             :                 "and everything alive inside it, that is) AT JS_ShutDown "
     155           0 :                 "TIME.  FIX THIS!\n");
     156             :     }
     157             : #endif
     158             : 
     159           0 :     FutexThread::destroy();
     160             : 
     161           0 :     js::DestroyHelperThreadsState();
     162             : 
     163             : #ifdef JS_SIMULATOR
     164             :     js::jit::SimulatorProcess::destroy();
     165             : #endif
     166             : 
     167             : #ifdef JS_TRACE_LOGGING
     168           0 :     js::DestroyTraceLoggerThreadState();
     169           0 :     js::DestroyTraceLoggerGraphState();
     170             : #endif
     171             : 
     172           0 :     js::MemoryProtectionExceptionHandler::uninstall();
     173             : 
     174           0 :     js::wasm::ShutDownInstanceStaticData();
     175             : 
     176           0 :     js::Mutex::ShutDown();
     177             : 
     178             :     // The only difficult-to-address reason for the restriction that you can't
     179             :     // call JS_Init/stuff/JS_ShutDown multiple times is the Windows PRMJ
     180             :     // NowInit initialization code, which uses PR_CallOnce to initialize the
     181             :     // PRMJ_Now subsystem.  (For reinitialization to be permitted, we'd need to
     182             :     // "reset" the called-once status -- doable, but more trouble than it's
     183             :     // worth now.)  Initializing that subsystem from JS_Init eliminates the
     184             :     // problem, but initialization can take a comparatively long time (15ms or
     185             :     // so), so we really don't want to do it in JS_Init, and we really do want
     186             :     // to do it only when PRMJ_Now is eventually called.
     187           0 :     PRMJ_NowShutdown();
     188             : 
     189             : #if EXPOSE_INTL_API
     190           0 :     u_cleanup();
     191             : #endif // EXPOSE_INTL_API
     192             : 
     193             : #ifdef MOZ_VTUNE
     194           0 :     js::vtune::Shutdown();
     195             : #endif // MOZ_VTUNE
     196             : 
     197           0 :     js::FinishDateTimeState();
     198             : 
     199           0 :     if (!JSRuntime::hasLiveRuntimes()) {
     200           0 :         js::wasm::ReleaseBuiltinThunks();
     201           0 :         js::jit::ReleaseProcessExecutableMemory();
     202             :     }
     203             : 
     204           0 :     libraryInitState = InitState::ShutDown;
     205           0 : }
     206             : 
     207             : JS_PUBLIC_API(bool)
     208           3 : JS_SetICUMemoryFunctions(JS_ICUAllocFn allocFn, JS_ICUReallocFn reallocFn, JS_ICUFreeFn freeFn)
     209             : {
     210           3 :     MOZ_ASSERT(libraryInitState == InitState::Uninitialized,
     211             :                "must call JS_SetICUMemoryFunctions before any other JSAPI "
     212             :                "operation (including JS_Init)");
     213             : 
     214             : #if EXPOSE_INTL_API
     215           3 :     UErrorCode status = U_ZERO_ERROR;
     216           3 :     u_setMemoryFunctions(/* context = */ nullptr, allocFn, reallocFn, freeFn, &status);
     217           3 :     return U_SUCCESS(status);
     218             : #else
     219             :     return true;
     220             : #endif
     221           9 : }

Generated by: LCOV version 1.13