• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 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 #include "src/init/v8.h"
6 
7 #include <fstream>
8 
9 #include "include/cppgc/platform.h"
10 #include "src/api/api.h"
11 #include "src/base/atomicops.h"
12 #include "src/base/once.h"
13 #include "src/base/platform/platform.h"
14 #include "src/codegen/cpu-features.h"
15 #include "src/codegen/interface-descriptors.h"
16 #include "src/debug/debug.h"
17 #include "src/deoptimizer/deoptimizer.h"
18 #include "src/execution/frames.h"
19 #include "src/execution/isolate.h"
20 #include "src/execution/simulator.h"
21 #include "src/init/bootstrapper.h"
22 #include "src/libsampler/sampler.h"
23 #include "src/objects/elements.h"
24 #include "src/objects/objects-inl.h"
25 #include "src/profiler/heap-profiler.h"
26 #include "src/sandbox/sandbox.h"
27 #include "src/snapshot/snapshot.h"
28 #include "src/tracing/tracing-category-observer.h"
29 
30 #if V8_ENABLE_WEBASSEMBLY
31 #include "src/wasm/wasm-engine.h"
32 #endif  // V8_ENABLE_WEBASSEMBLY
33 
34 #if defined(V8_OS_WIN) && defined(V8_ENABLE_SYSTEM_INSTRUMENTATION)
35 #include "src/diagnostics/system-jit-win.h"
36 #endif
37 
38 namespace v8 {
39 namespace internal {
40 
41 v8::Platform* V8::platform_ = nullptr;
42 
43 namespace {
44 enum class V8StartupState {
45   kIdle,
46   kPlatformInitializing,
47   kPlatformInitialized,
48   kV8Initializing,
49   kV8Initialized,
50   kV8Disposing,
51   kV8Disposed,
52   kPlatformDisposing,
53   kPlatformDisposed
54 };
55 
56 std::atomic<V8StartupState> v8_startup_state_(V8StartupState::kIdle);
57 
AdvanceStartupState(V8StartupState expected_next_state)58 void AdvanceStartupState(V8StartupState expected_next_state) {
59   V8StartupState current_state = v8_startup_state_;
60   CHECK_NE(current_state, V8StartupState::kPlatformDisposed);
61   V8StartupState next_state =
62       static_cast<V8StartupState>(static_cast<int>(current_state) + 1);
63   if (next_state != expected_next_state) {
64     // Ensure the following order:
65     // v8::V8::InitializePlatform(platform);
66     // v8::V8::Initialize();
67     // v8::Isolate* isolate = v8::Isolate::New(...);
68     // ...
69     // isolate->Dispose();
70     // v8::V8::Dispose();
71     // v8::V8::DisposePlatform();
72     FATAL("Wrong initialization order: got %d expected %d!",
73           static_cast<int>(current_state), static_cast<int>(next_state));
74   }
75   if (!v8_startup_state_.compare_exchange_strong(current_state, next_state)) {
76     FATAL(
77         "Multiple threads are initializating V8 in the wrong order: expected "
78         "%d got %d!",
79         static_cast<int>(current_state),
80         static_cast<int>(v8_startup_state_.load()));
81   }
82 }
83 
84 }  // namespace
85 
86 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
87 V8_DECLARE_ONCE(init_snapshot_once);
88 #endif
89 
InitializePlatform(v8::Platform * platform)90 void V8::InitializePlatform(v8::Platform* platform) {
91   AdvanceStartupState(V8StartupState::kPlatformInitializing);
92   CHECK(!platform_);
93   CHECK_NOT_NULL(platform);
94   platform_ = platform;
95   v8::base::SetPrintStackTrace(platform_->GetStackTracePrinter());
96   v8::tracing::TracingCategoryObserver::SetUp();
97 #if defined(V8_OS_WIN) && defined(V8_ENABLE_SYSTEM_INSTRUMENTATION)
98   if (FLAG_enable_system_instrumentation) {
99     // TODO(sartang@microsoft.com): Move to platform specific diagnostics object
100     v8::internal::ETWJITInterface::Register();
101   }
102 #endif
103   AdvanceStartupState(V8StartupState::kPlatformInitialized);
104 }
105 
106 #ifdef V8_SANDBOX
InitializeSandbox()107 bool V8::InitializeSandbox() {
108   // Platform must have been initialized already.
109   CHECK(platform_);
110   v8::VirtualAddressSpace* vas = GetPlatformVirtualAddressSpace();
111   return GetProcessWideSandbox()->Initialize(vas);
112 }
113 #endif  // V8_SANDBOX
114 
115 #define DISABLE_FLAG(flag)                                                    \
116   if (FLAG_##flag) {                                                          \
117     PrintF(stderr,                                                            \
118            "Warning: disabling flag --" #flag " due to conflicting flags\n"); \
119     FLAG_##flag = false;                                                      \
120   }
121 
Initialize()122 void V8::Initialize() {
123   AdvanceStartupState(V8StartupState::kV8Initializing);
124   CHECK(platform_);
125 
126 #ifdef V8_SANDBOX
127   if (!GetProcessWideSandbox()->is_initialized()) {
128     // For now, we still allow the cage to be disabled even if V8 was compiled
129     // with V8_SANDBOX. This will eventually be forbidden.
130     CHECK(kAllowBackingStoresOutsideSandbox);
131     GetProcessWideSandbox()->Disable();
132   }
133 #endif
134 
135   // Update logging information before enforcing flag implications.
136   bool* log_all_flags[] = {&FLAG_turbo_profiling_log_builtins,
137                            &FLAG_log_all,
138                            &FLAG_log_code,
139                            &FLAG_log_code_disassemble,
140                            &FLAG_log_source_code,
141                            &FLAG_log_function_events,
142                            &FLAG_log_internal_timer_events,
143                            &FLAG_log_deopt,
144                            &FLAG_log_ic,
145                            &FLAG_log_maps};
146   if (FLAG_log_all) {
147     // Enable all logging flags
148     for (auto* flag : log_all_flags) {
149       *flag = true;
150     }
151     FLAG_log = true;
152   } else if (!FLAG_log) {
153     // Enable --log if any log flag is set.
154     for (const auto* flag : log_all_flags) {
155       if (!*flag) continue;
156       FLAG_log = true;
157       break;
158     }
159     // Profiling flags depend on logging.
160     FLAG_log |= FLAG_perf_prof || FLAG_perf_basic_prof || FLAG_ll_prof ||
161                 FLAG_prof || FLAG_prof_cpp;
162     FLAG_log |= FLAG_gdbjit;
163 #if defined(V8_OS_WIN) && defined(V8_ENABLE_SYSTEM_INSTRUMENTATION)
164     FLAG_log |= FLAG_enable_system_instrumentation;
165 #endif
166   }
167 
168   FlagList::EnforceFlagImplications();
169 
170   if (FLAG_predictable && FLAG_random_seed == 0) {
171     // Avoid random seeds in predictable mode.
172     FLAG_random_seed = 12347;
173   }
174 
175   if (FLAG_stress_compaction) {
176     FLAG_force_marking_deque_overflows = true;
177     FLAG_gc_global = true;
178     FLAG_max_semi_space_size = 1;
179   }
180 
181   if (FLAG_trace_turbo) {
182     // Create an empty file shared by the process (e.g. the wasm engine).
183     std::ofstream(Isolate::GetTurboCfgFileName(nullptr).c_str(),
184                   std::ios_base::trunc);
185   }
186 
187   // Do not expose wasm in jitless mode.
188   //
189   // Even in interpreter-only mode, wasm currently still creates executable
190   // memory at runtime. Unexpose wasm until this changes.
191   // The correctness fuzzers are a special case: many of their test cases are
192   // built by fetching a random property from the the global object, and thus
193   // the global object layout must not change between configs. That is why we
194   // continue exposing wasm on correctness fuzzers even in jitless mode.
195   // TODO(jgruber): Remove this once / if wasm can run without executable
196   // memory.
197 #if V8_ENABLE_WEBASSEMBLY
198   if (FLAG_jitless && !FLAG_correctness_fuzzer_suppressions) {
199     DISABLE_FLAG(expose_wasm);
200   }
201 #endif
202 
203   // When fuzzing and concurrent compilation is enabled, disable Turbofan
204   // tracing flags since reading/printing heap state is not thread-safe and
205   // leads to false positives on TSAN bots.
206   // TODO(chromium:1205289): Teach relevant fuzzers to not pass TF tracing
207   // flags instead, and remove this section.
208   if (FLAG_fuzzing && FLAG_concurrent_recompilation) {
209     DISABLE_FLAG(trace_turbo);
210     DISABLE_FLAG(trace_turbo_graph);
211     DISABLE_FLAG(trace_turbo_scheduled);
212     DISABLE_FLAG(trace_turbo_reduction);
213     DISABLE_FLAG(trace_turbo_trimming);
214     DISABLE_FLAG(trace_turbo_jt);
215     DISABLE_FLAG(trace_turbo_ceq);
216     DISABLE_FLAG(trace_turbo_loop);
217     DISABLE_FLAG(trace_turbo_alloc);
218     DISABLE_FLAG(trace_all_uses);
219     DISABLE_FLAG(trace_representation);
220     DISABLE_FLAG(trace_turbo_stack_accesses);
221   }
222 
223   // The --jitless and --interpreted-frames-native-stack flags are incompatible
224   // since the latter requires code generation while the former prohibits code
225   // generation.
226   CHECK(!FLAG_interpreted_frames_native_stack || !FLAG_jitless);
227 
228   base::OS::Initialize(FLAG_hard_abort, FLAG_gc_fake_mmap);
229 
230   if (FLAG_random_seed) SetRandomMmapSeed(FLAG_random_seed);
231 
232   if (FLAG_print_flag_values) FlagList::PrintValues();
233 
234   // Initialize the default FlagList::Hash
235   FlagList::Hash();
236 
237 #if defined(V8_USE_PERFETTO)
238   if (perfetto::Tracing::IsInitialized()) TrackEvent::Register();
239 #endif
240   IsolateAllocator::InitializeOncePerProcess();
241   Isolate::InitializeOncePerProcess();
242 
243 #if defined(USE_SIMULATOR)
244   Simulator::InitializeOncePerProcess();
245 #endif
246   CpuFeatures::Probe(false);
247   ElementsAccessor::InitializeOncePerProcess();
248   Bootstrapper::InitializeOncePerProcess();
249   CallDescriptors::InitializeOncePerProcess();
250 #if V8_ENABLE_WEBASSEMBLY
251   wasm::WasmEngine::InitializeOncePerProcess();
252 #endif  // V8_ENABLE_WEBASSEMBLY
253 
254   ExternalReferenceTable::InitializeOncePerProcess();
255 
256   AdvanceStartupState(V8StartupState::kV8Initialized);
257 }
258 
259 #undef DISABLE_FLAG
260 
Dispose()261 void V8::Dispose() {
262   AdvanceStartupState(V8StartupState::kV8Disposing);
263   CHECK(platform_);
264 #if V8_ENABLE_WEBASSEMBLY
265   wasm::WasmEngine::GlobalTearDown();
266 #endif  // V8_ENABLE_WEBASSEMBLY
267 #if defined(USE_SIMULATOR)
268   Simulator::GlobalTearDown();
269 #endif
270   CallDescriptors::TearDown();
271   ElementsAccessor::TearDown();
272   RegisteredExtension::UnregisterAll();
273   Isolate::DisposeOncePerProcess();
274   FlagList::ResetAllFlags();  // Frees memory held by string arguments.
275   AdvanceStartupState(V8StartupState::kV8Disposed);
276 }
277 
DisposePlatform()278 void V8::DisposePlatform() {
279   AdvanceStartupState(V8StartupState::kPlatformDisposing);
280   CHECK(platform_);
281 #if defined(V8_OS_WIN) && defined(V8_ENABLE_SYSTEM_INSTRUMENTATION)
282   if (FLAG_enable_system_instrumentation) {
283     v8::internal::ETWJITInterface::Unregister();
284   }
285 #endif
286   v8::tracing::TracingCategoryObserver::TearDown();
287   v8::base::SetPrintStackTrace(nullptr);
288 
289 #ifdef V8_SANDBOX
290   // TODO(chromium:1218005) alternatively, this could move to its own
291   // public TearDownSandbox function.
292   GetProcessWideSandbox()->TearDown();
293 #endif
294 
295   platform_ = nullptr;
296   AdvanceStartupState(V8StartupState::kPlatformDisposed);
297 }
298 
GetCurrentPlatform()299 v8::Platform* V8::GetCurrentPlatform() {
300   v8::Platform* platform = reinterpret_cast<v8::Platform*>(
301       base::Relaxed_Load(reinterpret_cast<base::AtomicWord*>(&platform_)));
302   DCHECK(platform);
303   return platform;
304 }
305 
SetPlatformForTesting(v8::Platform * platform)306 void V8::SetPlatformForTesting(v8::Platform* platform) {
307   base::Relaxed_Store(reinterpret_cast<base::AtomicWord*>(&platform_),
308                       reinterpret_cast<base::AtomicWord>(platform));
309 }
310 
SetSnapshotBlob(StartupData * snapshot_blob)311 void V8::SetSnapshotBlob(StartupData* snapshot_blob) {
312 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
313   base::CallOnce(&init_snapshot_once, &SetSnapshotFromFile, snapshot_blob);
314 #else
315   UNREACHABLE();
316 #endif
317 }
318 }  // namespace internal
319 
320 // static
SystemClockTimeMillis()321 double Platform::SystemClockTimeMillis() {
322   return base::OS::TimeCurrentMillis();
323 }
324 }  // namespace v8
325