// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.


// Defined when linking against shared lib on Windows.
#if defined(USING_V8_SHARED) && !defined(V8_SHARED)
#define V8_SHARED
#endif

#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

#ifdef V8_SHARED
#include <assert.h>
#endif  // V8_SHARED

#ifndef V8_SHARED
#include <algorithm>
#include <vector>
#endif  // !V8_SHARED

#ifdef V8_SHARED
#include "include/v8-testing.h"
#endif  // V8_SHARED

#ifdef ENABLE_VTUNE_JIT_INTERFACE
#include "src/third_party/vtune/v8-vtune.h"
#endif

#include "src/d8.h"
#include "src/ostreams.h"

#include "include/libplatform/libplatform.h"
#ifndef V8_SHARED
#include "src/api.h"
#include "src/base/cpu.h"
#include "src/base/logging.h"
#include "src/base/platform/platform.h"
#include "src/base/sys-info.h"
#include "src/basic-block-profiler.h"
#include "src/snapshot/natives.h"
#include "src/utils.h"
#include "src/v8.h"
#endif  // !V8_SHARED

#if !defined(_WIN32) && !defined(_WIN64)
#include <unistd.h>  // NOLINT
#else
#include <windows.h>  // NOLINT
#if defined(_MSC_VER)
#include <crtdbg.h>  // NOLINT
#endif               // defined(_MSC_VER)
#endif               // !defined(_WIN32) && !defined(_WIN64)

#ifndef DCHECK
#define DCHECK(condition) assert(condition)
#endif

#ifndef CHECK
#define CHECK(condition) assert(condition)
#endif

namespace v8 {

namespace {

const int MB = 1024 * 1024;
#ifndef V8_SHARED
const int kMaxWorkers = 50;
#endif


class ShellArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
 public:
  virtual void* Allocate(size_t length) {
    void* data = AllocateUninitialized(length);
    return data == NULL ? data : memset(data, 0, length);
  }
  virtual void* AllocateUninitialized(size_t length) { return malloc(length); }
  virtual void Free(void* data, size_t) { free(data); }
};


class MockArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
 public:
  void* Allocate(size_t length) override {
    size_t actual_length = length > 10 * MB ? 1 : length;
    void* data = AllocateUninitialized(actual_length);
    return data == NULL ? data : memset(data, 0, actual_length);
  }
  void* AllocateUninitialized(size_t length) override {
    return length > 10 * MB ? malloc(1) : malloc(length);
  }
  void Free(void* p, size_t) override { free(p); }
};


#ifndef V8_SHARED
// Predictable v8::Platform implementation. All background and foreground
// tasks are run immediately, delayed tasks are not executed at all.
class PredictablePlatform : public Platform {
 public:
  PredictablePlatform() {}

  void CallOnBackgroundThread(Task* task,
                              ExpectedRuntime expected_runtime) override {
    task->Run();
    delete task;
  }

  void CallOnForegroundThread(v8::Isolate* isolate, Task* task) override {
    task->Run();
    delete task;
  }

  void CallDelayedOnForegroundThread(v8::Isolate* isolate, Task* task,
                                     double delay_in_seconds) override {
    delete task;
  }

  void CallIdleOnForegroundThread(v8::Isolate* isolate,
                                  IdleTask* task) override {
    UNREACHABLE();
  }

  bool IdleTasksEnabled(v8::Isolate* isolate) override { return false; }

  double MonotonicallyIncreasingTime() override {
    return synthetic_time_in_sec_ += 0.00001;
  }

  uint64_t AddTraceEvent(char phase, const uint8_t* categoryEnabledFlag,
                         const char* name, uint64_t id, uint64_t bind_id,
                         int numArgs, const char** argNames,
                         const uint8_t* argTypes, const uint64_t* argValues,
                         unsigned int flags) override {
    return 0;
  }

  void UpdateTraceEventDuration(const uint8_t* categoryEnabledFlag,
                                const char* name, uint64_t handle) override {}

  const uint8_t* GetCategoryGroupEnabled(const char* name) override {
    static uint8_t no = 0;
    return &no;
  }

  const char* GetCategoryGroupName(
      const uint8_t* categoryEnabledFlag) override {
    static const char* dummy = "dummy";
    return dummy;
  }

 private:
  double synthetic_time_in_sec_ = 0.0;

  DISALLOW_COPY_AND_ASSIGN(PredictablePlatform);
};
#endif  // !V8_SHARED


v8::Platform* g_platform = NULL;


static Local<Value> Throw(Isolate* isolate, const char* message) {
  return isolate->ThrowException(
      String::NewFromUtf8(isolate, message, NewStringType::kNormal)
          .ToLocalChecked());
}


#ifndef V8_SHARED
bool FindInObjectList(Local<Object> object, const Shell::ObjectList& list) {
  for (int i = 0; i < list.length(); ++i) {
    if (list[i]->StrictEquals(object)) {
      return true;
    }
  }
  return false;
}


Worker* GetWorkerFromInternalField(Isolate* isolate, Local<Object> object) {
  if (object->InternalFieldCount() != 1) {
    Throw(isolate, "this is not a Worker");
    return NULL;
  }

  Worker* worker =
      static_cast<Worker*>(object->GetAlignedPointerFromInternalField(0));
  if (worker == NULL) {
    Throw(isolate, "Worker is defunct because main thread is terminating");
    return NULL;
  }

  return worker;
}
#endif  // !V8_SHARED


}  // namespace


class PerIsolateData {
 public:
  explicit PerIsolateData(Isolate* isolate) : isolate_(isolate), realms_(NULL) {
    HandleScope scope(isolate);
    isolate->SetData(0, this);
  }

  ~PerIsolateData() {
    isolate_->SetData(0, NULL);  // Not really needed, just to be sure...
  }

  inline static PerIsolateData* Get(Isolate* isolate) {
    return reinterpret_cast<PerIsolateData*>(isolate->GetData(0));
  }

  class RealmScope {
   public:
    explicit RealmScope(PerIsolateData* data);
    ~RealmScope();
   private:
    PerIsolateData* data_;
  };

 private:
  friend class Shell;
  friend class RealmScope;
  Isolate* isolate_;
  int realm_count_;
  int realm_current_;
  int realm_switch_;
  Global<Context>* realms_;
  Global<Value> realm_shared_;

  int RealmIndexOrThrow(const v8::FunctionCallbackInfo<v8::Value>& args,
                        int arg_offset);
  int RealmFind(Local<Context> context);
};


#ifndef V8_SHARED
CounterMap* Shell::counter_map_;
base::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
CounterCollection Shell::local_counters_;
CounterCollection* Shell::counters_ = &local_counters_;
base::LazyMutex Shell::context_mutex_;
const base::TimeTicks Shell::kInitialTicks =
    base::TimeTicks::HighResolutionNow();
Global<Context> Shell::utility_context_;
base::LazyMutex Shell::workers_mutex_;
bool Shell::allow_new_workers_ = true;
i::List<Worker*> Shell::workers_;
i::List<SharedArrayBuffer::Contents> Shell::externalized_shared_contents_;
#endif  // !V8_SHARED

Global<Context> Shell::evaluation_context_;
ArrayBuffer::Allocator* Shell::array_buffer_allocator;
ShellOptions Shell::options;
base::OnceType Shell::quit_once_ = V8_ONCE_INIT;

#ifndef V8_SHARED
bool CounterMap::Match(void* key1, void* key2) {
  const char* name1 = reinterpret_cast<const char*>(key1);
  const char* name2 = reinterpret_cast<const char*>(key2);
  return strcmp(name1, name2) == 0;
}
#endif  // !V8_SHARED


// Converts a V8 value to a C string.
const char* Shell::ToCString(const v8::String::Utf8Value& value) {
  return *value ? *value : "<string conversion failed>";
}


ScriptCompiler::CachedData* CompileForCachedData(
    Local<String> source, Local<Value> name,
    ScriptCompiler::CompileOptions compile_options) {
  int source_length = source->Length();
  uint16_t* source_buffer = new uint16_t[source_length];
  source->Write(source_buffer, 0, source_length);
  int name_length = 0;
  uint16_t* name_buffer = NULL;
  if (name->IsString()) {
    Local<String> name_string = Local<String>::Cast(name);
    name_length = name_string->Length();
    name_buffer = new uint16_t[name_length];
    name_string->Write(name_buffer, 0, name_length);
  }
  Isolate::CreateParams create_params;
  create_params.array_buffer_allocator = Shell::array_buffer_allocator;
  Isolate* temp_isolate = Isolate::New(create_params);
  ScriptCompiler::CachedData* result = NULL;
  {
    Isolate::Scope isolate_scope(temp_isolate);
    HandleScope handle_scope(temp_isolate);
    Context::Scope context_scope(Context::New(temp_isolate));
    Local<String> source_copy =
        v8::String::NewFromTwoByte(temp_isolate, source_buffer,
                                   v8::NewStringType::kNormal,
                                   source_length).ToLocalChecked();
    Local<Value> name_copy;
    if (name_buffer) {
      name_copy = v8::String::NewFromTwoByte(temp_isolate, name_buffer,
                                             v8::NewStringType::kNormal,
                                             name_length).ToLocalChecked();
    } else {
      name_copy = v8::Undefined(temp_isolate);
    }
    ScriptCompiler::Source script_source(source_copy, ScriptOrigin(name_copy));
    if (!ScriptCompiler::CompileUnboundScript(temp_isolate, &script_source,
                                              compile_options).IsEmpty() &&
        script_source.GetCachedData()) {
      int length = script_source.GetCachedData()->length;
      uint8_t* cache = new uint8_t[length];
      memcpy(cache, script_source.GetCachedData()->data, length);
      result = new ScriptCompiler::CachedData(
          cache, length, ScriptCompiler::CachedData::BufferOwned);
    }
  }
  temp_isolate->Dispose();
  delete[] source_buffer;
  delete[] name_buffer;
  return result;
}


// Compile a string within the current v8 context.
MaybeLocal<Script> Shell::CompileString(
    Isolate* isolate, Local<String> source, Local<Value> name,
    ScriptCompiler::CompileOptions compile_options, SourceType source_type) {
  Local<Context> context(isolate->GetCurrentContext());
  ScriptOrigin origin(name);
  if (compile_options == ScriptCompiler::kNoCompileOptions) {
    ScriptCompiler::Source script_source(source, origin);
    return source_type == SCRIPT
               ? ScriptCompiler::Compile(context, &script_source,
                                         compile_options)
               : ScriptCompiler::CompileModule(context, &script_source,
                                               compile_options);
  }

  ScriptCompiler::CachedData* data =
      CompileForCachedData(source, name, compile_options);
  ScriptCompiler::Source cached_source(source, origin, data);
  if (compile_options == ScriptCompiler::kProduceCodeCache) {
    compile_options = ScriptCompiler::kConsumeCodeCache;
  } else if (compile_options == ScriptCompiler::kProduceParserCache) {
    compile_options = ScriptCompiler::kConsumeParserCache;
  } else {
    DCHECK(false);  // A new compile option?
  }
  if (data == NULL) compile_options = ScriptCompiler::kNoCompileOptions;
  MaybeLocal<Script> result =
      source_type == SCRIPT
          ? ScriptCompiler::Compile(context, &cached_source, compile_options)
          : ScriptCompiler::CompileModule(context, &cached_source,
                                          compile_options);
  CHECK(data == NULL || !data->rejected);
  return result;
}


// Executes a string within the current v8 context.
bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
                          Local<Value> name, bool print_result,
                          bool report_exceptions, SourceType source_type) {
  HandleScope handle_scope(isolate);
  TryCatch try_catch(isolate);
  try_catch.SetVerbose(true);

  MaybeLocal<Value> maybe_result;
  {
    PerIsolateData* data = PerIsolateData::Get(isolate);
    Local<Context> realm =
        Local<Context>::New(isolate, data->realms_[data->realm_current_]);
    Context::Scope context_scope(realm);
    Local<Script> script;
    if (!Shell::CompileString(isolate, source, name, options.compile_options,
                              source_type).ToLocal(&script)) {
      // Print errors that happened during compilation.
      if (report_exceptions) ReportException(isolate, &try_catch);
      return false;
    }
    maybe_result = script->Run(realm);
    EmptyMessageQueues(isolate);
    data->realm_current_ = data->realm_switch_;
  }
  Local<Value> result;
  if (!maybe_result.ToLocal(&result)) {
    DCHECK(try_catch.HasCaught());
    // Print errors that happened during execution.
    if (report_exceptions) ReportException(isolate, &try_catch);
    return false;
  }
  DCHECK(!try_catch.HasCaught());
  if (print_result) {
#if !defined(V8_SHARED)
    if (options.test_shell) {
#endif
      if (!result->IsUndefined()) {
        // If all went well and the result wasn't undefined then print
        // the returned value.
        v8::String::Utf8Value str(result);
        fwrite(*str, sizeof(**str), str.length(), stdout);
        printf("\n");
      }
#if !defined(V8_SHARED)
    } else {
      v8::TryCatch try_catch(isolate);
      v8::Local<v8::Context> context =
          v8::Local<v8::Context>::New(isolate, utility_context_);
      v8::Context::Scope context_scope(context);
      Local<Object> global = context->Global();
      Local<Value> fun =
          global->Get(context, String::NewFromUtf8(isolate, "Stringify",
                                                   v8::NewStringType::kNormal)
                                   .ToLocalChecked()).ToLocalChecked();
      Local<Value> argv[1] = {result};
      Local<Value> s;
      if (!Local<Function>::Cast(fun)
               ->Call(context, global, 1, argv)
               .ToLocal(&s)) {
        return true;
      }
      DCHECK(!try_catch.HasCaught());
      v8::String::Utf8Value str(s);
      fwrite(*str, sizeof(**str), str.length(), stdout);
      printf("\n");
    }
#endif
  }
  return true;
}


PerIsolateData::RealmScope::RealmScope(PerIsolateData* data) : data_(data) {
  data_->realm_count_ = 1;
  data_->realm_current_ = 0;
  data_->realm_switch_ = 0;
  data_->realms_ = new Global<Context>[1];
  data_->realms_[0].Reset(data_->isolate_,
                          data_->isolate_->GetEnteredContext());
}


PerIsolateData::RealmScope::~RealmScope() {
  // Drop realms to avoid keeping them alive.
  for (int i = 0; i < data_->realm_count_; ++i)
    data_->realms_[i].Reset();
  delete[] data_->realms_;
  if (!data_->realm_shared_.IsEmpty())
    data_->realm_shared_.Reset();
}


int PerIsolateData::RealmFind(Local<Context> context) {
  for (int i = 0; i < realm_count_; ++i) {
    if (realms_[i] == context) return i;
  }
  return -1;
}


int PerIsolateData::RealmIndexOrThrow(
    const v8::FunctionCallbackInfo<v8::Value>& args,
    int arg_offset) {
  if (args.Length() < arg_offset || !args[arg_offset]->IsNumber()) {
    Throw(args.GetIsolate(), "Invalid argument");
    return -1;
  }
  int index = args[arg_offset]
                  ->Int32Value(args.GetIsolate()->GetCurrentContext())
                  .FromMaybe(-1);
  if (index < 0 || index >= realm_count_ || realms_[index].IsEmpty()) {
    Throw(args.GetIsolate(), "Invalid realm index");
    return -1;
  }
  return index;
}


#ifndef V8_SHARED
// performance.now() returns a time stamp as double, measured in milliseconds.
// When FLAG_verify_predictable mode is enabled it returns result of
// v8::Platform::MonotonicallyIncreasingTime().
void Shell::PerformanceNow(const v8::FunctionCallbackInfo<v8::Value>& args) {
  if (i::FLAG_verify_predictable) {
    args.GetReturnValue().Set(g_platform->MonotonicallyIncreasingTime());
  } else {
    base::TimeDelta delta =
        base::TimeTicks::HighResolutionNow() - kInitialTicks;
    args.GetReturnValue().Set(delta.InMillisecondsF());
  }
}
#endif  // !V8_SHARED


// Realm.current() returns the index of the currently active realm.
void Shell::RealmCurrent(const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();
  PerIsolateData* data = PerIsolateData::Get(isolate);
  int index = data->RealmFind(isolate->GetEnteredContext());
  if (index == -1) return;
  args.GetReturnValue().Set(index);
}


// Realm.owner(o) returns the index of the realm that created o.
void Shell::RealmOwner(const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();
  PerIsolateData* data = PerIsolateData::Get(isolate);
  if (args.Length() < 1 || !args[0]->IsObject()) {
    Throw(args.GetIsolate(), "Invalid argument");
    return;
  }
  int index = data->RealmFind(args[0]
                                  ->ToObject(isolate->GetCurrentContext())
                                  .ToLocalChecked()
                                  ->CreationContext());
  if (index == -1) return;
  args.GetReturnValue().Set(index);
}


// Realm.global(i) returns the global object of realm i.
// (Note that properties of global objects cannot be read/written cross-realm.)
void Shell::RealmGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
  PerIsolateData* data = PerIsolateData::Get(args.GetIsolate());
  int index = data->RealmIndexOrThrow(args, 0);
  if (index == -1) return;
  args.GetReturnValue().Set(
      Local<Context>::New(args.GetIsolate(), data->realms_[index])->Global());
}


// Realm.create() creates a new realm and returns its index.
void Shell::RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();
  TryCatch try_catch(isolate);
  PerIsolateData* data = PerIsolateData::Get(isolate);
  Global<Context>* old_realms = data->realms_;
  int index = data->realm_count_;
  data->realms_ = new Global<Context>[++data->realm_count_];
  for (int i = 0; i < index; ++i) {
    data->realms_[i].Reset(isolate, old_realms[i]);
    old_realms[i].Reset();
  }
  delete[] old_realms;
  Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
  Local<Context> context = Context::New(isolate, NULL, global_template);
  if (context.IsEmpty()) {
    DCHECK(try_catch.HasCaught());
    try_catch.ReThrow();
    return;
  }
  data->realms_[index].Reset(isolate, context);
  args.GetReturnValue().Set(index);
}


// Realm.dispose(i) disposes the reference to the realm i.
void Shell::RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();
  PerIsolateData* data = PerIsolateData::Get(isolate);
  int index = data->RealmIndexOrThrow(args, 0);
  if (index == -1) return;
  if (index == 0 ||
      index == data->realm_current_ || index == data->realm_switch_) {
    Throw(args.GetIsolate(), "Invalid realm index");
    return;
  }
  data->realms_[index].Reset();
  isolate->ContextDisposedNotification();
  isolate->IdleNotificationDeadline(g_platform->MonotonicallyIncreasingTime());
}


// Realm.switch(i) switches to the realm i for consecutive interactive inputs.
void Shell::RealmSwitch(const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();
  PerIsolateData* data = PerIsolateData::Get(isolate);
  int index = data->RealmIndexOrThrow(args, 0);
  if (index == -1) return;
  data->realm_switch_ = index;
}


// Realm.eval(i, s) evaluates s in realm i and returns the result.
void Shell::RealmEval(const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();
  PerIsolateData* data = PerIsolateData::Get(isolate);
  int index = data->RealmIndexOrThrow(args, 0);
  if (index == -1) return;
  if (args.Length() < 2 || !args[1]->IsString()) {
    Throw(args.GetIsolate(), "Invalid argument");
    return;
  }
  ScriptCompiler::Source script_source(
      args[1]->ToString(isolate->GetCurrentContext()).ToLocalChecked());
  Local<UnboundScript> script;
  if (!ScriptCompiler::CompileUnboundScript(isolate, &script_source)
           .ToLocal(&script)) {
    return;
  }
  Local<Context> realm = Local<Context>::New(isolate, data->realms_[index]);
  realm->Enter();
  Local<Value> result;
  if (!script->BindToCurrentContext()->Run(realm).ToLocal(&result)) {
    realm->Exit();
    return;
  }
  realm->Exit();
  args.GetReturnValue().Set(result);
}


// Realm.shared is an accessor for a single shared value across realms.
void Shell::RealmSharedGet(Local<String> property,
                           const PropertyCallbackInfo<Value>& info) {
  Isolate* isolate = info.GetIsolate();
  PerIsolateData* data = PerIsolateData::Get(isolate);
  if (data->realm_shared_.IsEmpty()) return;
  info.GetReturnValue().Set(data->realm_shared_);
}

void Shell::RealmSharedSet(Local<String> property,
                           Local<Value> value,
                           const PropertyCallbackInfo<void>& info) {
  Isolate* isolate = info.GetIsolate();
  PerIsolateData* data = PerIsolateData::Get(isolate);
  data->realm_shared_.Reset(isolate, value);
}


void Shell::Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
  Write(args);
  printf("\n");
  fflush(stdout);
}


void Shell::Write(const v8::FunctionCallbackInfo<v8::Value>& args) {
  for (int i = 0; i < args.Length(); i++) {
    HandleScope handle_scope(args.GetIsolate());
    if (i != 0) {
      printf(" ");
    }

    // Explicitly catch potential exceptions in toString().
    v8::TryCatch try_catch(args.GetIsolate());
    Local<Value> arg = args[i];
    Local<String> str_obj;

    if (arg->IsSymbol()) {
      arg = Local<Symbol>::Cast(arg)->Name();
    }
    if (!arg->ToString(args.GetIsolate()->GetCurrentContext())
             .ToLocal(&str_obj)) {
      try_catch.ReThrow();
      return;
    }

    v8::String::Utf8Value str(str_obj);
    int n = static_cast<int>(fwrite(*str, sizeof(**str), str.length(), stdout));
    if (n != str.length()) {
      printf("Error in fwrite\n");
      Exit(1);
    }
  }
}


void Shell::Read(const v8::FunctionCallbackInfo<v8::Value>& args) {
  String::Utf8Value file(args[0]);
  if (*file == NULL) {
    Throw(args.GetIsolate(), "Error loading file");
    return;
  }
  Local<String> source = ReadFile(args.GetIsolate(), *file);
  if (source.IsEmpty()) {
    Throw(args.GetIsolate(), "Error loading file");
    return;
  }
  args.GetReturnValue().Set(source);
}


Local<String> Shell::ReadFromStdin(Isolate* isolate) {
  static const int kBufferSize = 256;
  char buffer[kBufferSize];
  Local<String> accumulator =
      String::NewFromUtf8(isolate, "", NewStringType::kNormal).ToLocalChecked();
  int length;
  while (true) {
    // Continue reading if the line ends with an escape '\\' or the line has
    // not been fully read into the buffer yet (does not end with '\n').
    // If fgets gets an error, just give up.
    char* input = NULL;
    input = fgets(buffer, kBufferSize, stdin);
    if (input == NULL) return Local<String>();
    length = static_cast<int>(strlen(buffer));
    if (length == 0) {
      return accumulator;
    } else if (buffer[length-1] != '\n') {
      accumulator = String::Concat(
          accumulator,
          String::NewFromUtf8(isolate, buffer, NewStringType::kNormal, length)
              .ToLocalChecked());
    } else if (length > 1 && buffer[length-2] == '\\') {
      buffer[length-2] = '\n';
      accumulator = String::Concat(
          accumulator,
          String::NewFromUtf8(isolate, buffer, NewStringType::kNormal,
                              length - 1).ToLocalChecked());
    } else {
      return String::Concat(
          accumulator,
          String::NewFromUtf8(isolate, buffer, NewStringType::kNormal,
                              length - 1).ToLocalChecked());
    }
  }
}


void Shell::Load(const v8::FunctionCallbackInfo<v8::Value>& args) {
  for (int i = 0; i < args.Length(); i++) {
    HandleScope handle_scope(args.GetIsolate());
    String::Utf8Value file(args[i]);
    if (*file == NULL) {
      Throw(args.GetIsolate(), "Error loading file");
      return;
    }
    Local<String> source = ReadFile(args.GetIsolate(), *file);
    if (source.IsEmpty()) {
      Throw(args.GetIsolate(), "Error loading file");
      return;
    }
    if (!ExecuteString(
            args.GetIsolate(), source,
            String::NewFromUtf8(args.GetIsolate(), *file,
                                NewStringType::kNormal).ToLocalChecked(),
            false, true)) {
      Throw(args.GetIsolate(), "Error executing file");
      return;
    }
  }
}


#ifndef V8_SHARED
void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();
  HandleScope handle_scope(isolate);
  if (args.Length() < 1 || !args[0]->IsString()) {
    Throw(args.GetIsolate(), "1st argument must be string");
    return;
  }

  if (!args.IsConstructCall()) {
    Throw(args.GetIsolate(), "Worker must be constructed with new");
    return;
  }

  {
    base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer());
    if (workers_.length() >= kMaxWorkers) {
      Throw(args.GetIsolate(), "Too many workers, I won't let you create more");
      return;
    }

    // Initialize the internal field to NULL; if we return early without
    // creating a new Worker (because the main thread is terminating) we can
    // early-out from the instance calls.
    args.Holder()->SetAlignedPointerInInternalField(0, NULL);

    if (!allow_new_workers_) return;

    Worker* worker = new Worker;
    args.Holder()->SetAlignedPointerInInternalField(0, worker);
    workers_.Add(worker);

    String::Utf8Value script(args[0]);
    if (!*script) {
      Throw(args.GetIsolate(), "Can't get worker script");
      return;
    }
    worker->StartExecuteInThread(*script);
  }
}


void Shell::WorkerPostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();
  HandleScope handle_scope(isolate);
  Local<Context> context = isolate->GetCurrentContext();

  if (args.Length() < 1) {
    Throw(isolate, "Invalid argument");
    return;
  }

  Worker* worker = GetWorkerFromInternalField(isolate, args.Holder());
  if (!worker) {
    return;
  }

  Local<Value> message = args[0];
  ObjectList to_transfer;
  if (args.Length() >= 2) {
    if (!args[1]->IsArray()) {
      Throw(isolate, "Transfer list must be an Array");
      return;
    }

    Local<Array> transfer = Local<Array>::Cast(args[1]);
    uint32_t length = transfer->Length();
    for (uint32_t i = 0; i < length; ++i) {
      Local<Value> element;
      if (transfer->Get(context, i).ToLocal(&element)) {
        if (!element->IsArrayBuffer() && !element->IsSharedArrayBuffer()) {
          Throw(isolate,
                "Transfer array elements must be an ArrayBuffer or "
                "SharedArrayBuffer.");
          break;
        }

        to_transfer.Add(Local<Object>::Cast(element));
      }
    }
  }

  ObjectList seen_objects;
  SerializationData* data = new SerializationData;
  if (SerializeValue(isolate, message, to_transfer, &seen_objects, data)) {
    worker->PostMessage(data);
  } else {
    delete data;
  }
}


void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();
  HandleScope handle_scope(isolate);
  Worker* worker = GetWorkerFromInternalField(isolate, args.Holder());
  if (!worker) {
    return;
  }

  SerializationData* data = worker->GetMessage();
  if (data) {
    int offset = 0;
    Local<Value> data_value;
    if (Shell::DeserializeValue(isolate, *data, &offset).ToLocal(&data_value)) {
      args.GetReturnValue().Set(data_value);
    }
    delete data;
  }
}


void Shell::WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();
  HandleScope handle_scope(isolate);
  Worker* worker = GetWorkerFromInternalField(isolate, args.Holder());
  if (!worker) {
    return;
  }

  worker->Terminate();
}
#endif  // !V8_SHARED


void Shell::QuitOnce(v8::FunctionCallbackInfo<v8::Value>* args) {
  int exit_code = (*args)[0]
                      ->Int32Value(args->GetIsolate()->GetCurrentContext())
                      .FromMaybe(0);
#ifndef V8_SHARED
  CleanupWorkers();
#endif  // !V8_SHARED
  OnExit(args->GetIsolate());
  Exit(exit_code);
}


void Shell::Quit(const v8::FunctionCallbackInfo<v8::Value>& args) {
  base::CallOnce(&quit_once_, &QuitOnce,
                 const_cast<v8::FunctionCallbackInfo<v8::Value>*>(&args));
}


void Shell::Version(const v8::FunctionCallbackInfo<v8::Value>& args) {
  args.GetReturnValue().Set(
      String::NewFromUtf8(args.GetIsolate(), V8::GetVersion(),
                          NewStringType::kNormal).ToLocalChecked());
}


void Shell::ReportException(Isolate* isolate, v8::TryCatch* try_catch) {
  HandleScope handle_scope(isolate);
#ifndef V8_SHARED
  Local<Context> utility_context;
  bool enter_context = !isolate->InContext();
  if (enter_context) {
    utility_context = Local<Context>::New(isolate, utility_context_);
    utility_context->Enter();
  }
#endif  // !V8_SHARED
  v8::String::Utf8Value exception(try_catch->Exception());
  const char* exception_string = ToCString(exception);
  Local<Message> message = try_catch->Message();
  if (message.IsEmpty()) {
    // V8 didn't provide any extra information about this error; just
    // print the exception.
    printf("%s\n", exception_string);
  } else {
    // Print (filename):(line number): (message).
    v8::String::Utf8Value filename(message->GetScriptOrigin().ResourceName());
    const char* filename_string = ToCString(filename);
    int linenum =
        message->GetLineNumber(isolate->GetCurrentContext()).FromJust();
    printf("%s:%i: %s\n", filename_string, linenum, exception_string);
    // Print line of source code.
    v8::String::Utf8Value sourceline(
        message->GetSourceLine(isolate->GetCurrentContext()).ToLocalChecked());
    const char* sourceline_string = ToCString(sourceline);
    printf("%s\n", sourceline_string);
    // Print wavy underline (GetUnderline is deprecated).
    int start =
        message->GetStartColumn(isolate->GetCurrentContext()).FromJust();
    for (int i = 0; i < start; i++) {
      printf(" ");
    }
    int end = message->GetEndColumn(isolate->GetCurrentContext()).FromJust();
    for (int i = start; i < end; i++) {
      printf("^");
    }
    printf("\n");
    Local<Value> stack_trace_string;
    if (try_catch->StackTrace(isolate->GetCurrentContext())
            .ToLocal(&stack_trace_string) &&
        stack_trace_string->IsString()) {
      v8::String::Utf8Value stack_trace(
          Local<String>::Cast(stack_trace_string));
      printf("%s\n", ToCString(stack_trace));
    }
  }
  printf("\n");
#ifndef V8_SHARED
  if (enter_context) utility_context->Exit();
#endif  // !V8_SHARED
}


#ifndef V8_SHARED
int32_t* Counter::Bind(const char* name, bool is_histogram) {
  int i;
  for (i = 0; i < kMaxNameSize - 1 && name[i]; i++)
    name_[i] = static_cast<char>(name[i]);
  name_[i] = '\0';
  is_histogram_ = is_histogram;
  return ptr();
}


void Counter::AddSample(int32_t sample) {
  count_++;
  sample_total_ += sample;
}


CounterCollection::CounterCollection() {
  magic_number_ = 0xDEADFACE;
  max_counters_ = kMaxCounters;
  max_name_size_ = Counter::kMaxNameSize;
  counters_in_use_ = 0;
}


Counter* CounterCollection::GetNextCounter() {
  if (counters_in_use_ == kMaxCounters) return NULL;
  return &counters_[counters_in_use_++];
}


void Shell::MapCounters(v8::Isolate* isolate, const char* name) {
  counters_file_ = base::OS::MemoryMappedFile::create(
      name, sizeof(CounterCollection), &local_counters_);
  void* memory = (counters_file_ == NULL) ?
      NULL : counters_file_->memory();
  if (memory == NULL) {
    printf("Could not map counters file %s\n", name);
    Exit(1);
  }
  counters_ = static_cast<CounterCollection*>(memory);
  isolate->SetCounterFunction(LookupCounter);
  isolate->SetCreateHistogramFunction(CreateHistogram);
  isolate->SetAddHistogramSampleFunction(AddHistogramSample);
}


int CounterMap::Hash(const char* name) {
  int h = 0;
  int c;
  while ((c = *name++) != 0) {
    h += h << 5;
    h += c;
  }
  return h;
}


Counter* Shell::GetCounter(const char* name, bool is_histogram) {
  Counter* counter = counter_map_->Lookup(name);

  if (counter == NULL) {
    counter = counters_->GetNextCounter();
    if (counter != NULL) {
      counter_map_->Set(name, counter);
      counter->Bind(name, is_histogram);
    }
  } else {
    DCHECK(counter->is_histogram() == is_histogram);
  }
  return counter;
}


int* Shell::LookupCounter(const char* name) {
  Counter* counter = GetCounter(name, false);

  if (counter != NULL) {
    return counter->ptr();
  } else {
    return NULL;
  }
}


void* Shell::CreateHistogram(const char* name,
                             int min,
                             int max,
                             size_t buckets) {
  return GetCounter(name, true);
}


void Shell::AddHistogramSample(void* histogram, int sample) {
  Counter* counter = reinterpret_cast<Counter*>(histogram);
  counter->AddSample(sample);
}


class NoUseStrongForUtilityScriptScope {
 public:
  NoUseStrongForUtilityScriptScope() : flag_(i::FLAG_use_strong) {
    i::FLAG_use_strong = false;
  }
  ~NoUseStrongForUtilityScriptScope() { i::FLAG_use_strong = flag_; }

 private:
  bool flag_;
};


void Shell::InstallUtilityScript(Isolate* isolate) {
  NoUseStrongForUtilityScriptScope no_use_strong;
  HandleScope scope(isolate);
  // If we use the utility context, we have to set the security tokens so that
  // utility, evaluation and debug context can all access each other.
  Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
  utility_context_.Reset(isolate, Context::New(isolate, NULL, global_template));
  v8::Local<v8::Context> utility_context =
      v8::Local<v8::Context>::New(isolate, utility_context_);
  v8::Local<v8::Context> evaluation_context =
      v8::Local<v8::Context>::New(isolate, evaluation_context_);
  utility_context->SetSecurityToken(Undefined(isolate));
  evaluation_context->SetSecurityToken(Undefined(isolate));
  v8::Context::Scope context_scope(utility_context);

  // Run the d8 shell utility script in the utility context
  int source_index = i::NativesCollection<i::D8>::GetIndex("d8");
  i::Vector<const char> shell_source =
      i::NativesCollection<i::D8>::GetScriptSource(source_index);
  i::Vector<const char> shell_source_name =
      i::NativesCollection<i::D8>::GetScriptName(source_index);
  Local<String> source =
      String::NewFromUtf8(isolate, shell_source.start(), NewStringType::kNormal,
                          shell_source.length()).ToLocalChecked();
  Local<String> name =
      String::NewFromUtf8(isolate, shell_source_name.start(),
                          NewStringType::kNormal,
                          shell_source_name.length()).ToLocalChecked();
  ScriptOrigin origin(name);
  Local<Script> script =
      Script::Compile(utility_context, source, &origin).ToLocalChecked();
  script->Run(utility_context).ToLocalChecked();
  // Mark the d8 shell script as native to avoid it showing up as normal source
  // in the debugger.
  i::Handle<i::Object> compiled_script = Utils::OpenHandle(*script);
  i::Handle<i::Script> script_object = compiled_script->IsJSFunction()
      ? i::Handle<i::Script>(i::Script::cast(
          i::JSFunction::cast(*compiled_script)->shared()->script()))
      : i::Handle<i::Script>(i::Script::cast(
          i::SharedFunctionInfo::cast(*compiled_script)->script()));
  script_object->set_type(i::Script::TYPE_EXTENSION);
}
#endif  // !V8_SHARED


Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
  Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
  global_template->Set(
      String::NewFromUtf8(isolate, "print", NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate, Print));
  global_template->Set(
      String::NewFromUtf8(isolate, "write", NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate, Write));
  global_template->Set(
      String::NewFromUtf8(isolate, "read", NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate, Read));
  global_template->Set(
      String::NewFromUtf8(isolate, "readbuffer", NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate, ReadBuffer));
  global_template->Set(
      String::NewFromUtf8(isolate, "readline", NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate, ReadLine));
  global_template->Set(
      String::NewFromUtf8(isolate, "load", NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate, Load));
  // Some Emscripten-generated code tries to call 'quit', which in turn would
  // call C's exit(). This would lead to memory leaks, because there is no way
  // we can terminate cleanly then, so we need a way to hide 'quit'.
  if (!options.omit_quit) {
    global_template->Set(
        String::NewFromUtf8(isolate, "quit", NewStringType::kNormal)
            .ToLocalChecked(),
        FunctionTemplate::New(isolate, Quit));
  }
  global_template->Set(
      String::NewFromUtf8(isolate, "version", NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate, Version));

  // Bind the Realm object.
  Local<ObjectTemplate> realm_template = ObjectTemplate::New(isolate);
  realm_template->Set(
      String::NewFromUtf8(isolate, "current", NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate, RealmCurrent));
  realm_template->Set(
      String::NewFromUtf8(isolate, "owner", NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate, RealmOwner));
  realm_template->Set(
      String::NewFromUtf8(isolate, "global", NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate, RealmGlobal));
  realm_template->Set(
      String::NewFromUtf8(isolate, "create", NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate, RealmCreate));
  realm_template->Set(
      String::NewFromUtf8(isolate, "dispose", NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate, RealmDispose));
  realm_template->Set(
      String::NewFromUtf8(isolate, "switch", NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate, RealmSwitch));
  realm_template->Set(
      String::NewFromUtf8(isolate, "eval", NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate, RealmEval));
  realm_template->SetAccessor(
      String::NewFromUtf8(isolate, "shared", NewStringType::kNormal)
          .ToLocalChecked(),
      RealmSharedGet, RealmSharedSet);
  global_template->Set(
      String::NewFromUtf8(isolate, "Realm", NewStringType::kNormal)
          .ToLocalChecked(),
      realm_template);

#ifndef V8_SHARED
  Local<ObjectTemplate> performance_template = ObjectTemplate::New(isolate);
  performance_template->Set(
      String::NewFromUtf8(isolate, "now", NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate, PerformanceNow));
  global_template->Set(
      String::NewFromUtf8(isolate, "performance", NewStringType::kNormal)
          .ToLocalChecked(),
      performance_template);

  Local<FunctionTemplate> worker_fun_template =
      FunctionTemplate::New(isolate, WorkerNew);
  Local<Signature> worker_signature =
      Signature::New(isolate, worker_fun_template);
  worker_fun_template->SetClassName(
      String::NewFromUtf8(isolate, "Worker", NewStringType::kNormal)
          .ToLocalChecked());
  worker_fun_template->ReadOnlyPrototype();
  worker_fun_template->PrototypeTemplate()->Set(
      String::NewFromUtf8(isolate, "terminate", NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate, WorkerTerminate, Local<Value>(),
                            worker_signature));
  worker_fun_template->PrototypeTemplate()->Set(
      String::NewFromUtf8(isolate, "postMessage", NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate, WorkerPostMessage, Local<Value>(),
                            worker_signature));
  worker_fun_template->PrototypeTemplate()->Set(
      String::NewFromUtf8(isolate, "getMessage", NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate, WorkerGetMessage, Local<Value>(),
                            worker_signature));
  worker_fun_template->InstanceTemplate()->SetInternalFieldCount(1);
  global_template->Set(
      String::NewFromUtf8(isolate, "Worker", NewStringType::kNormal)
          .ToLocalChecked(),
      worker_fun_template);
#endif  // !V8_SHARED

  Local<ObjectTemplate> os_templ = ObjectTemplate::New(isolate);
  AddOSMethods(isolate, os_templ);
  global_template->Set(
      String::NewFromUtf8(isolate, "os", NewStringType::kNormal)
          .ToLocalChecked(),
      os_templ);

  return global_template;
}

static void EmptyMessageCallback(Local<Message> message, Local<Value> error) {
  // Nothing to be done here, exceptions thrown up to the shell will be reported
  // separately by {Shell::ReportException} after they are caught.
}

void Shell::Initialize(Isolate* isolate) {
#ifndef V8_SHARED
  // Set up counters
  if (i::StrLength(i::FLAG_map_counters) != 0)
    MapCounters(isolate, i::FLAG_map_counters);
#endif  // !V8_SHARED
  // Disable default message reporting.
  isolate->AddMessageListener(EmptyMessageCallback);
}


Local<Context> Shell::CreateEvaluationContext(Isolate* isolate) {
#ifndef V8_SHARED
  // This needs to be a critical section since this is not thread-safe
  base::LockGuard<base::Mutex> lock_guard(context_mutex_.Pointer());
#endif  // !V8_SHARED
  // Initialize the global objects
  Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
  EscapableHandleScope handle_scope(isolate);
  Local<Context> context = Context::New(isolate, NULL, global_template);
  DCHECK(!context.IsEmpty());
  Context::Scope scope(context);

#ifndef V8_SHARED
  i::Factory* factory = reinterpret_cast<i::Isolate*>(isolate)->factory();
  i::JSArguments js_args = i::FLAG_js_arguments;
  i::Handle<i::FixedArray> arguments_array =
      factory->NewFixedArray(js_args.argc);
  for (int j = 0; j < js_args.argc; j++) {
    i::Handle<i::String> arg =
        factory->NewStringFromUtf8(i::CStrVector(js_args[j])).ToHandleChecked();
    arguments_array->set(j, *arg);
  }
  i::Handle<i::JSArray> arguments_jsarray =
      factory->NewJSArrayWithElements(arguments_array);
  context->Global()
      ->Set(context,
            String::NewFromUtf8(isolate, "arguments", NewStringType::kNormal)
                .ToLocalChecked(),
            Utils::ToLocal(arguments_jsarray))
      .FromJust();
#endif  // !V8_SHARED
  return handle_scope.Escape(context);
}


void Shell::Exit(int exit_code) {
  // Use _exit instead of exit to avoid races between isolate
  // threads and static destructors.
  fflush(stdout);
  fflush(stderr);
  _exit(exit_code);
}


#ifndef V8_SHARED
struct CounterAndKey {
  Counter* counter;
  const char* key;
};


inline bool operator<(const CounterAndKey& lhs, const CounterAndKey& rhs) {
  return strcmp(lhs.key, rhs.key) < 0;
}
#endif  // !V8_SHARED


void Shell::OnExit(v8::Isolate* isolate) {
#ifndef V8_SHARED
  reinterpret_cast<i::Isolate*>(isolate)->DumpAndResetCompilationStats();
  if (i::FLAG_dump_counters) {
    int number_of_counters = 0;
    for (CounterMap::Iterator i(counter_map_); i.More(); i.Next()) {
      number_of_counters++;
    }
    CounterAndKey* counters = new CounterAndKey[number_of_counters];
    int j = 0;
    for (CounterMap::Iterator i(counter_map_); i.More(); i.Next(), j++) {
      counters[j].counter = i.CurrentValue();
      counters[j].key = i.CurrentKey();
    }
    std::sort(counters, counters + number_of_counters);
    printf("+----------------------------------------------------------------+"
           "-------------+\n");
    printf("| Name                                                           |"
           " Value       |\n");
    printf("+----------------------------------------------------------------+"
           "-------------+\n");
    for (j = 0; j < number_of_counters; j++) {
      Counter* counter = counters[j].counter;
      const char* key = counters[j].key;
      if (counter->is_histogram()) {
        printf("| c:%-60s | %11i |\n", key, counter->count());
        printf("| t:%-60s | %11i |\n", key, counter->sample_total());
      } else {
        printf("| %-62s | %11i |\n", key, counter->count());
      }
    }
    printf("+----------------------------------------------------------------+"
           "-------------+\n");
    delete [] counters;
  }
  delete counters_file_;
  delete counter_map_;
#endif  // !V8_SHARED
}



static FILE* FOpen(const char* path, const char* mode) {
#if defined(_MSC_VER) && (defined(_WIN32) || defined(_WIN64))
  FILE* result;
  if (fopen_s(&result, path, mode) == 0) {
    return result;
  } else {
    return NULL;
  }
#else
  FILE* file = fopen(path, mode);
  if (file == NULL) return NULL;
  struct stat file_stat;
  if (fstat(fileno(file), &file_stat) != 0) return NULL;
  bool is_regular_file = ((file_stat.st_mode & S_IFREG) != 0);
  if (is_regular_file) return file;
  fclose(file);
  return NULL;
#endif
}


static char* ReadChars(Isolate* isolate, const char* name, int* size_out) {
  FILE* file = FOpen(name, "rb");
  if (file == NULL) return NULL;

  fseek(file, 0, SEEK_END);
  size_t size = ftell(file);
  rewind(file);

  char* chars = new char[size + 1];
  chars[size] = '\0';
  for (size_t i = 0; i < size;) {
    i += fread(&chars[i], 1, size - i, file);
    if (ferror(file)) {
      fclose(file);
      delete[] chars;
      return nullptr;
    }
  }
  fclose(file);
  *size_out = static_cast<int>(size);
  return chars;
}


struct DataAndPersistent {
  uint8_t* data;
  int byte_length;
  Global<ArrayBuffer> handle;
};


static void ReadBufferWeakCallback(
    const v8::WeakCallbackInfo<DataAndPersistent>& data) {
  int byte_length = data.GetParameter()->byte_length;
  data.GetIsolate()->AdjustAmountOfExternalAllocatedMemory(
      -static_cast<intptr_t>(byte_length));

  delete[] data.GetParameter()->data;
  data.GetParameter()->handle.Reset();
  delete data.GetParameter();
}


void Shell::ReadBuffer(const v8::FunctionCallbackInfo<v8::Value>& args) {
  DCHECK(sizeof(char) == sizeof(uint8_t));  // NOLINT
  String::Utf8Value filename(args[0]);
  int length;
  if (*filename == NULL) {
    Throw(args.GetIsolate(), "Error loading file");
    return;
  }

  Isolate* isolate = args.GetIsolate();
  DataAndPersistent* data = new DataAndPersistent;
  data->data = reinterpret_cast<uint8_t*>(
      ReadChars(args.GetIsolate(), *filename, &length));
  if (data->data == NULL) {
    delete data;
    Throw(args.GetIsolate(), "Error reading file");
    return;
  }
  data->byte_length = length;
  Local<v8::ArrayBuffer> buffer = ArrayBuffer::New(isolate, data->data, length);
  data->handle.Reset(isolate, buffer);
  data->handle.SetWeak(data, ReadBufferWeakCallback,
                       v8::WeakCallbackType::kParameter);
  data->handle.MarkIndependent();
  isolate->AdjustAmountOfExternalAllocatedMemory(length);

  args.GetReturnValue().Set(buffer);
}


// Reads a file into a v8 string.
Local<String> Shell::ReadFile(Isolate* isolate, const char* name) {
  int size = 0;
  char* chars = ReadChars(isolate, name, &size);
  if (chars == NULL) return Local<String>();
  Local<String> result =
      String::NewFromUtf8(isolate, chars, NewStringType::kNormal, size)
          .ToLocalChecked();
  delete[] chars;
  return result;
}


void Shell::RunShell(Isolate* isolate) {
  HandleScope outer_scope(isolate);
  v8::Local<v8::Context> context =
      v8::Local<v8::Context>::New(isolate, evaluation_context_);
  v8::Context::Scope context_scope(context);
  PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
  Local<String> name =
      String::NewFromUtf8(isolate, "(d8)", NewStringType::kNormal)
          .ToLocalChecked();
  printf("V8 version %s\n", V8::GetVersion());
  while (true) {
    HandleScope inner_scope(isolate);
    printf("d8> ");
#if defined(__native_client__)
    // Native Client libc is used to being embedded in Chrome and
    // has trouble recognizing when to flush.
    fflush(stdout);
#endif
    Local<String> input = Shell::ReadFromStdin(isolate);
    if (input.IsEmpty()) break;
    ExecuteString(isolate, input, name, true, true);
  }
  printf("\n");
}


SourceGroup::~SourceGroup() {
#ifndef V8_SHARED
  delete thread_;
  thread_ = NULL;
#endif  // !V8_SHARED
}


void SourceGroup::Execute(Isolate* isolate) {
  bool exception_was_thrown = false;
  for (int i = begin_offset_; i < end_offset_; ++i) {
    const char* arg = argv_[i];
    Shell::SourceType source_type = Shell::SCRIPT;
    if (strcmp(arg, "-e") == 0 && i + 1 < end_offset_) {
      // Execute argument given to -e option directly.
      HandleScope handle_scope(isolate);
      Local<String> file_name =
          String::NewFromUtf8(isolate, "unnamed", NewStringType::kNormal)
              .ToLocalChecked();
      Local<String> source =
          String::NewFromUtf8(isolate, argv_[i + 1], NewStringType::kNormal)
              .ToLocalChecked();
      Shell::options.script_executed = true;
      if (!Shell::ExecuteString(isolate, source, file_name, false, true)) {
        exception_was_thrown = true;
        break;
      }
      ++i;
      continue;
    } else if (strcmp(arg, "--module") == 0 && i + 1 < end_offset_) {
      // Treat the next file as a module.
      source_type = Shell::MODULE;
      arg = argv_[++i];
    } else if (arg[0] == '-') {
      // Ignore other options. They have been parsed already.
      continue;
    }

    // Use all other arguments as names of files to load and run.
    HandleScope handle_scope(isolate);
    Local<String> file_name =
        String::NewFromUtf8(isolate, arg, NewStringType::kNormal)
            .ToLocalChecked();
    Local<String> source = ReadFile(isolate, arg);
    if (source.IsEmpty()) {
      printf("Error reading '%s'\n", arg);
      Shell::Exit(1);
    }
    Shell::options.script_executed = true;
    if (!Shell::ExecuteString(isolate, source, file_name, false, true,
                              source_type)) {
      exception_was_thrown = true;
      break;
    }
  }
  if (exception_was_thrown != Shell::options.expected_to_throw) {
    Shell::Exit(1);
  }
}


Local<String> SourceGroup::ReadFile(Isolate* isolate, const char* name) {
  int size;
  char* chars = ReadChars(isolate, name, &size);
  if (chars == NULL) return Local<String>();
  Local<String> result =
      String::NewFromUtf8(isolate, chars, NewStringType::kNormal, size)
          .ToLocalChecked();
  delete[] chars;
  return result;
}


#ifndef V8_SHARED
base::Thread::Options SourceGroup::GetThreadOptions() {
  // On some systems (OSX 10.6) the stack size default is 0.5Mb or less
  // which is not enough to parse the big literal expressions used in tests.
  // The stack size should be at least StackGuard::kLimitSize + some
  // OS-specific padding for thread startup code.  2Mbytes seems to be enough.
  return base::Thread::Options("IsolateThread", 2 * MB);
}


void SourceGroup::ExecuteInThread() {
  Isolate::CreateParams create_params;
  create_params.array_buffer_allocator = Shell::array_buffer_allocator;
  Isolate* isolate = Isolate::New(create_params);
  for (int i = 0; i < Shell::options.stress_runs; ++i) {
    next_semaphore_.Wait();
    {
      Isolate::Scope iscope(isolate);
      {
        HandleScope scope(isolate);
        PerIsolateData data(isolate);
        Local<Context> context = Shell::CreateEvaluationContext(isolate);
        {
          Context::Scope cscope(context);
          PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
          Execute(isolate);
        }
      }
      Shell::CollectGarbage(isolate);
    }
    done_semaphore_.Signal();
  }

  isolate->Dispose();
}


void SourceGroup::StartExecuteInThread() {
  if (thread_ == NULL) {
    thread_ = new IsolateThread(this);
    thread_->Start();
  }
  next_semaphore_.Signal();
}


void SourceGroup::WaitForThread() {
  if (thread_ == NULL) return;
  done_semaphore_.Wait();
}


void SourceGroup::JoinThread() {
  if (thread_ == NULL) return;
  thread_->Join();
}


SerializationData::~SerializationData() {
  // Any ArrayBuffer::Contents are owned by this SerializationData object if
  // ownership hasn't been transferred out via ReadArrayBufferContents.
  // SharedArrayBuffer::Contents may be used by multiple threads, so must be
  // cleaned up by the main thread in Shell::CleanupWorkers().
  for (int i = 0; i < array_buffer_contents_.length(); ++i) {
    ArrayBuffer::Contents& contents = array_buffer_contents_[i];
    if (contents.Data()) {
      Shell::array_buffer_allocator->Free(contents.Data(),
                                          contents.ByteLength());
    }
  }
}


void SerializationData::WriteTag(SerializationTag tag) { data_.Add(tag); }


void SerializationData::WriteMemory(const void* p, int length) {
  if (length > 0) {
    i::Vector<uint8_t> block = data_.AddBlock(0, length);
    memcpy(&block[0], p, length);
  }
}


void SerializationData::WriteArrayBufferContents(
    const ArrayBuffer::Contents& contents) {
  array_buffer_contents_.Add(contents);
  WriteTag(kSerializationTagTransferredArrayBuffer);
  int index = array_buffer_contents_.length() - 1;
  Write(index);
}


void SerializationData::WriteSharedArrayBufferContents(
    const SharedArrayBuffer::Contents& contents) {
  shared_array_buffer_contents_.Add(contents);
  WriteTag(kSerializationTagTransferredSharedArrayBuffer);
  int index = shared_array_buffer_contents_.length() - 1;
  Write(index);
}


SerializationTag SerializationData::ReadTag(int* offset) const {
  return static_cast<SerializationTag>(Read<uint8_t>(offset));
}


void SerializationData::ReadMemory(void* p, int length, int* offset) const {
  if (length > 0) {
    memcpy(p, &data_[*offset], length);
    (*offset) += length;
  }
}


void SerializationData::ReadArrayBufferContents(ArrayBuffer::Contents* contents,
                                                int* offset) const {
  int index = Read<int>(offset);
  DCHECK(index < array_buffer_contents_.length());
  *contents = array_buffer_contents_[index];
  // Ownership of this ArrayBuffer::Contents is passed to the caller. Neuter
  // our copy so it won't be double-free'd when this SerializationData is
  // destroyed.
  array_buffer_contents_[index] = ArrayBuffer::Contents();
}


void SerializationData::ReadSharedArrayBufferContents(
    SharedArrayBuffer::Contents* contents, int* offset) const {
  int index = Read<int>(offset);
  DCHECK(index < shared_array_buffer_contents_.length());
  *contents = shared_array_buffer_contents_[index];
}


void SerializationDataQueue::Enqueue(SerializationData* data) {
  base::LockGuard<base::Mutex> lock_guard(&mutex_);
  data_.Add(data);
}


bool SerializationDataQueue::Dequeue(SerializationData** data) {
  base::LockGuard<base::Mutex> lock_guard(&mutex_);
  *data = NULL;
  if (data_.is_empty()) return false;
  *data = data_.Remove(0);
  return true;
}


bool SerializationDataQueue::IsEmpty() {
  base::LockGuard<base::Mutex> lock_guard(&mutex_);
  return data_.is_empty();
}


void SerializationDataQueue::Clear() {
  base::LockGuard<base::Mutex> lock_guard(&mutex_);
  for (int i = 0; i < data_.length(); ++i) {
    delete data_[i];
  }
  data_.Clear();
}


Worker::Worker()
    : in_semaphore_(0),
      out_semaphore_(0),
      thread_(NULL),
      script_(NULL),
      running_(false) {}


Worker::~Worker() {
  delete thread_;
  thread_ = NULL;
  delete[] script_;
  script_ = NULL;
  in_queue_.Clear();
  out_queue_.Clear();
}


void Worker::StartExecuteInThread(const char* script) {
  running_ = true;
  script_ = i::StrDup(script);
  thread_ = new WorkerThread(this);
  thread_->Start();
}


void Worker::PostMessage(SerializationData* data) {
  in_queue_.Enqueue(data);
  in_semaphore_.Signal();
}


SerializationData* Worker::GetMessage() {
  SerializationData* data = NULL;
  while (!out_queue_.Dequeue(&data)) {
    // If the worker is no longer running, and there are no messages in the
    // queue, don't expect any more messages from it.
    if (!base::NoBarrier_Load(&running_)) break;
    out_semaphore_.Wait();
  }
  return data;
}


void Worker::Terminate() {
  base::NoBarrier_Store(&running_, false);
  // Post NULL to wake the Worker thread message loop, and tell it to stop
  // running.
  PostMessage(NULL);
}


void Worker::WaitForThread() {
  Terminate();
  thread_->Join();
}


void Worker::ExecuteInThread() {
  Isolate::CreateParams create_params;
  create_params.array_buffer_allocator = Shell::array_buffer_allocator;
  Isolate* isolate = Isolate::New(create_params);
  {
    Isolate::Scope iscope(isolate);
    {
      HandleScope scope(isolate);
      PerIsolateData data(isolate);
      Local<Context> context = Shell::CreateEvaluationContext(isolate);
      {
        Context::Scope cscope(context);
        PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));

        Local<Object> global = context->Global();
        Local<Value> this_value = External::New(isolate, this);
        Local<FunctionTemplate> postmessage_fun_template =
            FunctionTemplate::New(isolate, PostMessageOut, this_value);

        Local<Function> postmessage_fun;
        if (postmessage_fun_template->GetFunction(context)
                .ToLocal(&postmessage_fun)) {
          global->Set(context, String::NewFromUtf8(isolate, "postMessage",
                                                   NewStringType::kNormal)
                                   .ToLocalChecked(),
                      postmessage_fun).FromJust();
        }

        // First run the script
        Local<String> file_name =
            String::NewFromUtf8(isolate, "unnamed", NewStringType::kNormal)
                .ToLocalChecked();
        Local<String> source =
            String::NewFromUtf8(isolate, script_, NewStringType::kNormal)
                .ToLocalChecked();
        if (Shell::ExecuteString(isolate, source, file_name, false, true)) {
          // Get the message handler
          Local<Value> onmessage =
              global->Get(context, String::NewFromUtf8(isolate, "onmessage",
                                                       NewStringType::kNormal)
                                       .ToLocalChecked()).ToLocalChecked();
          if (onmessage->IsFunction()) {
            Local<Function> onmessage_fun = Local<Function>::Cast(onmessage);
            // Now wait for messages
            while (true) {
              in_semaphore_.Wait();
              SerializationData* data;
              if (!in_queue_.Dequeue(&data)) continue;
              if (data == NULL) {
                break;
              }
              int offset = 0;
              Local<Value> data_value;
              if (Shell::DeserializeValue(isolate, *data, &offset)
                      .ToLocal(&data_value)) {
                Local<Value> argv[] = {data_value};
                (void)onmessage_fun->Call(context, global, 1, argv);
              }
              delete data;
            }
          }
        }
      }
    }
    Shell::CollectGarbage(isolate);
  }
  isolate->Dispose();

  // Post NULL to wake the thread waiting on GetMessage() if there is one.
  out_queue_.Enqueue(NULL);
  out_semaphore_.Signal();
}


void Worker::PostMessageOut(const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();
  HandleScope handle_scope(isolate);

  if (args.Length() < 1) {
    Throw(isolate, "Invalid argument");
    return;
  }

  Local<Value> message = args[0];

  // TODO(binji): Allow transferring from worker to main thread?
  Shell::ObjectList to_transfer;

  Shell::ObjectList seen_objects;
  SerializationData* data = new SerializationData;
  if (Shell::SerializeValue(isolate, message, to_transfer, &seen_objects,
                            data)) {
    DCHECK(args.Data()->IsExternal());
    Local<External> this_value = Local<External>::Cast(args.Data());
    Worker* worker = static_cast<Worker*>(this_value->Value());
    worker->out_queue_.Enqueue(data);
    worker->out_semaphore_.Signal();
  } else {
    delete data;
  }
}
#endif  // !V8_SHARED


void SetFlagsFromString(const char* flags) {
  v8::V8::SetFlagsFromString(flags, static_cast<int>(strlen(flags)));
}


bool Shell::SetOptions(int argc, char* argv[]) {
  bool logfile_per_isolate = false;
  for (int i = 0; i < argc; i++) {
    if (strcmp(argv[i], "--stress-opt") == 0) {
      options.stress_opt = true;
      argv[i] = NULL;
    } else if (strcmp(argv[i], "--nostress-opt") == 0) {
      options.stress_opt = false;
      argv[i] = NULL;
    } else if (strcmp(argv[i], "--stress-deopt") == 0) {
      options.stress_deopt = true;
      argv[i] = NULL;
    } else if (strcmp(argv[i], "--mock-arraybuffer-allocator") == 0) {
      options.mock_arraybuffer_allocator = true;
      argv[i] = NULL;
    } else if (strcmp(argv[i], "--noalways-opt") == 0) {
      // No support for stressing if we can't use --always-opt.
      options.stress_opt = false;
      options.stress_deopt = false;
    } else if (strcmp(argv[i], "--logfile-per-isolate") == 0) {
      logfile_per_isolate = true;
      argv[i] = NULL;
    } else if (strcmp(argv[i], "--shell") == 0) {
      options.interactive_shell = true;
      argv[i] = NULL;
    } else if (strcmp(argv[i], "--test") == 0) {
      options.test_shell = true;
      argv[i] = NULL;
    } else if (strcmp(argv[i], "--notest") == 0 ||
               strcmp(argv[i], "--no-test") == 0) {
      options.test_shell = false;
      argv[i] = NULL;
    } else if (strcmp(argv[i], "--send-idle-notification") == 0) {
      options.send_idle_notification = true;
      argv[i] = NULL;
    } else if (strcmp(argv[i], "--invoke-weak-callbacks") == 0) {
      options.invoke_weak_callbacks = true;
      // TODO(jochen) See issue 3351
      options.send_idle_notification = true;
      argv[i] = NULL;
    } else if (strcmp(argv[i], "--omit-quit") == 0) {
      options.omit_quit = true;
      argv[i] = NULL;
    } else if (strcmp(argv[i], "-f") == 0) {
      // Ignore any -f flags for compatibility with other stand-alone
      // JavaScript engines.
      continue;
    } else if (strcmp(argv[i], "--isolate") == 0) {
#ifdef V8_SHARED
      printf("D8 with shared library does not support multi-threading\n");
      return false;
#endif  // V8_SHARED
      options.num_isolates++;
    } else if (strcmp(argv[i], "--dump-heap-constants") == 0) {
#ifdef V8_SHARED
      printf("D8 with shared library does not support constant dumping\n");
      return false;
#else
      options.dump_heap_constants = true;
      argv[i] = NULL;
#endif  // V8_SHARED
    } else if (strcmp(argv[i], "--throws") == 0) {
      options.expected_to_throw = true;
      argv[i] = NULL;
    } else if (strncmp(argv[i], "--icu-data-file=", 16) == 0) {
      options.icu_data_file = argv[i] + 16;
      argv[i] = NULL;
#ifdef V8_SHARED
    } else if (strcmp(argv[i], "--dump-counters") == 0) {
      printf("D8 with shared library does not include counters\n");
      return false;
#endif  // V8_SHARED
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
    } else if (strncmp(argv[i], "--natives_blob=", 15) == 0) {
      options.natives_blob = argv[i] + 15;
      argv[i] = NULL;
    } else if (strncmp(argv[i], "--snapshot_blob=", 16) == 0) {
      options.snapshot_blob = argv[i] + 16;
      argv[i] = NULL;
#endif  // V8_USE_EXTERNAL_STARTUP_DATA
    } else if (strcmp(argv[i], "--cache") == 0 ||
               strncmp(argv[i], "--cache=", 8) == 0) {
      const char* value = argv[i] + 7;
      if (!*value || strncmp(value, "=code", 6) == 0) {
        options.compile_options = v8::ScriptCompiler::kProduceCodeCache;
      } else if (strncmp(value, "=parse", 7) == 0) {
        options.compile_options = v8::ScriptCompiler::kProduceParserCache;
      } else if (strncmp(value, "=none", 6) == 0) {
        options.compile_options = v8::ScriptCompiler::kNoCompileOptions;
      } else {
        printf("Unknown option to --cache.\n");
        return false;
      }
      argv[i] = NULL;
    }
  }

  v8::V8::SetFlagsFromCommandLine(&argc, argv, true);

  bool enable_harmony_modules = false;

  // Set up isolated source groups.
  options.isolate_sources = new SourceGroup[options.num_isolates];
  SourceGroup* current = options.isolate_sources;
  current->Begin(argv, 1);
  for (int i = 1; i < argc; i++) {
    const char* str = argv[i];
    if (strcmp(str, "--isolate") == 0) {
      current->End(i);
      current++;
      current->Begin(argv, i + 1);
    } else if (strcmp(str, "--module") == 0) {
      // Pass on to SourceGroup, which understands this option.
      enable_harmony_modules = true;
    } else if (strncmp(argv[i], "--", 2) == 0) {
      printf("Warning: unknown flag %s.\nTry --help for options\n", argv[i]);
    } else if (strcmp(str, "-e") == 0 && i + 1 < argc) {
      options.script_executed = true;
    } else if (strncmp(str, "-", 1) != 0) {
      // Not a flag, so it must be a script to execute.
      options.script_executed = true;
    }
  }
  current->End(argc);

  if (!logfile_per_isolate && options.num_isolates) {
    SetFlagsFromString("--nologfile_per_isolate");
  }

  if (enable_harmony_modules) {
    SetFlagsFromString("--harmony-modules");
  }

  return true;
}


int Shell::RunMain(Isolate* isolate, int argc, char* argv[], bool last_run) {
#ifndef V8_SHARED
  for (int i = 1; i < options.num_isolates; ++i) {
    options.isolate_sources[i].StartExecuteInThread();
  }
#endif  // !V8_SHARED
  {
    HandleScope scope(isolate);
    Local<Context> context = CreateEvaluationContext(isolate);
    if (last_run && options.use_interactive_shell()) {
      // Keep using the same context in the interactive shell.
      evaluation_context_.Reset(isolate, context);
    }
    {
      Context::Scope cscope(context);
      PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
      options.isolate_sources[0].Execute(isolate);
    }
  }
  CollectGarbage(isolate);
#ifndef V8_SHARED
  for (int i = 1; i < options.num_isolates; ++i) {
    if (last_run) {
      options.isolate_sources[i].JoinThread();
    } else {
      options.isolate_sources[i].WaitForThread();
    }
  }
  CleanupWorkers();
#endif  // !V8_SHARED
  return 0;
}


void Shell::CollectGarbage(Isolate* isolate) {
  if (options.send_idle_notification) {
    const double kLongIdlePauseInSeconds = 1.0;
    isolate->ContextDisposedNotification();
    isolate->IdleNotificationDeadline(
        g_platform->MonotonicallyIncreasingTime() + kLongIdlePauseInSeconds);
  }
  if (options.invoke_weak_callbacks) {
    // By sending a low memory notifications, we will try hard to collect all
    // garbage and will therefore also invoke all weak callbacks of actually
    // unreachable persistent handles.
    isolate->LowMemoryNotification();
  }
}


void Shell::EmptyMessageQueues(Isolate* isolate) {
#ifndef V8_SHARED
  if (!i::FLAG_verify_predictable) {
#endif
    while (v8::platform::PumpMessageLoop(g_platform, isolate)) continue;
#ifndef V8_SHARED
  }
#endif
}


#ifndef V8_SHARED
bool Shell::SerializeValue(Isolate* isolate, Local<Value> value,
                           const ObjectList& to_transfer,
                           ObjectList* seen_objects,
                           SerializationData* out_data) {
  DCHECK(out_data);
  Local<Context> context = isolate->GetCurrentContext();

  if (value->IsUndefined()) {
    out_data->WriteTag(kSerializationTagUndefined);
  } else if (value->IsNull()) {
    out_data->WriteTag(kSerializationTagNull);
  } else if (value->IsTrue()) {
    out_data->WriteTag(kSerializationTagTrue);
  } else if (value->IsFalse()) {
    out_data->WriteTag(kSerializationTagFalse);
  } else if (value->IsNumber()) {
    Local<Number> num = Local<Number>::Cast(value);
    double value = num->Value();
    out_data->WriteTag(kSerializationTagNumber);
    out_data->Write(value);
  } else if (value->IsString()) {
    v8::String::Utf8Value str(value);
    out_data->WriteTag(kSerializationTagString);
    out_data->Write(str.length());
    out_data->WriteMemory(*str, str.length());
  } else if (value->IsArray()) {
    Local<Array> array = Local<Array>::Cast(value);
    if (FindInObjectList(array, *seen_objects)) {
      Throw(isolate, "Duplicated arrays not supported");
      return false;
    }
    seen_objects->Add(array);
    out_data->WriteTag(kSerializationTagArray);
    uint32_t length = array->Length();
    out_data->Write(length);
    for (uint32_t i = 0; i < length; ++i) {
      Local<Value> element_value;
      if (array->Get(context, i).ToLocal(&element_value)) {
        if (!SerializeValue(isolate, element_value, to_transfer, seen_objects,
                            out_data))
          return false;
      } else {
        Throw(isolate, "Failed to serialize array element.");
        return false;
      }
    }
  } else if (value->IsArrayBuffer()) {
    Local<ArrayBuffer> array_buffer = Local<ArrayBuffer>::Cast(value);
    if (FindInObjectList(array_buffer, *seen_objects)) {
      Throw(isolate, "Duplicated array buffers not supported");
      return false;
    }
    seen_objects->Add(array_buffer);
    if (FindInObjectList(array_buffer, to_transfer)) {
      // Transfer ArrayBuffer
      if (!array_buffer->IsNeuterable()) {
        Throw(isolate, "Attempting to transfer an un-neuterable ArrayBuffer");
        return false;
      }

      ArrayBuffer::Contents contents = array_buffer->IsExternal()
                                           ? array_buffer->GetContents()
                                           : array_buffer->Externalize();
      array_buffer->Neuter();
      out_data->WriteArrayBufferContents(contents);
    } else {
      ArrayBuffer::Contents contents = array_buffer->GetContents();
      // Clone ArrayBuffer
      if (contents.ByteLength() > i::kMaxInt) {
        Throw(isolate, "ArrayBuffer is too big to clone");
        return false;
      }

      int32_t byte_length = static_cast<int32_t>(contents.ByteLength());
      out_data->WriteTag(kSerializationTagArrayBuffer);
      out_data->Write(byte_length);
      out_data->WriteMemory(contents.Data(), byte_length);
    }
  } else if (value->IsSharedArrayBuffer()) {
    Local<SharedArrayBuffer> sab = Local<SharedArrayBuffer>::Cast(value);
    if (FindInObjectList(sab, *seen_objects)) {
      Throw(isolate, "Duplicated shared array buffers not supported");
      return false;
    }
    seen_objects->Add(sab);
    if (!FindInObjectList(sab, to_transfer)) {
      Throw(isolate, "SharedArrayBuffer must be transferred");
      return false;
    }

    SharedArrayBuffer::Contents contents;
    if (sab->IsExternal()) {
      contents = sab->GetContents();
    } else {
      contents = sab->Externalize();
      base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer());
      externalized_shared_contents_.Add(contents);
    }
    out_data->WriteSharedArrayBufferContents(contents);
  } else if (value->IsObject()) {
    Local<Object> object = Local<Object>::Cast(value);
    if (FindInObjectList(object, *seen_objects)) {
      Throw(isolate, "Duplicated objects not supported");
      return false;
    }
    seen_objects->Add(object);
    Local<Array> property_names;
    if (!object->GetOwnPropertyNames(context).ToLocal(&property_names)) {
      Throw(isolate, "Unable to get property names");
      return false;
    }

    uint32_t length = property_names->Length();
    out_data->WriteTag(kSerializationTagObject);
    out_data->Write(length);
    for (uint32_t i = 0; i < length; ++i) {
      Local<Value> name;
      Local<Value> property_value;
      if (property_names->Get(context, i).ToLocal(&name) &&
          object->Get(context, name).ToLocal(&property_value)) {
        if (!SerializeValue(isolate, name, to_transfer, seen_objects, out_data))
          return false;
        if (!SerializeValue(isolate, property_value, to_transfer, seen_objects,
                            out_data))
          return false;
      } else {
        Throw(isolate, "Failed to serialize property.");
        return false;
      }
    }
  } else {
    Throw(isolate, "Don't know how to serialize object");
    return false;
  }

  return true;
}


MaybeLocal<Value> Shell::DeserializeValue(Isolate* isolate,
                                          const SerializationData& data,
                                          int* offset) {
  DCHECK(offset);
  EscapableHandleScope scope(isolate);
  // This function should not use utility_context_ because it is running on a
  // different thread.
  Local<Value> result;
  SerializationTag tag = data.ReadTag(offset);

  switch (tag) {
    case kSerializationTagUndefined:
      result = Undefined(isolate);
      break;
    case kSerializationTagNull:
      result = Null(isolate);
      break;
    case kSerializationTagTrue:
      result = True(isolate);
      break;
    case kSerializationTagFalse:
      result = False(isolate);
      break;
    case kSerializationTagNumber:
      result = Number::New(isolate, data.Read<double>(offset));
      break;
    case kSerializationTagString: {
      int length = data.Read<int>(offset);
      CHECK(length >= 0);
      std::vector<char> buffer(length + 1);  // + 1 so it is never empty.
      data.ReadMemory(&buffer[0], length, offset);
      MaybeLocal<String> str =
          String::NewFromUtf8(isolate, &buffer[0], NewStringType::kNormal,
                              length).ToLocalChecked();
      if (!str.IsEmpty()) result = str.ToLocalChecked();
      break;
    }
    case kSerializationTagArray: {
      uint32_t length = data.Read<uint32_t>(offset);
      Local<Array> array = Array::New(isolate, length);
      for (uint32_t i = 0; i < length; ++i) {
        Local<Value> element_value;
        CHECK(DeserializeValue(isolate, data, offset).ToLocal(&element_value));
        array->Set(isolate->GetCurrentContext(), i, element_value).FromJust();
      }
      result = array;
      break;
    }
    case kSerializationTagObject: {
      int length = data.Read<int>(offset);
      Local<Object> object = Object::New(isolate);
      for (int i = 0; i < length; ++i) {
        Local<Value> property_name;
        CHECK(DeserializeValue(isolate, data, offset).ToLocal(&property_name));
        Local<Value> property_value;
        CHECK(DeserializeValue(isolate, data, offset).ToLocal(&property_value));
        object->Set(isolate->GetCurrentContext(), property_name, property_value)
            .FromJust();
      }
      result = object;
      break;
    }
    case kSerializationTagArrayBuffer: {
      int32_t byte_length = data.Read<int32_t>(offset);
      Local<ArrayBuffer> array_buffer = ArrayBuffer::New(isolate, byte_length);
      ArrayBuffer::Contents contents = array_buffer->GetContents();
      DCHECK(static_cast<size_t>(byte_length) == contents.ByteLength());
      data.ReadMemory(contents.Data(), byte_length, offset);
      result = array_buffer;
      break;
    }
    case kSerializationTagTransferredArrayBuffer: {
      ArrayBuffer::Contents contents;
      data.ReadArrayBufferContents(&contents, offset);
      result = ArrayBuffer::New(isolate, contents.Data(), contents.ByteLength(),
                                ArrayBufferCreationMode::kInternalized);
      break;
    }
    case kSerializationTagTransferredSharedArrayBuffer: {
      SharedArrayBuffer::Contents contents;
      data.ReadSharedArrayBufferContents(&contents, offset);
      result = SharedArrayBuffer::New(isolate, contents.Data(),
                                      contents.ByteLength());
      break;
    }
    default:
      UNREACHABLE();
  }

  return scope.Escape(result);
}


void Shell::CleanupWorkers() {
  // Make a copy of workers_, because we don't want to call Worker::Terminate
  // while holding the workers_mutex_ lock. Otherwise, if a worker is about to
  // create a new Worker, it would deadlock.
  i::List<Worker*> workers_copy;
  {
    base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer());
    allow_new_workers_ = false;
    workers_copy.AddAll(workers_);
    workers_.Clear();
  }

  for (int i = 0; i < workers_copy.length(); ++i) {
    Worker* worker = workers_copy[i];
    worker->WaitForThread();
    delete worker;
  }

  // Now that all workers are terminated, we can re-enable Worker creation.
  base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer());
  allow_new_workers_ = true;

  for (int i = 0; i < externalized_shared_contents_.length(); ++i) {
    const SharedArrayBuffer::Contents& contents =
        externalized_shared_contents_[i];
    Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength());
  }
  externalized_shared_contents_.Clear();
}


static void DumpHeapConstants(i::Isolate* isolate) {
  i::Heap* heap = isolate->heap();

  // Dump the INSTANCE_TYPES table to the console.
  printf("# List of known V8 instance types.\n");
#define DUMP_TYPE(T) printf("  %d: \"%s\",\n", i::T, #T);
  printf("INSTANCE_TYPES = {\n");
  INSTANCE_TYPE_LIST(DUMP_TYPE)
  printf("}\n");
#undef DUMP_TYPE

  // Dump the KNOWN_MAP table to the console.
  printf("\n# List of known V8 maps.\n");
#define ROOT_LIST_CASE(type, name, camel_name) \
  if (n == NULL && o == heap->name()) n = #camel_name;
#define STRUCT_LIST_CASE(upper_name, camel_name, name) \
  if (n == NULL && o == heap->name##_map()) n = #camel_name "Map";
  i::HeapObjectIterator it(heap->map_space());
  printf("KNOWN_MAPS = {\n");
  for (i::Object* o = it.Next(); o != NULL; o = it.Next()) {
    i::Map* m = i::Map::cast(o);
    const char* n = NULL;
    intptr_t p = reinterpret_cast<intptr_t>(m) & 0xfffff;
    int t = m->instance_type();
    ROOT_LIST(ROOT_LIST_CASE)
    STRUCT_LIST(STRUCT_LIST_CASE)
    if (n == NULL) continue;
    printf("  0x%05" V8PRIxPTR ": (%d, \"%s\"),\n", p, t, n);
  }
  printf("}\n");
#undef STRUCT_LIST_CASE
#undef ROOT_LIST_CASE

  // Dump the KNOWN_OBJECTS table to the console.
  printf("\n# List of known V8 objects.\n");
#define ROOT_LIST_CASE(type, name, camel_name) \
  if (n == NULL && o == heap->name()) n = #camel_name;
  i::OldSpaces spit(heap);
  printf("KNOWN_OBJECTS = {\n");
  for (i::PagedSpace* s = spit.next(); s != NULL; s = spit.next()) {
    i::HeapObjectIterator it(s);
    const char* sname = AllocationSpaceName(s->identity());
    for (i::Object* o = it.Next(); o != NULL; o = it.Next()) {
      const char* n = NULL;
      intptr_t p = reinterpret_cast<intptr_t>(o) & 0xfffff;
      ROOT_LIST(ROOT_LIST_CASE)
      if (n == NULL) continue;
      printf("  (\"%s\", 0x%05" V8PRIxPTR "): \"%s\",\n", sname, p, n);
    }
  }
  printf("}\n");
#undef ROOT_LIST_CASE
}
#endif  // !V8_SHARED


int Shell::Main(int argc, char* argv[]) {
#if (defined(_WIN32) || defined(_WIN64))
  UINT new_flags =
      SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX;
  UINT existing_flags = SetErrorMode(new_flags);
  SetErrorMode(existing_flags | new_flags);
#if defined(_MSC_VER)
  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
  _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
  _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
  _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
  _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
  _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
  _set_error_mode(_OUT_TO_STDERR);
#endif  // defined(_MSC_VER)
#endif  // defined(_WIN32) || defined(_WIN64)
  if (!SetOptions(argc, argv)) return 1;
  v8::V8::InitializeICU(options.icu_data_file);
#ifndef V8_SHARED
  g_platform = i::FLAG_verify_predictable
                   ? new PredictablePlatform()
                   : v8::platform::CreateDefaultPlatform();
#else
  g_platform = v8::platform::CreateDefaultPlatform();
#endif  // !V8_SHARED

  v8::V8::InitializePlatform(g_platform);
  v8::V8::Initialize();
  if (options.natives_blob || options.snapshot_blob) {
    v8::V8::InitializeExternalStartupData(options.natives_blob,
                                          options.snapshot_blob);
  } else {
    v8::V8::InitializeExternalStartupData(argv[0]);
  }
  SetFlagsFromString("--trace-hydrogen-file=hydrogen.cfg");
  SetFlagsFromString("--trace-turbo-cfg-file=turbo.cfg");
  SetFlagsFromString("--redirect-code-traces-to=code.asm");
  int result = 0;
  Isolate::CreateParams create_params;
  ShellArrayBufferAllocator shell_array_buffer_allocator;
  MockArrayBufferAllocator mock_arraybuffer_allocator;
  if (options.mock_arraybuffer_allocator) {
    Shell::array_buffer_allocator = &mock_arraybuffer_allocator;
  } else {
    Shell::array_buffer_allocator = &shell_array_buffer_allocator;
  }
  create_params.array_buffer_allocator = Shell::array_buffer_allocator;
#ifdef ENABLE_VTUNE_JIT_INTERFACE
  create_params.code_event_handler = vTune::GetVtuneCodeEventHandler();
#endif
#ifndef V8_SHARED
  create_params.constraints.ConfigureDefaults(
      base::SysInfo::AmountOfPhysicalMemory(),
      base::SysInfo::AmountOfVirtualMemory());

  Shell::counter_map_ = new CounterMap();
  if (i::FLAG_dump_counters || i::FLAG_track_gc_object_stats) {
    create_params.counter_lookup_callback = LookupCounter;
    create_params.create_histogram_callback = CreateHistogram;
    create_params.add_histogram_sample_callback = AddHistogramSample;
  }
#endif
  Isolate* isolate = Isolate::New(create_params);
  {
    Isolate::Scope scope(isolate);
    Initialize(isolate);
    PerIsolateData data(isolate);

#ifndef V8_SHARED
    if (options.dump_heap_constants) {
      DumpHeapConstants(reinterpret_cast<i::Isolate*>(isolate));
      return 0;
    }
#endif

    if (options.stress_opt || options.stress_deopt) {
      Testing::SetStressRunType(options.stress_opt
                                ? Testing::kStressTypeOpt
                                : Testing::kStressTypeDeopt);
      options.stress_runs = Testing::GetStressRuns();
      for (int i = 0; i < options.stress_runs && result == 0; i++) {
        printf("============ Stress %d/%d ============\n", i + 1,
               options.stress_runs);
        Testing::PrepareStressRun(i);
        bool last_run = i == options.stress_runs - 1;
        result = RunMain(isolate, argc, argv, last_run);
      }
      printf("======== Full Deoptimization =======\n");
      Testing::DeoptimizeAll(isolate);
#if !defined(V8_SHARED)
    } else if (i::FLAG_stress_runs > 0) {
      options.stress_runs = i::FLAG_stress_runs;
      for (int i = 0; i < options.stress_runs && result == 0; i++) {
        printf("============ Run %d/%d ============\n", i + 1,
               options.stress_runs);
        bool last_run = i == options.stress_runs - 1;
        result = RunMain(isolate, argc, argv, last_run);
      }
#endif
    } else {
      bool last_run = true;
      result = RunMain(isolate, argc, argv, last_run);
    }

    // Run interactive shell if explicitly requested or if no script has been
    // executed, but never on --test
    if (options.use_interactive_shell()) {
#ifndef V8_SHARED
      InstallUtilityScript(isolate);
#endif  // !V8_SHARED
      RunShell(isolate);
    }

    // Shut down contexts and collect garbage.
    evaluation_context_.Reset();
#ifndef V8_SHARED
    utility_context_.Reset();
#endif  // !V8_SHARED
    CollectGarbage(isolate);
  }
  OnExit(isolate);
#ifndef V8_SHARED
  // Dump basic block profiling data.
  if (i::BasicBlockProfiler* profiler =
          reinterpret_cast<i::Isolate*>(isolate)->basic_block_profiler()) {
    i::OFStream os(stdout);
    os << *profiler;
  }
#endif  // !V8_SHARED
  isolate->Dispose();
  V8::Dispose();
  V8::ShutdownPlatform();
  delete g_platform;

  return result;
}

}  // namespace v8


#ifndef GOOGLE3
int main(int argc, char* argv[]) {
  return v8::Shell::Main(argc, argv);
}
#endif
