blob: cb67105c3f55c08b4953b30d7b948e6823449d60 [file] [log] [blame]
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001// Copyright 2012 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
fschneider@chromium.org7d10be52012-04-10 12:30:14 +000030#include "assembler.h"
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000031#include "isolate.h"
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +000032#include "elements.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000033#include "bootstrapper.h"
34#include "debug.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000035#include "deoptimizer.h"
fschneider@chromium.org7d10be52012-04-10 12:30:14 +000036#include "frames.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000037#include "heap-profiler.h"
38#include "hydrogen.h"
39#include "lithium-allocator.h"
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +000040#include "objects.h"
jkummerow@chromium.org1456e702012-03-30 08:38:13 +000041#include "once.h"
42#include "platform.h"
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000043#include "sampler.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000044#include "runtime-profiler.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045#include "serialize.h"
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000046#include "store-buffer.h"
ager@chromium.orgeadaf222009-06-16 09:43:10 +000047
kasperl@chromium.org71affb52009-05-26 05:44:31 +000048namespace v8 {
49namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000050
jkummerow@chromium.org1456e702012-03-30 08:38:13 +000051V8_DECLARE_ONCE(init_once);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000052
kasperl@chromium.org71affb52009-05-26 05:44:31 +000053bool V8::is_running_ = false;
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000054bool V8::has_been_set_up_ = false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000055bool V8::has_been_disposed_ = false;
kasperl@chromium.org71affb52009-05-26 05:44:31 +000056bool V8::has_fatal_error_ = false;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000057bool V8::use_crankshaft_ = true;
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000058List<CallCompletedCallback>* V8::call_completed_callbacks_ = NULL;
ulan@chromium.org837a67e2013-06-11 15:39:48 +000059v8::ArrayBuffer::Allocator* V8::array_buffer_allocator_ = NULL;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000060
jkummerow@chromium.org1456e702012-03-30 08:38:13 +000061static LazyMutex entropy_mutex = LAZY_MUTEX_INITIALIZER;
62
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +000063static EntropySource entropy_source;
64
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +000065
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000066bool V8::Initialize(Deserializer* des) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000067 InitializeOncePerProcess();
68
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000069 // The current thread may not yet had entered an isolate to run.
70 // Note the Isolate::Current() may be non-null because for various
71 // initialization purposes an initializing thread may be assigned an isolate
72 // but not actually enter it.
73 if (i::Isolate::CurrentPerIsolateThreadData() == NULL) {
74 i::Isolate::EnterDefaultIsolate();
75 }
76
77 ASSERT(i::Isolate::CurrentPerIsolateThreadData() != NULL);
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000078 ASSERT(i::Isolate::CurrentPerIsolateThreadData()->thread_id().Equals(
79 i::ThreadId::Current()));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000080 ASSERT(i::Isolate::CurrentPerIsolateThreadData()->isolate() ==
81 i::Isolate::Current());
82
83 if (IsDead()) return false;
84
85 Isolate* isolate = Isolate::Current();
86 if (isolate->IsInitialized()) return true;
kasperl@chromium.org71affb52009-05-26 05:44:31 +000087
88 is_running_ = true;
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000089 has_been_set_up_ = true;
kasperl@chromium.org71affb52009-05-26 05:44:31 +000090 has_fatal_error_ = false;
91 has_been_disposed_ = false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000092
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000093 return isolate->Init(des);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000094}
95
96
kasperl@chromium.org71affb52009-05-26 05:44:31 +000097void V8::SetFatalError() {
98 is_running_ = false;
99 has_fatal_error_ = true;
100}
101
102
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000103void V8::TearDown() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000104 Isolate* isolate = Isolate::Current();
105 ASSERT(isolate->IsDefaultIsolate());
106
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000107 if (!has_been_set_up_ || has_been_disposed_) return;
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000108
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000109 // The isolate has to be torn down before clearing the LOperand
110 // caches so that the optimizing compiler thread (if running)
111 // doesn't see an inconsistent view of the lithium instructions.
112 isolate->TearDown();
113 delete isolate;
114
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000115 ElementsAccessor::TearDown();
116 LOperand::TearDownCaches();
danno@chromium.org1f34ad32012-11-26 14:53:56 +0000117 ExternalReference::TearDownMathExpData();
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000118 RegisteredExtension::UnregisterAll();
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000119 Isolate::GlobalTearDown();
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000120
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000121 is_running_ = false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000122 has_been_disposed_ = true;
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000123
124 delete call_completed_callbacks_;
125 call_completed_callbacks_ = NULL;
erik.corry@gmail.comed49e962012-04-17 11:57:53 +0000126
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000127 Sampler::TearDown();
erik.corry@gmail.comed49e962012-04-17 11:57:53 +0000128 OS::TearDown();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000129}
130
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000131
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000132static void seed_random(uint32_t* state) {
133 for (int i = 0; i < 2; ++i) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000134 if (FLAG_random_seed != 0) {
135 state[i] = FLAG_random_seed;
136 } else if (entropy_source != NULL) {
137 uint32_t val;
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000138 ScopedLock lock(entropy_mutex.Pointer());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000139 entropy_source(reinterpret_cast<unsigned char*>(&val), sizeof(uint32_t));
140 state[i] = val;
141 } else {
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000142 state[i] = random();
143 }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000144 }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000145}
146
147
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000148// Random number generator using George Marsaglia's MWC algorithm.
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000149static uint32_t random_base(uint32_t* state) {
150 // Initialize seed using the system random().
151 // No non-zero seed will ever become zero again.
152 if (state[0] == 0) seed_random(state);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000153
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000154 // Mix the bits. Never replaces state[i] with 0 if it is nonzero.
155 state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16);
156 state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16);
157
158 return (state[0] << 14) + (state[1] & 0x3FFFF);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000159}
160
161
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000162void V8::SetEntropySource(EntropySource source) {
163 entropy_source = source;
164}
165
166
ulan@chromium.org967e2702012-02-28 09:49:15 +0000167void V8::SetReturnAddressLocationResolver(
168 ReturnAddressLocationResolver resolver) {
169 StackFrame::SetReturnAddressLocationResolver(resolver);
170}
171
172
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000173// Used by JavaScript APIs
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000174uint32_t V8::Random(Context* context) {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000175 ASSERT(context->IsNativeContext());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000176 ByteArray* seed = context->random_seed();
177 return random_base(reinterpret_cast<uint32_t*>(seed->GetDataStartAddress()));
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000178}
179
180
181// Used internally by the JIT and memory allocator for security
182// purposes. So, we keep a different state to prevent informations
183// leaks that could be used in an exploit.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000184uint32_t V8::RandomPrivate(Isolate* isolate) {
185 ASSERT(isolate == Isolate::Current());
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000186 return random_base(isolate->private_random_seed());
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000187}
188
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000189
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +0000190bool V8::IdleNotification(int hint) {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000191 // Returning true tells the caller that there is no need to call
192 // IdleNotification again.
193 if (!FLAG_use_idle_notification) return true;
ager@chromium.orgadd848f2009-08-13 12:44:13 +0000194
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000195 // Tell the heap that it may want to adjust.
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +0000196 return HEAP->IdleNotification(hint);
ager@chromium.orgadd848f2009-08-13 12:44:13 +0000197}
198
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000199
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000200void V8::AddCallCompletedCallback(CallCompletedCallback callback) {
201 if (call_completed_callbacks_ == NULL) { // Lazy init.
202 call_completed_callbacks_ = new List<CallCompletedCallback>();
203 }
204 for (int i = 0; i < call_completed_callbacks_->length(); i++) {
205 if (callback == call_completed_callbacks_->at(i)) return;
206 }
207 call_completed_callbacks_->Add(callback);
208}
209
210
211void V8::RemoveCallCompletedCallback(CallCompletedCallback callback) {
212 if (call_completed_callbacks_ == NULL) return;
213 for (int i = 0; i < call_completed_callbacks_->length(); i++) {
214 if (callback == call_completed_callbacks_->at(i)) {
215 call_completed_callbacks_->Remove(i);
216 }
217 }
218}
219
220
221void V8::FireCallCompletedCallback(Isolate* isolate) {
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +0000222 bool has_call_completed_callbacks = call_completed_callbacks_ != NULL;
223 bool observer_delivery_pending =
224 FLAG_harmony_observation && isolate->observer_delivery_pending();
225 if (!has_call_completed_callbacks && !observer_delivery_pending) return;
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000226 HandleScopeImplementer* handle_scope_implementer =
227 isolate->handle_scope_implementer();
228 if (!handle_scope_implementer->CallDepthIsZero()) return;
229 // Fire callbacks. Increase call depth to prevent recursive callbacks.
230 handle_scope_implementer->IncrementCallDepth();
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +0000231 if (observer_delivery_pending) {
232 JSObject::DeliverChangeRecords(isolate);
233 }
234 if (has_call_completed_callbacks) {
235 for (int i = 0; i < call_completed_callbacks_->length(); i++) {
236 call_completed_callbacks_->at(i)();
237 }
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000238 }
239 handle_scope_implementer->DecrementCallDepth();
240}
241
242
ager@chromium.org357bf652010-04-12 11:30:10 +0000243// Use a union type to avoid type-aliasing optimizations in GCC.
244typedef union {
245 double double_value;
246 uint64_t uint64_t_value;
247} double_int_union;
248
249
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000250Object* V8::FillHeapNumberWithRandom(Object* heap_number,
251 Context* context) {
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000252 double_int_union r;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000253 uint64_t random_bits = Random(context);
ager@chromium.org357bf652010-04-12 11:30:10 +0000254 // Convert 32 random bits to 0.(32 random bits) in a double
255 // by computing:
256 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000257 static const double binary_million = 1048576.0;
258 r.double_value = binary_million;
259 r.uint64_t_value |= random_bits;
260 r.double_value -= binary_million;
ager@chromium.org357bf652010-04-12 11:30:10 +0000261
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000262 HeapNumber::cast(heap_number)->set_value(r.double_value);
ager@chromium.org357bf652010-04-12 11:30:10 +0000263 return heap_number;
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000264}
265
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000266void V8::InitializeOncePerProcessImpl() {
yangguo@chromium.org28381b42013-01-21 14:39:38 +0000267 FlagList::EnforceFlagImplications();
rossberg@chromium.orgb4b2aa62011-10-13 09:49:59 +0000268 if (FLAG_stress_compaction) {
269 FLAG_force_marking_deque_overflows = true;
270 FLAG_gc_global = true;
271 FLAG_max_new_space_size = (1 << (kPageSizeBits - 10)) * 2;
272 }
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000273 if (FLAG_trace_hydrogen) FLAG_parallel_recompilation = false;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000274
275 if (FLAG_sweeper_threads <= 0) {
276 if (FLAG_concurrent_sweeping) {
277 FLAG_sweeper_threads = SystemThreadManager::
278 NumberOfParallelSystemThreads(
279 SystemThreadManager::CONCURRENT_SWEEPING);
280 } else if (FLAG_parallel_sweeping) {
281 FLAG_sweeper_threads = SystemThreadManager::
282 NumberOfParallelSystemThreads(
283 SystemThreadManager::PARALLEL_SWEEPING);
284 }
285 if (FLAG_sweeper_threads == 0) {
286 FLAG_concurrent_sweeping = false;
287 FLAG_parallel_sweeping = false;
288 }
289 } else if (!FLAG_concurrent_sweeping && !FLAG_parallel_sweeping) {
290 FLAG_sweeper_threads = 0;
291 }
292
293 if (FLAG_parallel_marking) {
294 if (FLAG_marking_threads <= 0) {
295 FLAG_marking_threads = SystemThreadManager::
296 NumberOfParallelSystemThreads(
297 SystemThreadManager::PARALLEL_MARKING);
298 }
299 if (FLAG_marking_threads == 0) {
300 FLAG_parallel_marking = false;
301 }
302 } else {
303 FLAG_marking_threads = 0;
304 }
305
306 if (FLAG_parallel_recompilation &&
307 SystemThreadManager::NumberOfParallelSystemThreads(
308 SystemThreadManager::PARALLEL_RECOMPILATION) == 0) {
309 FLAG_parallel_recompilation = false;
310 }
311
yangguo@chromium.org28381b42013-01-21 14:39:38 +0000312 OS::SetUp();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000313 Sampler::SetUp();
yangguo@chromium.org28381b42013-01-21 14:39:38 +0000314 CPU::SetUp();
315 use_crankshaft_ = FLAG_crankshaft
316 && !Serializer::enabled()
317 && CPU::SupportsCrankshaft();
318 OS::PostSetUp();
yangguo@chromium.org28381b42013-01-21 14:39:38 +0000319 ElementsAccessor::InitializeOncePerProcess();
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000320 LOperand::SetUpCaches();
fschneider@chromium.org7d10be52012-04-10 12:30:14 +0000321 SetUpJSCallerSavedCodeData();
fschneider@chromium.org7d10be52012-04-10 12:30:14 +0000322 ExternalReference::SetUp();
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000323 Bootstrapper::InitializeOncePerProcess();
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000324}
325
326void V8::InitializeOncePerProcess() {
327 CallOnce(&init_once, &InitializeOncePerProcessImpl);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000328}
329
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000330} } // namespace v8::internal