The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / isolate.cc @ f230a1cf

History | View | Annotate | Download (83.7 KB)

1
// Copyright 2012 the V8 project authors. All rights reserved.
2
// 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 <stdlib.h>
29

    
30
#include "v8.h"
31

    
32
#include "allocation-inl.h"
33
#include "ast.h"
34
#include "bootstrapper.h"
35
#include "codegen.h"
36
#include "compilation-cache.h"
37
#include "cpu-profiler.h"
38
#include "debug.h"
39
#include "deoptimizer.h"
40
#include "heap-profiler.h"
41
#include "hydrogen.h"
42
#include "isolate-inl.h"
43
#include "lithium-allocator.h"
44
#include "log.h"
45
#include "messages.h"
46
#include "platform.h"
47
#include "regexp-stack.h"
48
#include "runtime-profiler.h"
49
#include "sampler.h"
50
#include "scopeinfo.h"
51
#include "serialize.h"
52
#include "simulator.h"
53
#include "spaces.h"
54
#include "stub-cache.h"
55
#include "sweeper-thread.h"
56
#include "utils/random-number-generator.h"
57
#include "version.h"
58
#include "vm-state-inl.h"
59

    
60

    
61
namespace v8 {
62
namespace internal {
63

    
64
Atomic32 ThreadId::highest_thread_id_ = 0;
65

    
66
int ThreadId::AllocateThreadId() {
67
  int new_id = NoBarrier_AtomicIncrement(&highest_thread_id_, 1);
68
  return new_id;
69
}
70

    
71

    
72
int ThreadId::GetCurrentThreadId() {
73
  int thread_id = Thread::GetThreadLocalInt(Isolate::thread_id_key_);
74
  if (thread_id == 0) {
75
    thread_id = AllocateThreadId();
76
    Thread::SetThreadLocalInt(Isolate::thread_id_key_, thread_id);
77
  }
78
  return thread_id;
79
}
80

    
81

    
82
ThreadLocalTop::ThreadLocalTop() {
83
  InitializeInternal();
84
  // This flag may be set using v8::V8::IgnoreOutOfMemoryException()
85
  // before an isolate is initialized. The initialize methods below do
86
  // not touch it to preserve its value.
87
  ignore_out_of_memory_ = false;
88
}
89

    
90

    
91
void ThreadLocalTop::InitializeInternal() {
92
  c_entry_fp_ = 0;
93
  handler_ = 0;
94
#ifdef USE_SIMULATOR
95
  simulator_ = NULL;
96
#endif
97
  js_entry_sp_ = NULL;
98
  external_callback_scope_ = NULL;
99
  current_vm_state_ = EXTERNAL;
100
  try_catch_handler_address_ = NULL;
101
  context_ = NULL;
102
  thread_id_ = ThreadId::Invalid();
103
  external_caught_exception_ = false;
104
  failed_access_check_callback_ = NULL;
105
  save_context_ = NULL;
106
  catcher_ = NULL;
107
  top_lookup_result_ = NULL;
108

    
109
  // These members are re-initialized later after deserialization
110
  // is complete.
111
  pending_exception_ = NULL;
112
  has_pending_message_ = false;
113
  rethrowing_message_ = false;
114
  pending_message_obj_ = NULL;
115
  pending_message_script_ = NULL;
116
  scheduled_exception_ = NULL;
117
}
118

    
119

    
120
void ThreadLocalTop::Initialize() {
121
  InitializeInternal();
122
#ifdef USE_SIMULATOR
123
  simulator_ = Simulator::current(isolate_);
124
#endif
125
  thread_id_ = ThreadId::Current();
126
}
127

    
128

    
129
v8::TryCatch* ThreadLocalTop::TryCatchHandler() {
130
  return TRY_CATCH_FROM_ADDRESS(try_catch_handler_address());
131
}
132

    
133

    
134
int SystemThreadManager::NumberOfParallelSystemThreads(
135
    ParallelSystemComponent type) {
136
  int number_of_threads = Min(CPU::NumberOfProcessorsOnline(), kMaxThreads);
137
  ASSERT(number_of_threads > 0);
138
  if (number_of_threads ==  1) {
139
    return 0;
140
  }
141
  if (type == PARALLEL_SWEEPING) {
142
    return number_of_threads;
143
  } else if (type == CONCURRENT_SWEEPING) {
144
    return number_of_threads - 1;
145
  }
146
  return 1;
147
}
148

    
149

    
150
// Create a dummy thread that will wait forever on a semaphore. The only
151
// purpose for this thread is to have some stack area to save essential data
152
// into for use by a stacks only core dump (aka minidump).
153
class PreallocatedMemoryThread: public Thread {
154
 public:
155
  char* data() {
156
    if (data_ready_semaphore_ != NULL) {
157
      // Initial access is guarded until the data has been published.
158
      data_ready_semaphore_->Wait();
159
      delete data_ready_semaphore_;
160
      data_ready_semaphore_ = NULL;
161
    }
162
    return data_;
163
  }
164

    
165
  unsigned length() {
166
    if (data_ready_semaphore_ != NULL) {
167
      // Initial access is guarded until the data has been published.
168
      data_ready_semaphore_->Wait();
169
      delete data_ready_semaphore_;
170
      data_ready_semaphore_ = NULL;
171
    }
172
    return length_;
173
  }
174

    
175
  // Stop the PreallocatedMemoryThread and release its resources.
176
  void StopThread() {
177
    keep_running_ = false;
178
    wait_for_ever_semaphore_->Signal();
179

    
180
    // Wait for the thread to terminate.
181
    Join();
182

    
183
    if (data_ready_semaphore_ != NULL) {
184
      delete data_ready_semaphore_;
185
      data_ready_semaphore_ = NULL;
186
    }
187

    
188
    delete wait_for_ever_semaphore_;
189
    wait_for_ever_semaphore_ = NULL;
190
  }
191

    
192
 protected:
193
  // When the thread starts running it will allocate a fixed number of bytes
194
  // on the stack and publish the location of this memory for others to use.
195
  void Run() {
196
    EmbeddedVector<char, 15 * 1024> local_buffer;
197

    
198
    // Initialize the buffer with a known good value.
199
    OS::StrNCpy(local_buffer, "Trace data was not generated.\n",
200
                local_buffer.length());
201

    
202
    // Publish the local buffer and signal its availability.
203
    data_ = local_buffer.start();
204
    length_ = local_buffer.length();
205
    data_ready_semaphore_->Signal();
206

    
207
    while (keep_running_) {
208
      // This thread will wait here until the end of time.
209
      wait_for_ever_semaphore_->Wait();
210
    }
211

    
212
    // Make sure we access the buffer after the wait to remove all possibility
213
    // of it being optimized away.
214
    OS::StrNCpy(local_buffer, "PreallocatedMemoryThread shutting down.\n",
215
                local_buffer.length());
216
  }
217

    
218

    
219
 private:
220
  PreallocatedMemoryThread()
221
      : Thread("v8:PreallocMem"),
222
        keep_running_(true),
223
        wait_for_ever_semaphore_(new Semaphore(0)),
224
        data_ready_semaphore_(new Semaphore(0)),
225
        data_(NULL),
226
        length_(0) {
227
  }
228

    
229
  // Used to make sure that the thread keeps looping even for spurious wakeups.
230
  bool keep_running_;
231

    
232
  // This semaphore is used by the PreallocatedMemoryThread to wait for ever.
233
  Semaphore* wait_for_ever_semaphore_;
234
  // Semaphore to signal that the data has been initialized.
235
  Semaphore* data_ready_semaphore_;
236

    
237
  // Location and size of the preallocated memory block.
238
  char* data_;
239
  unsigned length_;
240

    
241
  friend class Isolate;
242

    
243
  DISALLOW_COPY_AND_ASSIGN(PreallocatedMemoryThread);
244
};
245

    
246

    
247
void Isolate::PreallocatedMemoryThreadStart() {
248
  if (preallocated_memory_thread_ != NULL) return;
249
  preallocated_memory_thread_ = new PreallocatedMemoryThread();
250
  preallocated_memory_thread_->Start();
251
}
252

    
253

    
254
void Isolate::PreallocatedMemoryThreadStop() {
255
  if (preallocated_memory_thread_ == NULL) return;
256
  preallocated_memory_thread_->StopThread();
257
  // Done with the thread entirely.
258
  delete preallocated_memory_thread_;
259
  preallocated_memory_thread_ = NULL;
260
}
261

    
262

    
263
void Isolate::PreallocatedStorageInit(size_t size) {
264
  ASSERT(free_list_.next_ == &free_list_);
265
  ASSERT(free_list_.previous_ == &free_list_);
266
  PreallocatedStorage* free_chunk =
267
      reinterpret_cast<PreallocatedStorage*>(new char[size]);
268
  free_list_.next_ = free_list_.previous_ = free_chunk;
269
  free_chunk->next_ = free_chunk->previous_ = &free_list_;
270
  free_chunk->size_ = size - sizeof(PreallocatedStorage);
271
  preallocated_storage_preallocated_ = true;
272
}
273

    
274

    
275
void* Isolate::PreallocatedStorageNew(size_t size) {
276
  if (!preallocated_storage_preallocated_) {
277
    return FreeStoreAllocationPolicy().New(size);
278
  }
279
  ASSERT(free_list_.next_ != &free_list_);
280
  ASSERT(free_list_.previous_ != &free_list_);
281

    
282
  size = (size + kPointerSize - 1) & ~(kPointerSize - 1);
283
  // Search for exact fit.
284
  for (PreallocatedStorage* storage = free_list_.next_;
285
       storage != &free_list_;
286
       storage = storage->next_) {
287
    if (storage->size_ == size) {
288
      storage->Unlink();
289
      storage->LinkTo(&in_use_list_);
290
      return reinterpret_cast<void*>(storage + 1);
291
    }
292
  }
293
  // Search for first fit.
294
  for (PreallocatedStorage* storage = free_list_.next_;
295
       storage != &free_list_;
296
       storage = storage->next_) {
297
    if (storage->size_ >= size + sizeof(PreallocatedStorage)) {
298
      storage->Unlink();
299
      storage->LinkTo(&in_use_list_);
300
      PreallocatedStorage* left_over =
301
          reinterpret_cast<PreallocatedStorage*>(
302
              reinterpret_cast<char*>(storage + 1) + size);
303
      left_over->size_ = storage->size_ - size - sizeof(PreallocatedStorage);
304
      ASSERT(size + left_over->size_ + sizeof(PreallocatedStorage) ==
305
             storage->size_);
306
      storage->size_ = size;
307
      left_over->LinkTo(&free_list_);
308
      return reinterpret_cast<void*>(storage + 1);
309
    }
310
  }
311
  // Allocation failure.
312
  ASSERT(false);
313
  return NULL;
314
}
315

    
316

    
317
// We don't attempt to coalesce.
318
void Isolate::PreallocatedStorageDelete(void* p) {
319
  if (p == NULL) {
320
    return;
321
  }
322
  if (!preallocated_storage_preallocated_) {
323
    FreeStoreAllocationPolicy::Delete(p);
324
    return;
325
  }
326
  PreallocatedStorage* storage = reinterpret_cast<PreallocatedStorage*>(p) - 1;
327
  ASSERT(storage->next_->previous_ == storage);
328
  ASSERT(storage->previous_->next_ == storage);
329
  storage->Unlink();
330
  storage->LinkTo(&free_list_);
331
}
332

    
333
Isolate* Isolate::default_isolate_ = NULL;
334
Thread::LocalStorageKey Isolate::isolate_key_;
335
Thread::LocalStorageKey Isolate::thread_id_key_;
336
Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
337
#ifdef DEBUG
338
Thread::LocalStorageKey PerThreadAssertScopeBase::thread_local_key;
339
#endif  // DEBUG
340
Mutex Isolate::process_wide_mutex_;
341
// TODO(dcarney): Remove with default isolate.
342
enum DefaultIsolateStatus {
343
  kDefaultIsolateUninitialized,
344
  kDefaultIsolateInitialized,
345
  kDefaultIsolateCrashIfInitialized
346
};
347
static DefaultIsolateStatus default_isolate_status_
348
    = kDefaultIsolateUninitialized;
349
Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL;
350
Atomic32 Isolate::isolate_counter_ = 0;
351

    
352
Isolate::PerIsolateThreadData*
353
    Isolate::FindOrAllocatePerThreadDataForThisThread() {
354
  ThreadId thread_id = ThreadId::Current();
355
  PerIsolateThreadData* per_thread = NULL;
356
  {
357
    LockGuard<Mutex> lock_guard(&process_wide_mutex_);
358
    per_thread = thread_data_table_->Lookup(this, thread_id);
359
    if (per_thread == NULL) {
360
      per_thread = new PerIsolateThreadData(this, thread_id);
361
      thread_data_table_->Insert(per_thread);
362
    }
363
  }
364
  ASSERT(thread_data_table_->Lookup(this, thread_id) == per_thread);
365
  return per_thread;
366
}
367

    
368

    
369
Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThisThread() {
370
  ThreadId thread_id = ThreadId::Current();
371
  return FindPerThreadDataForThread(thread_id);
372
}
373

    
374

    
375
Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThread(
376
    ThreadId thread_id) {
377
  PerIsolateThreadData* per_thread = NULL;
378
  {
379
    LockGuard<Mutex> lock_guard(&process_wide_mutex_);
380
    per_thread = thread_data_table_->Lookup(this, thread_id);
381
  }
382
  return per_thread;
383
}
384

    
385

    
386
void Isolate::SetCrashIfDefaultIsolateInitialized() {
387
  LockGuard<Mutex> lock_guard(&process_wide_mutex_);
388
  CHECK(default_isolate_status_ != kDefaultIsolateInitialized);
389
  default_isolate_status_ = kDefaultIsolateCrashIfInitialized;
390
}
391

    
392

    
393
void Isolate::EnsureDefaultIsolate() {
394
  LockGuard<Mutex> lock_guard(&process_wide_mutex_);
395
  CHECK(default_isolate_status_ != kDefaultIsolateCrashIfInitialized);
396
  if (default_isolate_ == NULL) {
397
    isolate_key_ = Thread::CreateThreadLocalKey();
398
    thread_id_key_ = Thread::CreateThreadLocalKey();
399
    per_isolate_thread_data_key_ = Thread::CreateThreadLocalKey();
400
#ifdef DEBUG
401
    PerThreadAssertScopeBase::thread_local_key = Thread::CreateThreadLocalKey();
402
#endif  // DEBUG
403
    thread_data_table_ = new Isolate::ThreadDataTable();
404
    default_isolate_ = new Isolate();
405
  }
406
  // Can't use SetIsolateThreadLocals(default_isolate_, NULL) here
407
  // because a non-null thread data may be already set.
408
  if (Thread::GetThreadLocal(isolate_key_) == NULL) {
409
    Thread::SetThreadLocal(isolate_key_, default_isolate_);
410
  }
411
}
412

    
413
struct StaticInitializer {
414
  StaticInitializer() {
415
    Isolate::EnsureDefaultIsolate();
416
  }
417
} static_initializer;
418

    
419
#ifdef ENABLE_DEBUGGER_SUPPORT
420
Debugger* Isolate::GetDefaultIsolateDebugger() {
421
  EnsureDefaultIsolate();
422
  return default_isolate_->debugger();
423
}
424
#endif
425

    
426

    
427
StackGuard* Isolate::GetDefaultIsolateStackGuard() {
428
  EnsureDefaultIsolate();
429
  return default_isolate_->stack_guard();
430
}
431

    
432

    
433
void Isolate::EnterDefaultIsolate() {
434
  EnsureDefaultIsolate();
435
  ASSERT(default_isolate_ != NULL);
436

    
437
  PerIsolateThreadData* data = CurrentPerIsolateThreadData();
438
  // If not yet in default isolate - enter it.
439
  if (data == NULL || data->isolate() != default_isolate_) {
440
    default_isolate_->Enter();
441
  }
442
}
443

    
444

    
445
v8::Isolate* Isolate::GetDefaultIsolateForLocking() {
446
  EnsureDefaultIsolate();
447
  return reinterpret_cast<v8::Isolate*>(default_isolate_);
448
}
449

    
450

    
451
Address Isolate::get_address_from_id(Isolate::AddressId id) {
452
  return isolate_addresses_[id];
453
}
454

    
455

    
456
char* Isolate::Iterate(ObjectVisitor* v, char* thread_storage) {
457
  ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage);
458
  Iterate(v, thread);
459
  return thread_storage + sizeof(ThreadLocalTop);
460
}
461

    
462

    
463
void Isolate::IterateThread(ThreadVisitor* v, char* t) {
464
  ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(t);
465
  v->VisitThread(this, thread);
466
}
467

    
468

    
469
void Isolate::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
470
  // Visit the roots from the top for a given thread.
471
  Object* pending;
472
  // The pending exception can sometimes be a failure.  We can't show
473
  // that to the GC, which only understands objects.
474
  if (thread->pending_exception_->ToObject(&pending)) {
475
    v->VisitPointer(&pending);
476
    thread->pending_exception_ = pending;  // In case GC updated it.
477
  }
478
  v->VisitPointer(&(thread->pending_message_obj_));
479
  v->VisitPointer(BitCast<Object**>(&(thread->pending_message_script_)));
480
  v->VisitPointer(BitCast<Object**>(&(thread->context_)));
481
  Object* scheduled;
482
  if (thread->scheduled_exception_->ToObject(&scheduled)) {
483
    v->VisitPointer(&scheduled);
484
    thread->scheduled_exception_ = scheduled;
485
  }
486

    
487
  for (v8::TryCatch* block = thread->TryCatchHandler();
488
       block != NULL;
489
       block = TRY_CATCH_FROM_ADDRESS(block->next_)) {
490
    v->VisitPointer(BitCast<Object**>(&(block->exception_)));
491
    v->VisitPointer(BitCast<Object**>(&(block->message_obj_)));
492
    v->VisitPointer(BitCast<Object**>(&(block->message_script_)));
493
  }
494

    
495
  // Iterate over pointers on native execution stack.
496
  for (StackFrameIterator it(this, thread); !it.done(); it.Advance()) {
497
    it.frame()->Iterate(v);
498
  }
499

    
500
  // Iterate pointers in live lookup results.
501
  thread->top_lookup_result_->Iterate(v);
502
}
503

    
504

    
505
void Isolate::Iterate(ObjectVisitor* v) {
506
  ThreadLocalTop* current_t = thread_local_top();
507
  Iterate(v, current_t);
508
}
509

    
510

    
511
void Isolate::IterateDeferredHandles(ObjectVisitor* visitor) {
512
  for (DeferredHandles* deferred = deferred_handles_head_;
513
       deferred != NULL;
514
       deferred = deferred->next_) {
515
    deferred->Iterate(visitor);
516
  }
517
}
518

    
519

    
520
#ifdef DEBUG
521
bool Isolate::IsDeferredHandle(Object** handle) {
522
  // Each DeferredHandles instance keeps the handles to one job in the
523
  // concurrent recompilation queue, containing a list of blocks.  Each block
524
  // contains kHandleBlockSize handles except for the first block, which may
525
  // not be fully filled.
526
  // We iterate through all the blocks to see whether the argument handle
527
  // belongs to one of the blocks.  If so, it is deferred.
528
  for (DeferredHandles* deferred = deferred_handles_head_;
529
       deferred != NULL;
530
       deferred = deferred->next_) {
531
    List<Object**>* blocks = &deferred->blocks_;
532
    for (int i = 0; i < blocks->length(); i++) {
533
      Object** block_limit = (i == 0) ? deferred->first_block_limit_
534
                                      : blocks->at(i) + kHandleBlockSize;
535
      if (blocks->at(i) <= handle && handle < block_limit) return true;
536
    }
537
  }
538
  return false;
539
}
540
#endif  // DEBUG
541

    
542

    
543
void Isolate::RegisterTryCatchHandler(v8::TryCatch* that) {
544
  // The ARM simulator has a separate JS stack.  We therefore register
545
  // the C++ try catch handler with the simulator and get back an
546
  // address that can be used for comparisons with addresses into the
547
  // JS stack.  When running without the simulator, the address
548
  // returned will be the address of the C++ try catch handler itself.
549
  Address address = reinterpret_cast<Address>(
550
      SimulatorStack::RegisterCTryCatch(reinterpret_cast<uintptr_t>(that)));
551
  thread_local_top()->set_try_catch_handler_address(address);
552
}
553

    
554

    
555
void Isolate::UnregisterTryCatchHandler(v8::TryCatch* that) {
556
  ASSERT(thread_local_top()->TryCatchHandler() == that);
557
  thread_local_top()->set_try_catch_handler_address(
558
      reinterpret_cast<Address>(that->next_));
559
  thread_local_top()->catcher_ = NULL;
560
  SimulatorStack::UnregisterCTryCatch();
561
}
562

    
563

    
564
Handle<String> Isolate::StackTraceString() {
565
  if (stack_trace_nesting_level_ == 0) {
566
    stack_trace_nesting_level_++;
567
    HeapStringAllocator allocator;
568
    StringStream::ClearMentionedObjectCache(this);
569
    StringStream accumulator(&allocator);
570
    incomplete_message_ = &accumulator;
571
    PrintStack(&accumulator);
572
    Handle<String> stack_trace = accumulator.ToString(this);
573
    incomplete_message_ = NULL;
574
    stack_trace_nesting_level_ = 0;
575
    return stack_trace;
576
  } else if (stack_trace_nesting_level_ == 1) {
577
    stack_trace_nesting_level_++;
578
    OS::PrintError(
579
      "\n\nAttempt to print stack while printing stack (double fault)\n");
580
    OS::PrintError(
581
      "If you are lucky you may find a partial stack dump on stdout.\n\n");
582
    incomplete_message_->OutputToStdOut();
583
    return factory()->empty_string();
584
  } else {
585
    OS::Abort();
586
    // Unreachable
587
    return factory()->empty_string();
588
  }
589
}
590

    
591

    
592
void Isolate::PushStackTraceAndDie(unsigned int magic,
593
                                   Object* object,
594
                                   Map* map,
595
                                   unsigned int magic2) {
596
  const int kMaxStackTraceSize = 8192;
597
  Handle<String> trace = StackTraceString();
598
  uint8_t buffer[kMaxStackTraceSize];
599
  int length = Min(kMaxStackTraceSize - 1, trace->length());
600
  String::WriteToFlat(*trace, buffer, 0, length);
601
  buffer[length] = '\0';
602
  // TODO(dcarney): convert buffer to utf8?
603
  OS::PrintError("Stacktrace (%x-%x) %p %p: %s\n",
604
                 magic, magic2,
605
                 static_cast<void*>(object), static_cast<void*>(map),
606
                 reinterpret_cast<char*>(buffer));
607
  OS::Abort();
608
}
609

    
610

    
611
// Determines whether the given stack frame should be displayed in
612
// a stack trace.  The caller is the error constructor that asked
613
// for the stack trace to be collected.  The first time a construct
614
// call to this function is encountered it is skipped.  The seen_caller
615
// in/out parameter is used to remember if the caller has been seen
616
// yet.
617
static bool IsVisibleInStackTrace(StackFrame* raw_frame,
618
                                  Object* caller,
619
                                  bool* seen_caller) {
620
  // Only display JS frames.
621
  if (!raw_frame->is_java_script()) return false;
622
  JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
623
  JSFunction* fun = frame->function();
624
  if ((fun == caller) && !(*seen_caller)) {
625
    *seen_caller = true;
626
    return false;
627
  }
628
  // Skip all frames until we've seen the caller.
629
  if (!(*seen_caller)) return false;
630
  // Also, skip non-visible built-in functions and any call with the builtins
631
  // object as receiver, so as to not reveal either the builtins object or
632
  // an internal function.
633
  // The --builtins-in-stack-traces command line flag allows including
634
  // internal call sites in the stack trace for debugging purposes.
635
  if (!FLAG_builtins_in_stack_traces) {
636
    if (frame->receiver()->IsJSBuiltinsObject() ||
637
        (fun->IsBuiltin() && !fun->shared()->native())) {
638
      return false;
639
    }
640
  }
641
  return true;
642
}
643

    
644

    
645
Handle<JSArray> Isolate::CaptureSimpleStackTrace(Handle<JSObject> error_object,
646
                                                 Handle<Object> caller,
647
                                                 int limit) {
648
  limit = Max(limit, 0);  // Ensure that limit is not negative.
649
  int initial_size = Min(limit, 10);
650
  Handle<FixedArray> elements =
651
      factory()->NewFixedArrayWithHoles(initial_size * 4 + 1);
652

    
653
  // If the caller parameter is a function we skip frames until we're
654
  // under it before starting to collect.
655
  bool seen_caller = !caller->IsJSFunction();
656
  // First element is reserved to store the number of non-strict frames.
657
  int cursor = 1;
658
  int frames_seen = 0;
659
  int non_strict_frames = 0;
660
  bool encountered_strict_function = false;
661
  for (StackFrameIterator iter(this);
662
       !iter.done() && frames_seen < limit;
663
       iter.Advance()) {
664
    StackFrame* raw_frame = iter.frame();
665
    if (IsVisibleInStackTrace(raw_frame, *caller, &seen_caller)) {
666
      frames_seen++;
667
      JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
668
      // Set initial size to the maximum inlining level + 1 for the outermost
669
      // function.
670
      List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
671
      frame->Summarize(&frames);
672
      for (int i = frames.length() - 1; i >= 0; i--) {
673
        if (cursor + 4 > elements->length()) {
674
          int new_capacity = JSObject::NewElementsCapacity(elements->length());
675
          Handle<FixedArray> new_elements =
676
              factory()->NewFixedArrayWithHoles(new_capacity);
677
          for (int i = 0; i < cursor; i++) {
678
            new_elements->set(i, elements->get(i));
679
          }
680
          elements = new_elements;
681
        }
682
        ASSERT(cursor + 4 <= elements->length());
683

    
684
        Handle<Object> recv = frames[i].receiver();
685
        Handle<JSFunction> fun = frames[i].function();
686
        Handle<Code> code = frames[i].code();
687
        Handle<Smi> offset(Smi::FromInt(frames[i].offset()), this);
688
        // The stack trace API should not expose receivers and function
689
        // objects on frames deeper than the top-most one with a strict
690
        // mode function.  The number of non-strict frames is stored as
691
        // first element in the result array.
692
        if (!encountered_strict_function) {
693
          if (!fun->shared()->is_classic_mode()) {
694
            encountered_strict_function = true;
695
          } else {
696
            non_strict_frames++;
697
          }
698
        }
699
        elements->set(cursor++, *recv);
700
        elements->set(cursor++, *fun);
701
        elements->set(cursor++, *code);
702
        elements->set(cursor++, *offset);
703
      }
704
    }
705
  }
706
  elements->set(0, Smi::FromInt(non_strict_frames));
707
  Handle<JSArray> result = factory()->NewJSArrayWithElements(elements);
708
  result->set_length(Smi::FromInt(cursor));
709
  return result;
710
}
711

    
712

    
713
void Isolate::CaptureAndSetDetailedStackTrace(Handle<JSObject> error_object) {
714
  if (capture_stack_trace_for_uncaught_exceptions_) {
715
    // Capture stack trace for a detailed exception message.
716
    Handle<String> key = factory()->hidden_stack_trace_string();
717
    Handle<JSArray> stack_trace = CaptureCurrentStackTrace(
718
        stack_trace_for_uncaught_exceptions_frame_limit_,
719
        stack_trace_for_uncaught_exceptions_options_);
720
    JSObject::SetHiddenProperty(error_object, key, stack_trace);
721
  }
722
}
723

    
724

    
725
Handle<JSArray> Isolate::CaptureCurrentStackTrace(
726
    int frame_limit, StackTrace::StackTraceOptions options) {
727
  // Ensure no negative values.
728
  int limit = Max(frame_limit, 0);
729
  Handle<JSArray> stack_trace = factory()->NewJSArray(frame_limit);
730

    
731
  Handle<String> column_key =
732
      factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("column"));
733
  Handle<String> line_key =
734
      factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("lineNumber"));
735
  Handle<String> script_id_key =
736
      factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("scriptId"));
737
  Handle<String> script_name_key =
738
      factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("scriptName"));
739
  Handle<String> script_name_or_source_url_key =
740
      factory()->InternalizeOneByteString(
741
          STATIC_ASCII_VECTOR("scriptNameOrSourceURL"));
742
  Handle<String> function_key =
743
      factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("functionName"));
744
  Handle<String> eval_key =
745
      factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("isEval"));
746
  Handle<String> constructor_key =
747
      factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("isConstructor"));
748

    
749
  StackTraceFrameIterator it(this);
750
  int frames_seen = 0;
751
  while (!it.done() && (frames_seen < limit)) {
752
    JavaScriptFrame* frame = it.frame();
753
    // Set initial size to the maximum inlining level + 1 for the outermost
754
    // function.
755
    List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
756
    frame->Summarize(&frames);
757
    for (int i = frames.length() - 1; i >= 0 && frames_seen < limit; i--) {
758
      // Create a JSObject to hold the information for the StackFrame.
759
      Handle<JSObject> stack_frame = factory()->NewJSObject(object_function());
760

    
761
      Handle<JSFunction> fun = frames[i].function();
762
      Handle<Script> script(Script::cast(fun->shared()->script()));
763

    
764
      if (options & StackTrace::kLineNumber) {
765
        int script_line_offset = script->line_offset()->value();
766
        int position = frames[i].code()->SourcePosition(frames[i].pc());
767
        int line_number = GetScriptLineNumber(script, position);
768
        // line_number is already shifted by the script_line_offset.
769
        int relative_line_number = line_number - script_line_offset;
770
        if (options & StackTrace::kColumnOffset && relative_line_number >= 0) {
771
          Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
772
          int start = (relative_line_number == 0) ? 0 :
773
              Smi::cast(line_ends->get(relative_line_number - 1))->value() + 1;
774
          int column_offset = position - start;
775
          if (relative_line_number == 0) {
776
            // For the case where the code is on the same line as the script
777
            // tag.
778
            column_offset += script->column_offset()->value();
779
          }
780
          CHECK_NOT_EMPTY_HANDLE(
781
              this,
782
              JSObject::SetLocalPropertyIgnoreAttributes(
783
                  stack_frame, column_key,
784
                  Handle<Smi>(Smi::FromInt(column_offset + 1), this), NONE));
785
        }
786
        CHECK_NOT_EMPTY_HANDLE(
787
            this,
788
            JSObject::SetLocalPropertyIgnoreAttributes(
789
                stack_frame, line_key,
790
                Handle<Smi>(Smi::FromInt(line_number + 1), this), NONE));
791
      }
792

    
793
      if (options & StackTrace::kScriptId) {
794
        Handle<Smi> script_id(script->id(), this);
795
        CHECK_NOT_EMPTY_HANDLE(this,
796
                               JSObject::SetLocalPropertyIgnoreAttributes(
797
                                   stack_frame, script_id_key, script_id,
798
                                   NONE));
799
      }
800

    
801
      if (options & StackTrace::kScriptName) {
802
        Handle<Object> script_name(script->name(), this);
803
        CHECK_NOT_EMPTY_HANDLE(this,
804
                               JSObject::SetLocalPropertyIgnoreAttributes(
805
                                   stack_frame, script_name_key, script_name,
806
                                   NONE));
807
      }
808

    
809
      if (options & StackTrace::kScriptNameOrSourceURL) {
810
        Handle<Object> result = GetScriptNameOrSourceURL(script);
811
        CHECK_NOT_EMPTY_HANDLE(this,
812
                               JSObject::SetLocalPropertyIgnoreAttributes(
813
                                   stack_frame, script_name_or_source_url_key,
814
                                   result, NONE));
815
      }
816

    
817
      if (options & StackTrace::kFunctionName) {
818
        Handle<Object> fun_name(fun->shared()->name(), this);
819
        if (!fun_name->BooleanValue()) {
820
          fun_name = Handle<Object>(fun->shared()->inferred_name(), this);
821
        }
822
        CHECK_NOT_EMPTY_HANDLE(this,
823
                               JSObject::SetLocalPropertyIgnoreAttributes(
824
                                   stack_frame, function_key, fun_name, NONE));
825
      }
826

    
827
      if (options & StackTrace::kIsEval) {
828
        Handle<Object> is_eval =
829
            script->compilation_type() == Script::COMPILATION_TYPE_EVAL ?
830
                factory()->true_value() : factory()->false_value();
831
        CHECK_NOT_EMPTY_HANDLE(this,
832
                               JSObject::SetLocalPropertyIgnoreAttributes(
833
                                   stack_frame, eval_key, is_eval, NONE));
834
      }
835

    
836
      if (options & StackTrace::kIsConstructor) {
837
        Handle<Object> is_constructor = (frames[i].is_constructor()) ?
838
            factory()->true_value() : factory()->false_value();
839
        CHECK_NOT_EMPTY_HANDLE(this,
840
                               JSObject::SetLocalPropertyIgnoreAttributes(
841
                                   stack_frame, constructor_key,
842
                                   is_constructor, NONE));
843
      }
844

    
845
      FixedArray::cast(stack_trace->elements())->set(frames_seen, *stack_frame);
846
      frames_seen++;
847
    }
848
    it.Advance();
849
  }
850

    
851
  stack_trace->set_length(Smi::FromInt(frames_seen));
852
  return stack_trace;
853
}
854

    
855

    
856
void Isolate::PrintStack() {
857
  PrintStack(stdout);
858
}
859

    
860

    
861
void Isolate::PrintStack(FILE* out) {
862
  if (stack_trace_nesting_level_ == 0) {
863
    stack_trace_nesting_level_++;
864

    
865
    StringAllocator* allocator;
866
    if (preallocated_message_space_ == NULL) {
867
      allocator = new HeapStringAllocator();
868
    } else {
869
      allocator = preallocated_message_space_;
870
    }
871

    
872
    StringStream::ClearMentionedObjectCache(this);
873
    StringStream accumulator(allocator);
874
    incomplete_message_ = &accumulator;
875
    PrintStack(&accumulator);
876
    accumulator.OutputToFile(out);
877
    InitializeLoggingAndCounters();
878
    accumulator.Log(this);
879
    incomplete_message_ = NULL;
880
    stack_trace_nesting_level_ = 0;
881
    if (preallocated_message_space_ == NULL) {
882
      // Remove the HeapStringAllocator created above.
883
      delete allocator;
884
    }
885
  } else if (stack_trace_nesting_level_ == 1) {
886
    stack_trace_nesting_level_++;
887
    OS::PrintError(
888
      "\n\nAttempt to print stack while printing stack (double fault)\n");
889
    OS::PrintError(
890
      "If you are lucky you may find a partial stack dump on stdout.\n\n");
891
    incomplete_message_->OutputToFile(out);
892
  }
893
}
894

    
895

    
896
static void PrintFrames(Isolate* isolate,
897
                        StringStream* accumulator,
898
                        StackFrame::PrintMode mode) {
899
  StackFrameIterator it(isolate);
900
  for (int i = 0; !it.done(); it.Advance()) {
901
    it.frame()->Print(accumulator, mode, i++);
902
  }
903
}
904

    
905

    
906
void Isolate::PrintStack(StringStream* accumulator) {
907
  if (!IsInitialized()) {
908
    accumulator->Add(
909
        "\n==== JS stack trace is not available =======================\n\n");
910
    accumulator->Add(
911
        "\n==== Isolate for the thread is not initialized =============\n\n");
912
    return;
913
  }
914
  // The MentionedObjectCache is not GC-proof at the moment.
915
  DisallowHeapAllocation no_gc;
916
  ASSERT(StringStream::IsMentionedObjectCacheClear(this));
917

    
918
  // Avoid printing anything if there are no frames.
919
  if (c_entry_fp(thread_local_top()) == 0) return;
920

    
921
  accumulator->Add(
922
      "\n==== JS stack trace =========================================\n\n");
923
  PrintFrames(this, accumulator, StackFrame::OVERVIEW);
924

    
925
  accumulator->Add(
926
      "\n==== Details ================================================\n\n");
927
  PrintFrames(this, accumulator, StackFrame::DETAILS);
928

    
929
  accumulator->PrintMentionedObjectCache(this);
930
  accumulator->Add("=====================\n\n");
931
}
932

    
933

    
934
void Isolate::SetFailedAccessCheckCallback(
935
    v8::FailedAccessCheckCallback callback) {
936
  thread_local_top()->failed_access_check_callback_ = callback;
937
}
938

    
939

    
940
void Isolate::ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type) {
941
  if (!thread_local_top()->failed_access_check_callback_) return;
942

    
943
  ASSERT(receiver->IsAccessCheckNeeded());
944
  ASSERT(context());
945

    
946
  // Get the data object from access check info.
947
  JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
948
  if (!constructor->shared()->IsApiFunction()) return;
949
  Object* data_obj =
950
      constructor->shared()->get_api_func_data()->access_check_info();
951
  if (data_obj == heap_.undefined_value()) return;
952

    
953
  HandleScope scope(this);
954
  Handle<JSObject> receiver_handle(receiver);
955
  Handle<Object> data(AccessCheckInfo::cast(data_obj)->data(), this);
956
  { VMState<EXTERNAL> state(this);
957
    thread_local_top()->failed_access_check_callback_(
958
      v8::Utils::ToLocal(receiver_handle),
959
      type,
960
      v8::Utils::ToLocal(data));
961
  }
962
}
963

    
964

    
965
enum MayAccessDecision {
966
  YES, NO, UNKNOWN
967
};
968

    
969

    
970
static MayAccessDecision MayAccessPreCheck(Isolate* isolate,
971
                                           JSObject* receiver,
972
                                           v8::AccessType type) {
973
  // During bootstrapping, callback functions are not enabled yet.
974
  if (isolate->bootstrapper()->IsActive()) return YES;
975

    
976
  if (receiver->IsJSGlobalProxy()) {
977
    Object* receiver_context = JSGlobalProxy::cast(receiver)->native_context();
978
    if (!receiver_context->IsContext()) return NO;
979

    
980
    // Get the native context of current top context.
981
    // avoid using Isolate::native_context() because it uses Handle.
982
    Context* native_context =
983
        isolate->context()->global_object()->native_context();
984
    if (receiver_context == native_context) return YES;
985

    
986
    if (Context::cast(receiver_context)->security_token() ==
987
        native_context->security_token())
988
      return YES;
989
  }
990

    
991
  return UNKNOWN;
992
}
993

    
994

    
995
bool Isolate::MayNamedAccess(JSObject* receiver, Object* key,
996
                             v8::AccessType type) {
997
  ASSERT(receiver->IsAccessCheckNeeded());
998

    
999
  // The callers of this method are not expecting a GC.
1000
  DisallowHeapAllocation no_gc;
1001

    
1002
  // Skip checks for hidden properties access.  Note, we do not
1003
  // require existence of a context in this case.
1004
  if (key == heap_.hidden_string()) return true;
1005

    
1006
  // Check for compatibility between the security tokens in the
1007
  // current lexical context and the accessed object.
1008
  ASSERT(context());
1009

    
1010
  MayAccessDecision decision = MayAccessPreCheck(this, receiver, type);
1011
  if (decision != UNKNOWN) return decision == YES;
1012

    
1013
  // Get named access check callback
1014
  JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
1015
  if (!constructor->shared()->IsApiFunction()) return false;
1016

    
1017
  Object* data_obj =
1018
     constructor->shared()->get_api_func_data()->access_check_info();
1019
  if (data_obj == heap_.undefined_value()) return false;
1020

    
1021
  Object* fun_obj = AccessCheckInfo::cast(data_obj)->named_callback();
1022
  v8::NamedSecurityCallback callback =
1023
      v8::ToCData<v8::NamedSecurityCallback>(fun_obj);
1024

    
1025
  if (!callback) return false;
1026

    
1027
  HandleScope scope(this);
1028
  Handle<JSObject> receiver_handle(receiver, this);
1029
  Handle<Object> key_handle(key, this);
1030
  Handle<Object> data(AccessCheckInfo::cast(data_obj)->data(), this);
1031
  LOG(this, ApiNamedSecurityCheck(key));
1032
  bool result = false;
1033
  {
1034
    // Leaving JavaScript.
1035
    VMState<EXTERNAL> state(this);
1036
    result = callback(v8::Utils::ToLocal(receiver_handle),
1037
                      v8::Utils::ToLocal(key_handle),
1038
                      type,
1039
                      v8::Utils::ToLocal(data));
1040
  }
1041
  return result;
1042
}
1043

    
1044

    
1045
bool Isolate::MayIndexedAccess(JSObject* receiver,
1046
                               uint32_t index,
1047
                               v8::AccessType type) {
1048
  ASSERT(receiver->IsAccessCheckNeeded());
1049
  // Check for compatibility between the security tokens in the
1050
  // current lexical context and the accessed object.
1051
  ASSERT(context());
1052

    
1053
  MayAccessDecision decision = MayAccessPreCheck(this, receiver, type);
1054
  if (decision != UNKNOWN) return decision == YES;
1055

    
1056
  // Get indexed access check callback
1057
  JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
1058
  if (!constructor->shared()->IsApiFunction()) return false;
1059

    
1060
  Object* data_obj =
1061
      constructor->shared()->get_api_func_data()->access_check_info();
1062
  if (data_obj == heap_.undefined_value()) return false;
1063

    
1064
  Object* fun_obj = AccessCheckInfo::cast(data_obj)->indexed_callback();
1065
  v8::IndexedSecurityCallback callback =
1066
      v8::ToCData<v8::IndexedSecurityCallback>(fun_obj);
1067

    
1068
  if (!callback) return false;
1069

    
1070
  HandleScope scope(this);
1071
  Handle<JSObject> receiver_handle(receiver, this);
1072
  Handle<Object> data(AccessCheckInfo::cast(data_obj)->data(), this);
1073
  LOG(this, ApiIndexedSecurityCheck(index));
1074
  bool result = false;
1075
  {
1076
    // Leaving JavaScript.
1077
    VMState<EXTERNAL> state(this);
1078
    result = callback(v8::Utils::ToLocal(receiver_handle),
1079
                      index,
1080
                      type,
1081
                      v8::Utils::ToLocal(data));
1082
  }
1083
  return result;
1084
}
1085

    
1086

    
1087
const char* const Isolate::kStackOverflowMessage =
1088
  "Uncaught RangeError: Maximum call stack size exceeded";
1089

    
1090

    
1091
Failure* Isolate::StackOverflow() {
1092
  HandleScope scope(this);
1093
  // At this point we cannot create an Error object using its javascript
1094
  // constructor.  Instead, we copy the pre-constructed boilerplate and
1095
  // attach the stack trace as a hidden property.
1096
  Handle<String> key = factory()->stack_overflow_string();
1097
  Handle<JSObject> boilerplate =
1098
      Handle<JSObject>::cast(GetProperty(this, js_builtins_object(), key));
1099
  Handle<JSObject> exception = JSObject::Copy(boilerplate);
1100
  DoThrow(*exception, NULL);
1101

    
1102
  // Get stack trace limit.
1103
  Handle<Object> error = GetProperty(js_builtins_object(), "$Error");
1104
  if (!error->IsJSObject()) return Failure::Exception();
1105
  Handle<Object> stack_trace_limit =
1106
      GetProperty(Handle<JSObject>::cast(error), "stackTraceLimit");
1107
  if (!stack_trace_limit->IsNumber()) return Failure::Exception();
1108
  double dlimit = stack_trace_limit->Number();
1109
  int limit = std::isnan(dlimit) ? 0 : static_cast<int>(dlimit);
1110

    
1111
  Handle<JSArray> stack_trace = CaptureSimpleStackTrace(
1112
      exception, factory()->undefined_value(), limit);
1113
  JSObject::SetHiddenProperty(exception,
1114
                              factory()->hidden_stack_trace_string(),
1115
                              stack_trace);
1116
  return Failure::Exception();
1117
}
1118

    
1119

    
1120
Failure* Isolate::TerminateExecution() {
1121
  DoThrow(heap_.termination_exception(), NULL);
1122
  return Failure::Exception();
1123
}
1124

    
1125

    
1126
void Isolate::CancelTerminateExecution() {
1127
  if (try_catch_handler()) {
1128
    try_catch_handler()->has_terminated_ = false;
1129
  }
1130
  if (has_pending_exception() &&
1131
      pending_exception() == heap_.termination_exception()) {
1132
    thread_local_top()->external_caught_exception_ = false;
1133
    clear_pending_exception();
1134
  }
1135
  if (has_scheduled_exception() &&
1136
      scheduled_exception() == heap_.termination_exception()) {
1137
    thread_local_top()->external_caught_exception_ = false;
1138
    clear_scheduled_exception();
1139
  }
1140
}
1141

    
1142

    
1143
Failure* Isolate::Throw(Object* exception, MessageLocation* location) {
1144
  DoThrow(exception, location);
1145
  return Failure::Exception();
1146
}
1147

    
1148

    
1149
Failure* Isolate::ReThrow(MaybeObject* exception) {
1150
  bool can_be_caught_externally = false;
1151
  bool catchable_by_javascript = is_catchable_by_javascript(exception);
1152
  ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
1153

    
1154
  thread_local_top()->catcher_ = can_be_caught_externally ?
1155
      try_catch_handler() : NULL;
1156

    
1157
  // Set the exception being re-thrown.
1158
  set_pending_exception(exception);
1159
  if (exception->IsFailure()) return exception->ToFailureUnchecked();
1160
  return Failure::Exception();
1161
}
1162

    
1163

    
1164
Failure* Isolate::ThrowIllegalOperation() {
1165
  return Throw(heap_.illegal_access_string());
1166
}
1167

    
1168

    
1169
void Isolate::ScheduleThrow(Object* exception) {
1170
  // When scheduling a throw we first throw the exception to get the
1171
  // error reporting if it is uncaught before rescheduling it.
1172
  Throw(exception);
1173
  PropagatePendingExceptionToExternalTryCatch();
1174
  if (has_pending_exception()) {
1175
    thread_local_top()->scheduled_exception_ = pending_exception();
1176
    thread_local_top()->external_caught_exception_ = false;
1177
    clear_pending_exception();
1178
  }
1179
}
1180

    
1181

    
1182
void Isolate::RestorePendingMessageFromTryCatch(v8::TryCatch* handler) {
1183
  ASSERT(handler == try_catch_handler());
1184
  ASSERT(handler->HasCaught());
1185
  ASSERT(handler->rethrow_);
1186
  ASSERT(handler->capture_message_);
1187
  Object* message = reinterpret_cast<Object*>(handler->message_obj_);
1188
  Object* script = reinterpret_cast<Object*>(handler->message_script_);
1189
  ASSERT(message->IsJSMessageObject() || message->IsTheHole());
1190
  ASSERT(script->IsScript() || script->IsTheHole());
1191
  thread_local_top()->pending_message_obj_ = message;
1192
  thread_local_top()->pending_message_script_ = script;
1193
  thread_local_top()->pending_message_start_pos_ = handler->message_start_pos_;
1194
  thread_local_top()->pending_message_end_pos_ = handler->message_end_pos_;
1195
}
1196

    
1197

    
1198
Failure* Isolate::PromoteScheduledException() {
1199
  MaybeObject* thrown = scheduled_exception();
1200
  clear_scheduled_exception();
1201
  // Re-throw the exception to avoid getting repeated error reporting.
1202
  return ReThrow(thrown);
1203
}
1204

    
1205

    
1206
void Isolate::PrintCurrentStackTrace(FILE* out) {
1207
  StackTraceFrameIterator it(this);
1208
  while (!it.done()) {
1209
    HandleScope scope(this);
1210
    // Find code position if recorded in relocation info.
1211
    JavaScriptFrame* frame = it.frame();
1212
    int pos = frame->LookupCode()->SourcePosition(frame->pc());
1213
    Handle<Object> pos_obj(Smi::FromInt(pos), this);
1214
    // Fetch function and receiver.
1215
    Handle<JSFunction> fun(frame->function());
1216
    Handle<Object> recv(frame->receiver(), this);
1217
    // Advance to the next JavaScript frame and determine if the
1218
    // current frame is the top-level frame.
1219
    it.Advance();
1220
    Handle<Object> is_top_level = it.done()
1221
        ? factory()->true_value()
1222
        : factory()->false_value();
1223
    // Generate and print stack trace line.
1224
    Handle<String> line =
1225
        Execution::GetStackTraceLine(recv, fun, pos_obj, is_top_level);
1226
    if (line->length() > 0) {
1227
      line->PrintOn(out);
1228
      PrintF(out, "\n");
1229
    }
1230
  }
1231
}
1232

    
1233

    
1234
void Isolate::ComputeLocation(MessageLocation* target) {
1235
  *target = MessageLocation(Handle<Script>(heap_.empty_script()), -1, -1);
1236
  StackTraceFrameIterator it(this);
1237
  if (!it.done()) {
1238
    JavaScriptFrame* frame = it.frame();
1239
    JSFunction* fun = frame->function();
1240
    Object* script = fun->shared()->script();
1241
    if (script->IsScript() &&
1242
        !(Script::cast(script)->source()->IsUndefined())) {
1243
      int pos = frame->LookupCode()->SourcePosition(frame->pc());
1244
      // Compute the location from the function and the reloc info.
1245
      Handle<Script> casted_script(Script::cast(script));
1246
      *target = MessageLocation(casted_script, pos, pos + 1);
1247
    }
1248
  }
1249
}
1250

    
1251

    
1252
bool Isolate::ShouldReportException(bool* can_be_caught_externally,
1253
                                    bool catchable_by_javascript) {
1254
  // Find the top-most try-catch handler.
1255
  StackHandler* handler =
1256
      StackHandler::FromAddress(Isolate::handler(thread_local_top()));
1257
  while (handler != NULL && !handler->is_catch()) {
1258
    handler = handler->next();
1259
  }
1260

    
1261
  // Get the address of the external handler so we can compare the address to
1262
  // determine which one is closer to the top of the stack.
1263
  Address external_handler_address =
1264
      thread_local_top()->try_catch_handler_address();
1265

    
1266
  // The exception has been externally caught if and only if there is
1267
  // an external handler which is on top of the top-most try-catch
1268
  // handler.
1269
  *can_be_caught_externally = external_handler_address != NULL &&
1270
      (handler == NULL || handler->address() > external_handler_address ||
1271
       !catchable_by_javascript);
1272

    
1273
  if (*can_be_caught_externally) {
1274
    // Only report the exception if the external handler is verbose.
1275
    return try_catch_handler()->is_verbose_;
1276
  } else {
1277
    // Report the exception if it isn't caught by JavaScript code.
1278
    return handler == NULL;
1279
  }
1280
}
1281

    
1282

    
1283
bool Isolate::IsErrorObject(Handle<Object> obj) {
1284
  if (!obj->IsJSObject()) return false;
1285

    
1286
  String* error_key =
1287
      *(factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("$Error")));
1288
  Object* error_constructor =
1289
      js_builtins_object()->GetPropertyNoExceptionThrown(error_key);
1290

    
1291
  for (Object* prototype = *obj; !prototype->IsNull();
1292
       prototype = prototype->GetPrototype(this)) {
1293
    if (!prototype->IsJSObject()) return false;
1294
    if (JSObject::cast(prototype)->map()->constructor() == error_constructor) {
1295
      return true;
1296
    }
1297
  }
1298
  return false;
1299
}
1300

    
1301
static int fatal_exception_depth = 0;
1302

    
1303
void Isolate::DoThrow(Object* exception, MessageLocation* location) {
1304
  ASSERT(!has_pending_exception());
1305

    
1306
  HandleScope scope(this);
1307
  Handle<Object> exception_handle(exception, this);
1308

    
1309
  // Determine reporting and whether the exception is caught externally.
1310
  bool catchable_by_javascript = is_catchable_by_javascript(exception);
1311
  bool can_be_caught_externally = false;
1312
  bool should_report_exception =
1313
      ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
1314
  bool report_exception = catchable_by_javascript && should_report_exception;
1315
  bool try_catch_needs_message =
1316
      can_be_caught_externally && try_catch_handler()->capture_message_ &&
1317
      !thread_local_top()->rethrowing_message_;
1318
  bool bootstrapping = bootstrapper()->IsActive();
1319

    
1320
  thread_local_top()->rethrowing_message_ = false;
1321

    
1322
#ifdef ENABLE_DEBUGGER_SUPPORT
1323
  // Notify debugger of exception.
1324
  if (catchable_by_javascript) {
1325
    debugger_->OnException(exception_handle, report_exception);
1326
  }
1327
#endif
1328

    
1329
  // Generate the message if required.
1330
  if (report_exception || try_catch_needs_message) {
1331
    MessageLocation potential_computed_location;
1332
    if (location == NULL) {
1333
      // If no location was specified we use a computed one instead.
1334
      ComputeLocation(&potential_computed_location);
1335
      location = &potential_computed_location;
1336
    }
1337
    // It's not safe to try to make message objects or collect stack traces
1338
    // while the bootstrapper is active since the infrastructure may not have
1339
    // been properly initialized.
1340
    if (!bootstrapping) {
1341
      Handle<String> stack_trace;
1342
      if (FLAG_trace_exception) stack_trace = StackTraceString();
1343
      Handle<JSArray> stack_trace_object;
1344
      if (capture_stack_trace_for_uncaught_exceptions_) {
1345
        if (IsErrorObject(exception_handle)) {
1346
          // We fetch the stack trace that corresponds to this error object.
1347
          String* key = heap()->hidden_stack_trace_string();
1348
          Object* stack_property =
1349
              JSObject::cast(*exception_handle)->GetHiddenProperty(key);
1350
          // Property lookup may have failed.  In this case it's probably not
1351
          // a valid Error object.
1352
          if (stack_property->IsJSArray()) {
1353
            stack_trace_object = Handle<JSArray>(JSArray::cast(stack_property));
1354
          }
1355
        }
1356
        if (stack_trace_object.is_null()) {
1357
          // Not an error object, we capture at throw site.
1358
          stack_trace_object = CaptureCurrentStackTrace(
1359
              stack_trace_for_uncaught_exceptions_frame_limit_,
1360
              stack_trace_for_uncaught_exceptions_options_);
1361
        }
1362
      }
1363

    
1364
      Handle<Object> exception_arg = exception_handle;
1365
      // If the exception argument is a custom object, turn it into a string
1366
      // before throwing as uncaught exception.  Note that the pending
1367
      // exception object to be set later must not be turned into a string.
1368
      if (exception_arg->IsJSObject() && !IsErrorObject(exception_arg)) {
1369
        bool failed = false;
1370
        exception_arg =
1371
            Execution::ToDetailString(this, exception_arg, &failed);
1372
        if (failed) {
1373
          exception_arg = factory()->InternalizeOneByteString(
1374
              STATIC_ASCII_VECTOR("exception"));
1375
        }
1376
      }
1377
      Handle<Object> message_obj = MessageHandler::MakeMessageObject(
1378
          this,
1379
          "uncaught_exception",
1380
          location,
1381
          HandleVector<Object>(&exception_arg, 1),
1382
          stack_trace,
1383
          stack_trace_object);
1384
      thread_local_top()->pending_message_obj_ = *message_obj;
1385
      if (location != NULL) {
1386
        thread_local_top()->pending_message_script_ = *location->script();
1387
        thread_local_top()->pending_message_start_pos_ = location->start_pos();
1388
        thread_local_top()->pending_message_end_pos_ = location->end_pos();
1389
      }
1390

    
1391
      // If the abort-on-uncaught-exception flag is specified, abort on any
1392
      // exception not caught by JavaScript, even when an external handler is
1393
      // present.  This flag is intended for use by JavaScript developers, so
1394
      // print a user-friendly stack trace (not an internal one).
1395
      if (fatal_exception_depth == 0 &&
1396
          FLAG_abort_on_uncaught_exception &&
1397
          (report_exception || can_be_caught_externally)) {
1398
        fatal_exception_depth++;
1399
        PrintF(stderr,
1400
               "%s\n\nFROM\n",
1401
               *MessageHandler::GetLocalizedMessage(this, message_obj));
1402
        PrintCurrentStackTrace(stderr);
1403
        OS::Abort();
1404
      }
1405
    } else if (location != NULL && !location->script().is_null()) {
1406
      // We are bootstrapping and caught an error where the location is set
1407
      // and we have a script for the location.
1408
      // In this case we could have an extension (or an internal error
1409
      // somewhere) and we print out the line number at which the error occured
1410
      // to the console for easier debugging.
1411
      int line_number = GetScriptLineNumberSafe(location->script(),
1412
                                                location->start_pos());
1413
      if (exception->IsString() && location->script()->name()->IsString()) {
1414
        OS::PrintError(
1415
            "Extension or internal compilation error: %s in %s at line %d.\n",
1416
            *String::cast(exception)->ToCString(),
1417
            *String::cast(location->script()->name())->ToCString(),
1418
            line_number + 1);
1419
      } else if (location->script()->name()->IsString()) {
1420
        OS::PrintError(
1421
            "Extension or internal compilation error in %s at line %d.\n",
1422
            *String::cast(location->script()->name())->ToCString(),
1423
            line_number + 1);
1424
      } else {
1425
        OS::PrintError("Extension or internal compilation error.\n");
1426
      }
1427
    }
1428
  }
1429

    
1430
  // Save the message for reporting if the the exception remains uncaught.
1431
  thread_local_top()->has_pending_message_ = report_exception;
1432

    
1433
  // Do not forget to clean catcher_ if currently thrown exception cannot
1434
  // be caught.  If necessary, ReThrow will update the catcher.
1435
  thread_local_top()->catcher_ = can_be_caught_externally ?
1436
      try_catch_handler() : NULL;
1437

    
1438
  set_pending_exception(*exception_handle);
1439
}
1440

    
1441

    
1442
bool Isolate::IsExternallyCaught() {
1443
  ASSERT(has_pending_exception());
1444

    
1445
  if ((thread_local_top()->catcher_ == NULL) ||
1446
      (try_catch_handler() != thread_local_top()->catcher_)) {
1447
    // When throwing the exception, we found no v8::TryCatch
1448
    // which should care about this exception.
1449
    return false;
1450
  }
1451

    
1452
  if (!is_catchable_by_javascript(pending_exception())) {
1453
    return true;
1454
  }
1455

    
1456
  // Get the address of the external handler so we can compare the address to
1457
  // determine which one is closer to the top of the stack.
1458
  Address external_handler_address =
1459
      thread_local_top()->try_catch_handler_address();
1460
  ASSERT(external_handler_address != NULL);
1461

    
1462
  // The exception has been externally caught if and only if there is
1463
  // an external handler which is on top of the top-most try-finally
1464
  // handler.
1465
  // There should be no try-catch blocks as they would prohibit us from
1466
  // finding external catcher in the first place (see catcher_ check above).
1467
  //
1468
  // Note, that finally clause would rethrow an exception unless it's
1469
  // aborted by jumps in control flow like return, break, etc. and we'll
1470
  // have another chances to set proper v8::TryCatch.
1471
  StackHandler* handler =
1472
      StackHandler::FromAddress(Isolate::handler(thread_local_top()));
1473
  while (handler != NULL && handler->address() < external_handler_address) {
1474
    ASSERT(!handler->is_catch());
1475
    if (handler->is_finally()) return false;
1476

    
1477
    handler = handler->next();
1478
  }
1479

    
1480
  return true;
1481
}
1482

    
1483

    
1484
void Isolate::ReportPendingMessages() {
1485
  ASSERT(has_pending_exception());
1486
  PropagatePendingExceptionToExternalTryCatch();
1487

    
1488
  // If the pending exception is OutOfMemoryException set out_of_memory in
1489
  // the native context.  Note: We have to mark the native context here
1490
  // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to
1491
  // set it.
1492
  HandleScope scope(this);
1493
  if (thread_local_top_.pending_exception_->IsOutOfMemory()) {
1494
    context()->mark_out_of_memory();
1495
  } else if (thread_local_top_.pending_exception_ ==
1496
             heap()->termination_exception()) {
1497
    // Do nothing: if needed, the exception has been already propagated to
1498
    // v8::TryCatch.
1499
  } else {
1500
    if (thread_local_top_.has_pending_message_) {
1501
      thread_local_top_.has_pending_message_ = false;
1502
      if (!thread_local_top_.pending_message_obj_->IsTheHole()) {
1503
        HandleScope scope(this);
1504
        Handle<Object> message_obj(thread_local_top_.pending_message_obj_,
1505
                                   this);
1506
        if (!thread_local_top_.pending_message_script_->IsTheHole()) {
1507
          Handle<Script> script(
1508
              Script::cast(thread_local_top_.pending_message_script_));
1509
          int start_pos = thread_local_top_.pending_message_start_pos_;
1510
          int end_pos = thread_local_top_.pending_message_end_pos_;
1511
          MessageLocation location(script, start_pos, end_pos);
1512
          MessageHandler::ReportMessage(this, &location, message_obj);
1513
        } else {
1514
          MessageHandler::ReportMessage(this, NULL, message_obj);
1515
        }
1516
      }
1517
    }
1518
  }
1519
  clear_pending_message();
1520
}
1521

    
1522

    
1523
MessageLocation Isolate::GetMessageLocation() {
1524
  ASSERT(has_pending_exception());
1525

    
1526
  if (!thread_local_top_.pending_exception_->IsOutOfMemory() &&
1527
      thread_local_top_.pending_exception_ != heap()->termination_exception() &&
1528
      thread_local_top_.has_pending_message_ &&
1529
      !thread_local_top_.pending_message_obj_->IsTheHole() &&
1530
      !thread_local_top_.pending_message_obj_->IsTheHole()) {
1531
    Handle<Script> script(
1532
        Script::cast(thread_local_top_.pending_message_script_));
1533
    int start_pos = thread_local_top_.pending_message_start_pos_;
1534
    int end_pos = thread_local_top_.pending_message_end_pos_;
1535
    return MessageLocation(script, start_pos, end_pos);
1536
  }
1537

    
1538
  return MessageLocation();
1539
}
1540

    
1541

    
1542
void Isolate::TraceException(bool flag) {
1543
  FLAG_trace_exception = flag;  // TODO(isolates): This is an unfortunate use.
1544
}
1545

    
1546

    
1547
bool Isolate::OptionalRescheduleException(bool is_bottom_call) {
1548
  ASSERT(has_pending_exception());
1549
  PropagatePendingExceptionToExternalTryCatch();
1550

    
1551
  // Always reschedule out of memory exceptions.
1552
  if (!is_out_of_memory()) {
1553
    bool is_termination_exception =
1554
        pending_exception() == heap_.termination_exception();
1555

    
1556
    // Do not reschedule the exception if this is the bottom call.
1557
    bool clear_exception = is_bottom_call;
1558

    
1559
    if (is_termination_exception) {
1560
      if (is_bottom_call) {
1561
        thread_local_top()->external_caught_exception_ = false;
1562
        clear_pending_exception();
1563
        return false;
1564
      }
1565
    } else if (thread_local_top()->external_caught_exception_) {
1566
      // If the exception is externally caught, clear it if there are no
1567
      // JavaScript frames on the way to the C++ frame that has the
1568
      // external handler.
1569
      ASSERT(thread_local_top()->try_catch_handler_address() != NULL);
1570
      Address external_handler_address =
1571
          thread_local_top()->try_catch_handler_address();
1572
      JavaScriptFrameIterator it(this);
1573
      if (it.done() || (it.frame()->sp() > external_handler_address)) {
1574
        clear_exception = true;
1575
      }
1576
    }
1577

    
1578
    // Clear the exception if needed.
1579
    if (clear_exception) {
1580
      thread_local_top()->external_caught_exception_ = false;
1581
      clear_pending_exception();
1582
      return false;
1583
    }
1584
  }
1585

    
1586
  // Reschedule the exception.
1587
  thread_local_top()->scheduled_exception_ = pending_exception();
1588
  clear_pending_exception();
1589
  return true;
1590
}
1591

    
1592

    
1593
void Isolate::SetCaptureStackTraceForUncaughtExceptions(
1594
      bool capture,
1595
      int frame_limit,
1596
      StackTrace::StackTraceOptions options) {
1597
  capture_stack_trace_for_uncaught_exceptions_ = capture;
1598
  stack_trace_for_uncaught_exceptions_frame_limit_ = frame_limit;
1599
  stack_trace_for_uncaught_exceptions_options_ = options;
1600
}
1601

    
1602

    
1603
bool Isolate::is_out_of_memory() {
1604
  if (has_pending_exception()) {
1605
    MaybeObject* e = pending_exception();
1606
    if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) {
1607
      return true;
1608
    }
1609
  }
1610
  if (has_scheduled_exception()) {
1611
    MaybeObject* e = scheduled_exception();
1612
    if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) {
1613
      return true;
1614
    }
1615
  }
1616
  return false;
1617
}
1618

    
1619

    
1620
Handle<Context> Isolate::native_context() {
1621
  return Handle<Context>(context()->global_object()->native_context());
1622
}
1623

    
1624

    
1625
Handle<Context> Isolate::global_context() {
1626
  return Handle<Context>(context()->global_object()->global_context());
1627
}
1628

    
1629

    
1630
Handle<Context> Isolate::GetCallingNativeContext() {
1631
  JavaScriptFrameIterator it(this);
1632
#ifdef ENABLE_DEBUGGER_SUPPORT
1633
  if (debug_->InDebugger()) {
1634
    while (!it.done()) {
1635
      JavaScriptFrame* frame = it.frame();
1636
      Context* context = Context::cast(frame->context());
1637
      if (context->native_context() == *debug_->debug_context()) {
1638
        it.Advance();
1639
      } else {
1640
        break;
1641
      }
1642
    }
1643
  }
1644
#endif  // ENABLE_DEBUGGER_SUPPORT
1645
  if (it.done()) return Handle<Context>::null();
1646
  JavaScriptFrame* frame = it.frame();
1647
  Context* context = Context::cast(frame->context());
1648
  return Handle<Context>(context->native_context());
1649
}
1650

    
1651

    
1652
char* Isolate::ArchiveThread(char* to) {
1653
  OS::MemCopy(to, reinterpret_cast<char*>(thread_local_top()),
1654
              sizeof(ThreadLocalTop));
1655
  InitializeThreadLocal();
1656
  clear_pending_exception();
1657
  clear_pending_message();
1658
  clear_scheduled_exception();
1659
  return to + sizeof(ThreadLocalTop);
1660
}
1661

    
1662

    
1663
char* Isolate::RestoreThread(char* from) {
1664
  OS::MemCopy(reinterpret_cast<char*>(thread_local_top()), from,
1665
              sizeof(ThreadLocalTop));
1666
  // This might be just paranoia, but it seems to be needed in case a
1667
  // thread_local_top_ is restored on a separate OS thread.
1668
#ifdef USE_SIMULATOR
1669
  thread_local_top()->simulator_ = Simulator::current(this);
1670
#endif
1671
  ASSERT(context() == NULL || context()->IsContext());
1672
  return from + sizeof(ThreadLocalTop);
1673
}
1674

    
1675

    
1676
Isolate::ThreadDataTable::ThreadDataTable()
1677
    : list_(NULL) {
1678
}
1679

    
1680

    
1681
Isolate::ThreadDataTable::~ThreadDataTable() {
1682
  // TODO(svenpanne) The assertion below would fire if an embedder does not
1683
  // cleanly dispose all Isolates before disposing v8, so we are conservative
1684
  // and leave it out for now.
1685
  // ASSERT_EQ(NULL, list_);
1686
}
1687

    
1688

    
1689
Isolate::PerIsolateThreadData*
1690
    Isolate::ThreadDataTable::Lookup(Isolate* isolate,
1691
                                     ThreadId thread_id) {
1692
  for (PerIsolateThreadData* data = list_; data != NULL; data = data->next_) {
1693
    if (data->Matches(isolate, thread_id)) return data;
1694
  }
1695
  return NULL;
1696
}
1697

    
1698

    
1699
void Isolate::ThreadDataTable::Insert(Isolate::PerIsolateThreadData* data) {
1700
  if (list_ != NULL) list_->prev_ = data;
1701
  data->next_ = list_;
1702
  list_ = data;
1703
}
1704

    
1705

    
1706
void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) {
1707
  if (list_ == data) list_ = data->next_;
1708
  if (data->next_ != NULL) data->next_->prev_ = data->prev_;
1709
  if (data->prev_ != NULL) data->prev_->next_ = data->next_;
1710
  delete data;
1711
}
1712

    
1713

    
1714
void Isolate::ThreadDataTable::RemoveAllThreads(Isolate* isolate) {
1715
  PerIsolateThreadData* data = list_;
1716
  while (data != NULL) {
1717
    PerIsolateThreadData* next = data->next_;
1718
    if (data->isolate() == isolate) Remove(data);
1719
    data = next;
1720
  }
1721
}
1722

    
1723

    
1724
#ifdef DEBUG
1725
#define TRACE_ISOLATE(tag)                                              \
1726
  do {                                                                  \
1727
    if (FLAG_trace_isolates) {                                          \
1728
      PrintF("Isolate %p (id %d)" #tag "\n",                            \
1729
             reinterpret_cast<void*>(this), id());                      \
1730
    }                                                                   \
1731
  } while (false)
1732
#else
1733
#define TRACE_ISOLATE(tag)
1734
#endif
1735

    
1736

    
1737
Isolate::Isolate()
1738
    : state_(UNINITIALIZED),
1739
      embedder_data_(NULL),
1740
      entry_stack_(NULL),
1741
      stack_trace_nesting_level_(0),
1742
      incomplete_message_(NULL),
1743
      preallocated_memory_thread_(NULL),
1744
      preallocated_message_space_(NULL),
1745
      bootstrapper_(NULL),
1746
      runtime_profiler_(NULL),
1747
      compilation_cache_(NULL),
1748
      counters_(NULL),
1749
      code_range_(NULL),
1750
      debugger_initialized_(false),
1751
      logger_(NULL),
1752
      stats_table_(NULL),
1753
      stub_cache_(NULL),
1754
      deoptimizer_data_(NULL),
1755
      capture_stack_trace_for_uncaught_exceptions_(false),
1756
      stack_trace_for_uncaught_exceptions_frame_limit_(0),
1757
      stack_trace_for_uncaught_exceptions_options_(StackTrace::kOverview),
1758
      transcendental_cache_(NULL),
1759
      memory_allocator_(NULL),
1760
      keyed_lookup_cache_(NULL),
1761
      context_slot_cache_(NULL),
1762
      descriptor_lookup_cache_(NULL),
1763
      handle_scope_implementer_(NULL),
1764
      unicode_cache_(NULL),
1765
      runtime_zone_(this),
1766
      in_use_list_(0),
1767
      free_list_(0),
1768
      preallocated_storage_preallocated_(false),
1769
      inner_pointer_to_code_cache_(NULL),
1770
      write_iterator_(NULL),
1771
      global_handles_(NULL),
1772
      eternal_handles_(NULL),
1773
      context_switcher_(NULL),
1774
      thread_manager_(NULL),
1775
      fp_stubs_generated_(false),
1776
      has_installed_extensions_(false),
1777
      string_tracker_(NULL),
1778
      regexp_stack_(NULL),
1779
      date_cache_(NULL),
1780
      code_stub_interface_descriptors_(NULL),
1781
      // TODO(bmeurer) Initialized lazily because it depends on flags; can
1782
      // be fixed once the default isolate cleanup is done.
1783
      random_number_generator_(NULL),
1784
      has_fatal_error_(false),
1785
      use_crankshaft_(true),
1786
      initialized_from_snapshot_(false),
1787
      cpu_profiler_(NULL),
1788
      heap_profiler_(NULL),
1789
      function_entry_hook_(NULL),
1790
      deferred_handles_head_(NULL),
1791
      optimizing_compiler_thread_(NULL),
1792
      sweeper_thread_(NULL),
1793
      stress_deopt_count_(0) {
1794
  id_ = NoBarrier_AtomicIncrement(&isolate_counter_, 1);
1795
  TRACE_ISOLATE(constructor);
1796

    
1797
  memset(isolate_addresses_, 0,
1798
      sizeof(isolate_addresses_[0]) * (kIsolateAddressCount + 1));
1799

    
1800
  heap_.isolate_ = this;
1801
  stack_guard_.isolate_ = this;
1802

    
1803
  // ThreadManager is initialized early to support locking an isolate
1804
  // before it is entered.
1805
  thread_manager_ = new ThreadManager();
1806
  thread_manager_->isolate_ = this;
1807

    
1808
#if V8_TARGET_ARCH_ARM && !defined(__arm__) || \
1809
    V8_TARGET_ARCH_MIPS && !defined(__mips__)
1810
  simulator_initialized_ = false;
1811
  simulator_i_cache_ = NULL;
1812
  simulator_redirection_ = NULL;
1813
#endif
1814

    
1815
#ifdef DEBUG
1816
  // heap_histograms_ initializes itself.
1817
  memset(&js_spill_information_, 0, sizeof(js_spill_information_));
1818
  memset(code_kind_statistics_, 0,
1819
         sizeof(code_kind_statistics_[0]) * Code::NUMBER_OF_KINDS);
1820
#endif
1821

    
1822
#ifdef ENABLE_DEBUGGER_SUPPORT
1823
  debug_ = NULL;
1824
  debugger_ = NULL;
1825
#endif
1826

    
1827
  handle_scope_data_.Initialize();
1828

    
1829
#define ISOLATE_INIT_EXECUTE(type, name, initial_value)                        \
1830
  name##_ = (initial_value);
1831
  ISOLATE_INIT_LIST(ISOLATE_INIT_EXECUTE)
1832
#undef ISOLATE_INIT_EXECUTE
1833

    
1834
#define ISOLATE_INIT_ARRAY_EXECUTE(type, name, length)                         \
1835
  memset(name##_, 0, sizeof(type) * length);
1836
  ISOLATE_INIT_ARRAY_LIST(ISOLATE_INIT_ARRAY_EXECUTE)
1837
#undef ISOLATE_INIT_ARRAY_EXECUTE
1838
}
1839

    
1840

    
1841
void Isolate::TearDown() {
1842
  TRACE_ISOLATE(tear_down);
1843

    
1844
  // Temporarily set this isolate as current so that various parts of
1845
  // the isolate can access it in their destructors without having a
1846
  // direct pointer. We don't use Enter/Exit here to avoid
1847
  // initializing the thread data.
1848
  PerIsolateThreadData* saved_data = CurrentPerIsolateThreadData();
1849
  Isolate* saved_isolate = UncheckedCurrent();
1850
  SetIsolateThreadLocals(this, NULL);
1851

    
1852
  Deinit();
1853

    
1854
  { LockGuard<Mutex> lock_guard(&process_wide_mutex_);
1855
    thread_data_table_->RemoveAllThreads(this);
1856
  }
1857

    
1858
  if (serialize_partial_snapshot_cache_ != NULL) {
1859
    delete[] serialize_partial_snapshot_cache_;
1860
    serialize_partial_snapshot_cache_ = NULL;
1861
  }
1862

    
1863
  if (!IsDefaultIsolate()) {
1864
    delete this;
1865
  }
1866

    
1867
  // Restore the previous current isolate.
1868
  SetIsolateThreadLocals(saved_isolate, saved_data);
1869
}
1870

    
1871

    
1872
void Isolate::GlobalTearDown() {
1873
  delete thread_data_table_;
1874
}
1875

    
1876

    
1877
void Isolate::Deinit() {
1878
  if (state_ == INITIALIZED) {
1879
    TRACE_ISOLATE(deinit);
1880

    
1881
#ifdef ENABLE_DEBUGGER_SUPPORT
1882
    debugger()->UnloadDebugger();
1883
#endif
1884

    
1885
    if (FLAG_concurrent_recompilation) {
1886
      optimizing_compiler_thread_->Stop();
1887
      delete optimizing_compiler_thread_;
1888
    }
1889

    
1890
    if (FLAG_sweeper_threads > 0) {
1891
      for (int i = 0; i < FLAG_sweeper_threads; i++) {
1892
        sweeper_thread_[i]->Stop();
1893
        delete sweeper_thread_[i];
1894
      }
1895
      delete[] sweeper_thread_;
1896
    }
1897

    
1898
    if (FLAG_hydrogen_stats) GetHStatistics()->Print();
1899

    
1900
    if (FLAG_print_deopt_stress) {
1901
      PrintF(stdout, "=== Stress deopt counter: %u\n", stress_deopt_count_);
1902
    }
1903

    
1904
    // We must stop the logger before we tear down other components.
1905
    Sampler* sampler = logger_->sampler();
1906
    if (sampler && sampler->IsActive()) sampler->Stop();
1907

    
1908
    delete deoptimizer_data_;
1909
    deoptimizer_data_ = NULL;
1910
    if (FLAG_preemption) {
1911
      v8::Locker locker(reinterpret_cast<v8::Isolate*>(this));
1912
      v8::Locker::StopPreemption(reinterpret_cast<v8::Isolate*>(this));
1913
    }
1914
    builtins_.TearDown();
1915
    bootstrapper_->TearDown();
1916

    
1917
    // Remove the external reference to the preallocated stack memory.
1918
    delete preallocated_message_space_;
1919
    preallocated_message_space_ = NULL;
1920
    PreallocatedMemoryThreadStop();
1921

    
1922
    if (runtime_profiler_ != NULL) {
1923
      runtime_profiler_->TearDown();
1924
      delete runtime_profiler_;
1925
      runtime_profiler_ = NULL;
1926
    }
1927
    heap_.TearDown();
1928
    logger_->TearDown();
1929

    
1930
    delete heap_profiler_;
1931
    heap_profiler_ = NULL;
1932
    delete cpu_profiler_;
1933
    cpu_profiler_ = NULL;
1934

    
1935
    // The default isolate is re-initializable due to legacy API.
1936
    state_ = UNINITIALIZED;
1937
  }
1938
}
1939

    
1940

    
1941
void Isolate::PushToPartialSnapshotCache(Object* obj) {
1942
  int length = serialize_partial_snapshot_cache_length();
1943
  int capacity = serialize_partial_snapshot_cache_capacity();
1944

    
1945
  if (length >= capacity) {
1946
    int new_capacity = static_cast<int>((capacity + 10) * 1.2);
1947
    Object** new_array = new Object*[new_capacity];
1948
    for (int i = 0; i < length; i++) {
1949
      new_array[i] = serialize_partial_snapshot_cache()[i];
1950
    }
1951
    if (capacity != 0) delete[] serialize_partial_snapshot_cache();
1952
    set_serialize_partial_snapshot_cache(new_array);
1953
    set_serialize_partial_snapshot_cache_capacity(new_capacity);
1954
  }
1955

    
1956
  serialize_partial_snapshot_cache()[length] = obj;
1957
  set_serialize_partial_snapshot_cache_length(length + 1);
1958
}
1959

    
1960

    
1961
void Isolate::SetIsolateThreadLocals(Isolate* isolate,
1962
                                     PerIsolateThreadData* data) {
1963
  Thread::SetThreadLocal(isolate_key_, isolate);
1964
  Thread::SetThreadLocal(per_isolate_thread_data_key_, data);
1965
}
1966

    
1967

    
1968
Isolate::~Isolate() {
1969
  TRACE_ISOLATE(destructor);
1970

    
1971
  // Has to be called while counters_ are still alive
1972
  runtime_zone_.DeleteKeptSegment();
1973

    
1974
  // The entry stack must be empty when we get here,
1975
  // except for the default isolate, where it can
1976
  // still contain up to one entry stack item
1977
  ASSERT(entry_stack_ == NULL || this == default_isolate_);
1978
  ASSERT(entry_stack_ == NULL || entry_stack_->previous_item == NULL);
1979

    
1980
  delete entry_stack_;
1981
  entry_stack_ = NULL;
1982

    
1983
  delete[] assembler_spare_buffer_;
1984
  assembler_spare_buffer_ = NULL;
1985

    
1986
  delete unicode_cache_;
1987
  unicode_cache_ = NULL;
1988

    
1989
  delete date_cache_;
1990
  date_cache_ = NULL;
1991

    
1992
  delete[] code_stub_interface_descriptors_;
1993
  code_stub_interface_descriptors_ = NULL;
1994

    
1995
  delete regexp_stack_;
1996
  regexp_stack_ = NULL;
1997

    
1998
  delete descriptor_lookup_cache_;
1999
  descriptor_lookup_cache_ = NULL;
2000
  delete context_slot_cache_;
2001
  context_slot_cache_ = NULL;
2002
  delete keyed_lookup_cache_;
2003
  keyed_lookup_cache_ = NULL;
2004

    
2005
  delete transcendental_cache_;
2006
  transcendental_cache_ = NULL;
2007
  delete stub_cache_;
2008
  stub_cache_ = NULL;
2009
  delete stats_table_;
2010
  stats_table_ = NULL;
2011

    
2012
  delete logger_;
2013
  logger_ = NULL;
2014

    
2015
  delete counters_;
2016
  counters_ = NULL;
2017

    
2018
  delete handle_scope_implementer_;
2019
  handle_scope_implementer_ = NULL;
2020

    
2021
  delete compilation_cache_;
2022
  compilation_cache_ = NULL;
2023
  delete bootstrapper_;
2024
  bootstrapper_ = NULL;
2025
  delete inner_pointer_to_code_cache_;
2026
  inner_pointer_to_code_cache_ = NULL;
2027
  delete write_iterator_;
2028
  write_iterator_ = NULL;
2029

    
2030
  delete context_switcher_;
2031
  context_switcher_ = NULL;
2032
  delete thread_manager_;
2033
  thread_manager_ = NULL;
2034

    
2035
  delete string_tracker_;
2036
  string_tracker_ = NULL;
2037

    
2038
  delete memory_allocator_;
2039
  memory_allocator_ = NULL;
2040
  delete code_range_;
2041
  code_range_ = NULL;
2042
  delete global_handles_;
2043
  global_handles_ = NULL;
2044
  delete eternal_handles_;
2045
  eternal_handles_ = NULL;
2046

    
2047
  delete string_stream_debug_object_cache_;
2048
  string_stream_debug_object_cache_ = NULL;
2049

    
2050
  delete external_reference_table_;
2051
  external_reference_table_ = NULL;
2052

    
2053
  delete random_number_generator_;
2054
  random_number_generator_ = NULL;
2055

    
2056
#ifdef ENABLE_DEBUGGER_SUPPORT
2057
  delete debugger_;
2058
  debugger_ = NULL;
2059
  delete debug_;
2060
  debug_ = NULL;
2061
#endif
2062
}
2063

    
2064

    
2065
void Isolate::InitializeThreadLocal() {
2066
  thread_local_top_.isolate_ = this;
2067
  thread_local_top_.Initialize();
2068
}
2069

    
2070

    
2071
void Isolate::PropagatePendingExceptionToExternalTryCatch() {
2072
  ASSERT(has_pending_exception());
2073

    
2074
  bool external_caught = IsExternallyCaught();
2075
  thread_local_top_.external_caught_exception_ = external_caught;
2076

    
2077
  if (!external_caught) return;
2078

    
2079
  if (thread_local_top_.pending_exception_->IsOutOfMemory()) {
2080
    // Do not propagate OOM exception: we should kill VM asap.
2081
  } else if (thread_local_top_.pending_exception_ ==
2082
             heap()->termination_exception()) {
2083
    try_catch_handler()->can_continue_ = false;
2084
    try_catch_handler()->has_terminated_ = true;
2085
    try_catch_handler()->exception_ = heap()->null_value();
2086
  } else {
2087
    v8::TryCatch* handler = try_catch_handler();
2088
    // At this point all non-object (failure) exceptions have
2089
    // been dealt with so this shouldn't fail.
2090
    ASSERT(!pending_exception()->IsFailure());
2091
    ASSERT(thread_local_top_.pending_message_obj_->IsJSMessageObject() ||
2092
           thread_local_top_.pending_message_obj_->IsTheHole());
2093
    ASSERT(thread_local_top_.pending_message_script_->IsScript() ||
2094
           thread_local_top_.pending_message_script_->IsTheHole());
2095
    handler->can_continue_ = true;
2096
    handler->has_terminated_ = false;
2097
    handler->exception_ = pending_exception();
2098
    // Propagate to the external try-catch only if we got an actual message.
2099
    if (thread_local_top_.pending_message_obj_->IsTheHole()) return;
2100

    
2101
    handler->message_obj_ = thread_local_top_.pending_message_obj_;
2102
    handler->message_script_ = thread_local_top_.pending_message_script_;
2103
    handler->message_start_pos_ = thread_local_top_.pending_message_start_pos_;
2104
    handler->message_end_pos_ = thread_local_top_.pending_message_end_pos_;
2105
  }
2106
}
2107

    
2108

    
2109
void Isolate::InitializeLoggingAndCounters() {
2110
  if (logger_ == NULL) {
2111
    logger_ = new Logger(this);
2112
  }
2113
  if (counters_ == NULL) {
2114
    counters_ = new Counters(this);
2115
  }
2116
}
2117

    
2118

    
2119
void Isolate::InitializeDebugger() {
2120
#ifdef ENABLE_DEBUGGER_SUPPORT
2121
  LockGuard<RecursiveMutex> lock_guard(debugger_access());
2122
  if (NoBarrier_Load(&debugger_initialized_)) return;
2123
  InitializeLoggingAndCounters();
2124
  debug_ = new Debug(this);
2125
  debugger_ = new Debugger(this);
2126
  Release_Store(&debugger_initialized_, true);
2127
#endif
2128
}
2129

    
2130

    
2131
bool Isolate::Init(Deserializer* des) {
2132
  ASSERT(state_ != INITIALIZED);
2133
  TRACE_ISOLATE(init);
2134

    
2135
  stress_deopt_count_ = FLAG_deopt_every_n_times;
2136

    
2137
  has_fatal_error_ = false;
2138

    
2139
  use_crankshaft_ = FLAG_crankshaft
2140
      && !Serializer::enabled()
2141
      && CPU::SupportsCrankshaft();
2142

    
2143
  if (function_entry_hook() != NULL) {
2144
    // When function entry hooking is in effect, we have to create the code
2145
    // stubs from scratch to get entry hooks, rather than loading the previously
2146
    // generated stubs from disk.
2147
    // If this assert fires, the initialization path has regressed.
2148
    ASSERT(des == NULL);
2149
  }
2150

    
2151
  // The initialization process does not handle memory exhaustion.
2152
  DisallowAllocationFailure disallow_allocation_failure;
2153

    
2154
  InitializeLoggingAndCounters();
2155

    
2156
  InitializeDebugger();
2157

    
2158
  memory_allocator_ = new MemoryAllocator(this);
2159
  code_range_ = new CodeRange(this);
2160

    
2161
  // Safe after setting Heap::isolate_, and initializing StackGuard
2162
  heap_.SetStackLimits();
2163

    
2164
#define ASSIGN_ELEMENT(CamelName, hacker_name)                  \
2165
  isolate_addresses_[Isolate::k##CamelName##Address] =          \
2166
      reinterpret_cast<Address>(hacker_name##_address());
2167
  FOR_EACH_ISOLATE_ADDRESS_NAME(ASSIGN_ELEMENT)
2168
#undef ASSIGN_ELEMENT
2169

    
2170
  string_tracker_ = new StringTracker();
2171
  string_tracker_->isolate_ = this;
2172
  compilation_cache_ = new CompilationCache(this);
2173
  transcendental_cache_ = new TranscendentalCache(this);
2174
  keyed_lookup_cache_ = new KeyedLookupCache();
2175
  context_slot_cache_ = new ContextSlotCache();
2176
  descriptor_lookup_cache_ = new DescriptorLookupCache();
2177
  unicode_cache_ = new UnicodeCache();
2178
  inner_pointer_to_code_cache_ = new InnerPointerToCodeCache(this);
2179
  write_iterator_ = new ConsStringIteratorOp();
2180
  global_handles_ = new GlobalHandles(this);
2181
  eternal_handles_ = new EternalHandles();
2182
  bootstrapper_ = new Bootstrapper(this);
2183
  handle_scope_implementer_ = new HandleScopeImplementer(this);
2184
  stub_cache_ = new StubCache(this);
2185
  regexp_stack_ = new RegExpStack();
2186
  regexp_stack_->isolate_ = this;
2187
  date_cache_ = new DateCache();
2188
  code_stub_interface_descriptors_ =
2189
      new CodeStubInterfaceDescriptor[CodeStub::NUMBER_OF_IDS];
2190
  cpu_profiler_ = new CpuProfiler(this);
2191
  heap_profiler_ = new HeapProfiler(heap());
2192

    
2193
  // Enable logging before setting up the heap
2194
  logger_->SetUp(this);
2195

    
2196
  // Initialize other runtime facilities
2197
#if defined(USE_SIMULATOR)
2198
#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
2199
  Simulator::Initialize(this);
2200
#endif
2201
#endif
2202

    
2203
  { // NOLINT
2204
    // Ensure that the thread has a valid stack guard.  The v8::Locker object
2205
    // will ensure this too, but we don't have to use lockers if we are only
2206
    // using one thread.
2207
    ExecutionAccess lock(this);
2208
    stack_guard_.InitThread(lock);
2209
  }
2210

    
2211
  // SetUp the object heap.
2212
  ASSERT(!heap_.HasBeenSetUp());
2213
  if (!heap_.SetUp()) {
2214
    V8::FatalProcessOutOfMemory("heap setup");
2215
    return false;
2216
  }
2217

    
2218
  deoptimizer_data_ = new DeoptimizerData(memory_allocator_);
2219

    
2220
  if (FLAG_concurrent_recompilation) {
2221
    optimizing_compiler_thread_ = new OptimizingCompilerThread(this);
2222
    optimizing_compiler_thread_->Start();
2223
  }
2224

    
2225
  const bool create_heap_objects = (des == NULL);
2226
  if (create_heap_objects && !heap_.CreateHeapObjects()) {
2227
    V8::FatalProcessOutOfMemory("heap object creation");
2228
    return false;
2229
  }
2230

    
2231
  if (create_heap_objects) {
2232
    // Terminate the cache array with the sentinel so we can iterate.
2233
    PushToPartialSnapshotCache(heap_.undefined_value());
2234
  }
2235

    
2236
  InitializeThreadLocal();
2237

    
2238
  bootstrapper_->Initialize(create_heap_objects);
2239
  builtins_.SetUp(this, create_heap_objects);
2240

    
2241
  // Only preallocate on the first initialization.
2242
  if (FLAG_preallocate_message_memory && preallocated_message_space_ == NULL) {
2243
    // Start the thread which will set aside some memory.
2244
    PreallocatedMemoryThreadStart();
2245
    preallocated_message_space_ =
2246
        new NoAllocationStringAllocator(
2247
            preallocated_memory_thread_->data(),
2248
            preallocated_memory_thread_->length());
2249
    PreallocatedStorageInit(preallocated_memory_thread_->length() / 4);
2250
  }
2251

    
2252
  if (FLAG_preemption) {
2253
    v8::Locker locker(reinterpret_cast<v8::Isolate*>(this));
2254
    v8::Locker::StartPreemption(reinterpret_cast<v8::Isolate*>(this), 100);
2255
  }
2256

    
2257
#ifdef ENABLE_DEBUGGER_SUPPORT
2258
  debug_->SetUp(create_heap_objects);
2259
#endif
2260

    
2261
  // If we are deserializing, read the state into the now-empty heap.
2262
  if (!create_heap_objects) {
2263
    des->Deserialize(this);
2264
  }
2265
  stub_cache_->Initialize();
2266

    
2267
  // Finish initialization of ThreadLocal after deserialization is done.
2268
  clear_pending_exception();
2269
  clear_pending_message();
2270
  clear_scheduled_exception();
2271

    
2272
  // Deserializing may put strange things in the root array's copy of the
2273
  // stack guard.
2274
  heap_.SetStackLimits();
2275

    
2276
  // Quiet the heap NaN if needed on target platform.
2277
  if (!create_heap_objects) Assembler::QuietNaN(heap_.nan_value());
2278

    
2279
  runtime_profiler_ = new RuntimeProfiler(this);
2280
  runtime_profiler_->SetUp();
2281

    
2282
  // If we are deserializing, log non-function code objects and compiled
2283
  // functions found in the snapshot.
2284
  if (!create_heap_objects &&
2285
      (FLAG_log_code || FLAG_ll_prof || logger_->is_logging_code_events())) {
2286
    HandleScope scope(this);
2287
    LOG(this, LogCodeObjects());
2288
    LOG(this, LogCompiledFunctions());
2289
  }
2290

    
2291
  CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, embedder_data_)),
2292
           Internals::kIsolateEmbedderDataOffset);
2293
  CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.roots_)),
2294
           Internals::kIsolateRootsOffset);
2295

    
2296
  state_ = INITIALIZED;
2297
  time_millis_at_init_ = OS::TimeCurrentMillis();
2298

    
2299
  if (!create_heap_objects) {
2300
    // Now that the heap is consistent, it's OK to generate the code for the
2301
    // deopt entry table that might have been referred to by optimized code in
2302
    // the snapshot.
2303
    HandleScope scope(this);
2304
    Deoptimizer::EnsureCodeForDeoptimizationEntry(
2305
        this,
2306
        Deoptimizer::LAZY,
2307
        kDeoptTableSerializeEntryCount - 1);
2308
  }
2309

    
2310
  if (!Serializer::enabled()) {
2311
    // Ensure that all stubs which need to be generated ahead of time, but
2312
    // cannot be serialized into the snapshot have been generated.
2313
    HandleScope scope(this);
2314
    CodeStub::GenerateFPStubs(this);
2315
    StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(this);
2316
    StubFailureTrampolineStub::GenerateAheadOfTime(this);
2317
    // TODO(mstarzinger): The following is an ugly hack to make sure the
2318
    // interface descriptor is initialized even when stubs have been
2319
    // deserialized out of the snapshot without the graph builder.
2320
    FastCloneShallowArrayStub stub(FastCloneShallowArrayStub::CLONE_ELEMENTS,
2321
                                   DONT_TRACK_ALLOCATION_SITE, 0);
2322
    stub.InitializeInterfaceDescriptor(
2323
        this, code_stub_interface_descriptor(CodeStub::FastCloneShallowArray));
2324
    BinaryOpStub::InitializeForIsolate(this);
2325
    CompareNilICStub::InitializeForIsolate(this);
2326
    ToBooleanStub::InitializeForIsolate(this);
2327
    ArrayConstructorStubBase::InstallDescriptors(this);
2328
    InternalArrayConstructorStubBase::InstallDescriptors(this);
2329
    FastNewClosureStub::InstallDescriptors(this);
2330
    NumberToStringStub::InstallDescriptors(this);
2331
  }
2332

    
2333
  if (FLAG_sweeper_threads > 0) {
2334
    sweeper_thread_ = new SweeperThread*[FLAG_sweeper_threads];
2335
    for (int i = 0; i < FLAG_sweeper_threads; i++) {
2336
      sweeper_thread_[i] = new SweeperThread(this);
2337
      sweeper_thread_[i]->Start();
2338
    }
2339
  }
2340

    
2341
  initialized_from_snapshot_ = (des != NULL);
2342

    
2343
  return true;
2344
}
2345

    
2346

    
2347
// Initialized lazily to allow early
2348
// v8::V8::SetAddHistogramSampleFunction calls.
2349
StatsTable* Isolate::stats_table() {
2350
  if (stats_table_ == NULL) {
2351
    stats_table_ = new StatsTable;
2352
  }
2353
  return stats_table_;
2354
}
2355

    
2356

    
2357
void Isolate::Enter() {
2358
  Isolate* current_isolate = NULL;
2359
  PerIsolateThreadData* current_data = CurrentPerIsolateThreadData();
2360
  if (current_data != NULL) {
2361
    current_isolate = current_data->isolate_;
2362
    ASSERT(current_isolate != NULL);
2363
    if (current_isolate == this) {
2364
      ASSERT(Current() == this);
2365
      ASSERT(entry_stack_ != NULL);
2366
      ASSERT(entry_stack_->previous_thread_data == NULL ||
2367
             entry_stack_->previous_thread_data->thread_id().Equals(
2368
                 ThreadId::Current()));
2369
      // Same thread re-enters the isolate, no need to re-init anything.
2370
      entry_stack_->entry_count++;
2371
      return;
2372
    }
2373
  }
2374

    
2375
  // Threads can have default isolate set into TLS as Current but not yet have
2376
  // PerIsolateThreadData for it, as it requires more advanced phase of the
2377
  // initialization. For example, a thread might be the one that system used for
2378
  // static initializers - in this case the default isolate is set in TLS but
2379
  // the thread did not yet Enter the isolate. If PerisolateThreadData is not
2380
  // there, use the isolate set in TLS.
2381
  if (current_isolate == NULL) {
2382
    current_isolate = Isolate::UncheckedCurrent();
2383
  }
2384

    
2385
  PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread();
2386
  ASSERT(data != NULL);
2387
  ASSERT(data->isolate_ == this);
2388

    
2389
  EntryStackItem* item = new EntryStackItem(current_data,
2390
                                            current_isolate,
2391
                                            entry_stack_);
2392
  entry_stack_ = item;
2393

    
2394
  SetIsolateThreadLocals(this, data);
2395

    
2396
  // In case it's the first time some thread enters the isolate.
2397
  set_thread_id(data->thread_id());
2398
}
2399

    
2400

    
2401
void Isolate::Exit() {
2402
  ASSERT(entry_stack_ != NULL);
2403
  ASSERT(entry_stack_->previous_thread_data == NULL ||
2404
         entry_stack_->previous_thread_data->thread_id().Equals(
2405
             ThreadId::Current()));
2406

    
2407
  if (--entry_stack_->entry_count > 0) return;
2408

    
2409
  ASSERT(CurrentPerIsolateThreadData() != NULL);
2410
  ASSERT(CurrentPerIsolateThreadData()->isolate_ == this);
2411

    
2412
  // Pop the stack.
2413
  EntryStackItem* item = entry_stack_;
2414
  entry_stack_ = item->previous_item;
2415

    
2416
  PerIsolateThreadData* previous_thread_data = item->previous_thread_data;
2417
  Isolate* previous_isolate = item->previous_isolate;
2418

    
2419
  delete item;
2420

    
2421
  // Reinit the current thread for the isolate it was running before this one.
2422
  SetIsolateThreadLocals(previous_isolate, previous_thread_data);
2423
}
2424

    
2425

    
2426
void Isolate::LinkDeferredHandles(DeferredHandles* deferred) {
2427
  deferred->next_ = deferred_handles_head_;
2428
  if (deferred_handles_head_ != NULL) {
2429
    deferred_handles_head_->previous_ = deferred;
2430
  }
2431
  deferred_handles_head_ = deferred;
2432
}
2433

    
2434

    
2435
void Isolate::UnlinkDeferredHandles(DeferredHandles* deferred) {
2436
#ifdef DEBUG
2437
  // In debug mode assert that the linked list is well-formed.
2438
  DeferredHandles* deferred_iterator = deferred;
2439
  while (deferred_iterator->previous_ != NULL) {
2440
    deferred_iterator = deferred_iterator->previous_;
2441
  }
2442
  ASSERT(deferred_handles_head_ == deferred_iterator);
2443
#endif
2444
  if (deferred_handles_head_ == deferred) {
2445
    deferred_handles_head_ = deferred_handles_head_->next_;
2446
  }
2447
  if (deferred->next_ != NULL) {
2448
    deferred->next_->previous_ = deferred->previous_;
2449
  }
2450
  if (deferred->previous_ != NULL) {
2451
    deferred->previous_->next_ = deferred->next_;
2452
  }
2453
}
2454

    
2455

    
2456
HStatistics* Isolate::GetHStatistics() {
2457
  if (hstatistics() == NULL) set_hstatistics(new HStatistics());
2458
  return hstatistics();
2459
}
2460

    
2461

    
2462
HTracer* Isolate::GetHTracer() {
2463
  if (htracer() == NULL) set_htracer(new HTracer(id()));
2464
  return htracer();
2465
}
2466

    
2467

    
2468
Map* Isolate::get_initial_js_array_map(ElementsKind kind) {
2469
  Context* native_context = context()->native_context();
2470
  Object* maybe_map_array = native_context->js_array_maps();
2471
  if (!maybe_map_array->IsUndefined()) {
2472
    Object* maybe_transitioned_map =
2473
        FixedArray::cast(maybe_map_array)->get(kind);
2474
    if (!maybe_transitioned_map->IsUndefined()) {
2475
      return Map::cast(maybe_transitioned_map);
2476
    }
2477
  }
2478
  return NULL;
2479
}
2480

    
2481

    
2482
bool Isolate::IsFastArrayConstructorPrototypeChainIntact() {
2483
  Map* root_array_map =
2484
      get_initial_js_array_map(GetInitialFastElementsKind());
2485
  ASSERT(root_array_map != NULL);
2486
  JSObject* initial_array_proto = JSObject::cast(*initial_array_prototype());
2487

    
2488
  // Check that the array prototype hasn't been altered WRT empty elements.
2489
  if (root_array_map->prototype() != initial_array_proto) return false;
2490
  if (initial_array_proto->elements() != heap()->empty_fixed_array()) {
2491
    return false;
2492
  }
2493

    
2494
  // Check that the object prototype hasn't been altered WRT empty elements.
2495
  JSObject* initial_object_proto = JSObject::cast(*initial_object_prototype());
2496
  Object* root_array_map_proto = initial_array_proto->GetPrototype();
2497
  if (root_array_map_proto != initial_object_proto) return false;
2498
  if (initial_object_proto->elements() != heap()->empty_fixed_array()) {
2499
    return false;
2500
  }
2501

    
2502
  return initial_object_proto->GetPrototype()->IsNull();
2503
}
2504

    
2505

    
2506
CodeStubInterfaceDescriptor*
2507
    Isolate::code_stub_interface_descriptor(int index) {
2508
  return code_stub_interface_descriptors_ + index;
2509
}
2510

    
2511

    
2512
Object* Isolate::FindCodeObject(Address a) {
2513
  return inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer(a);
2514
}
2515

    
2516

    
2517
#ifdef DEBUG
2518
#define ISOLATE_FIELD_OFFSET(type, name, ignored)                       \
2519
const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_);
2520
ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
2521
ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
2522
#undef ISOLATE_FIELD_OFFSET
2523
#endif
2524

    
2525
} }  // namespace v8::internal