d8.h 16 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4 5 6 7

#ifndef V8_D8_H_
#define V8_D8_H_

8
#ifndef V8_SHARED
9
#include "src/allocation.h"
lpy's avatar
lpy committed
10
#include "src/base/hashmap.h"
11
#include "src/base/platform/time.h"
12
#include "src/list.h"
13
#else
14
#include "include/v8.h"
15
#include "src/base/compiler-specific.h"
16
#endif  // !V8_SHARED
17

18 19 20
#include "src/base/once.h"


21 22 23
namespace v8 {


24
#ifndef V8_SHARED
25
// A single counter in a counter collection.
26 27
class Counter {
 public:
28
  static const int kMaxNameSize = 64;
29 30 31 32 33 34
  int32_t* Bind(const char* name, bool histogram);
  int32_t* ptr() { return &count_; }
  int32_t count() { return count_; }
  int32_t sample_total() { return sample_total_; }
  bool is_histogram() { return is_histogram_; }
  void AddSample(int32_t sample);
35
 private:
36 37 38
  int32_t count_;
  int32_t sample_total_;
  bool is_histogram_;
39 40 41 42 43 44 45 46 47 48 49 50
  uint8_t name_[kMaxNameSize];
};


// A set of counters and associated information.  An instance of this
// class is stored directly in the memory-mapped counters file if
// the --map-counters options is used
class CounterCollection {
 public:
  CounterCollection();
  Counter* GetNextCounter();
 private:
51
  static const unsigned kMaxCounters = 512;
52 53 54 55 56
  uint32_t magic_number_;
  uint32_t max_counters_;
  uint32_t max_name_size_;
  uint32_t counters_in_use_;
  Counter counters_[kMaxCounters];
57 58 59
};


60 61 62 63
class CounterMap {
 public:
  CounterMap(): hash_map_(Match) { }
  Counter* Lookup(const char* name) {
lpy's avatar
lpy committed
64
    base::HashMap::Entry* answer =
65
        hash_map_.Lookup(const_cast<char*>(name), Hash(name));
66 67 68 69
    if (!answer) return NULL;
    return reinterpret_cast<Counter*>(answer->value);
  }
  void Set(const char* name, Counter* value) {
lpy's avatar
lpy committed
70
    base::HashMap::Entry* answer =
71
        hash_map_.LookupOrInsert(const_cast<char*>(name), Hash(name));
72
    DCHECK(answer != NULL);
73 74 75 76
    answer->value = value;
  }
  class Iterator {
   public:
77 78
    explicit Iterator(CounterMap* map)
        : map_(&map->hash_map_), entry_(map_->Start()) { }
79 80 81 82 83
    void Next() { entry_ = map_->Next(entry_); }
    bool More() { return entry_ != NULL; }
    const char* CurrentKey() { return static_cast<const char*>(entry_->key); }
    Counter* CurrentValue() { return static_cast<Counter*>(entry_->value); }
   private:
lpy's avatar
lpy committed
84 85
    base::HashMap* map_;
    base::HashMap::Entry* entry_;
86
  };
87

88 89 90
 private:
  static int Hash(const char* name);
  static bool Match(void* key1, void* key2);
lpy's avatar
lpy committed
91
  base::HashMap hash_map_;
92
};
93
#endif  // !V8_SHARED
94 95


96 97
class SourceGroup {
 public:
98
  SourceGroup() :
99
#ifndef V8_SHARED
100 101
      next_semaphore_(0),
      done_semaphore_(0),
102
      thread_(NULL),
103
#endif  // !V8_SHARED
104 105
      argv_(NULL),
      begin_offset_(0),
106
      end_offset_(0) {}
107

108 109
  ~SourceGroup();

110 111 112 113 114 115 116
  void Begin(char** argv, int offset) {
    argv_ = const_cast<const char**>(argv);
    begin_offset_ = offset;
  }

  void End(int offset) { end_offset_ = offset; }

117
  void Execute(Isolate* isolate);
118

119
#ifndef V8_SHARED
120 121
  void StartExecuteInThread();
  void WaitForThread();
binji's avatar
binji committed
122
  void JoinThread();
123 124

 private:
125
  class IsolateThread : public base::Thread {
126 127
   public:
    explicit IsolateThread(SourceGroup* group)
128
        : base::Thread(GetThreadOptions()), group_(group) {}
129 130 131 132 133 134 135 136 137

    virtual void Run() {
      group_->ExecuteInThread();
    }

   private:
    SourceGroup* group_;
  };

138
  static base::Thread::Options GetThreadOptions();
139 140
  void ExecuteInThread();

141 142 143
  base::Semaphore next_semaphore_;
  base::Semaphore done_semaphore_;
  base::Thread* thread_;
144
#endif  // !V8_SHARED
145 146

  void ExitShell(int exit_code);
147
  Local<String> ReadFile(Isolate* isolate, const char* name);
148 149 150 151 152 153

  const char** argv_;
  int begin_offset_;
  int end_offset_;
};

154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
#ifndef V8_SHARED
enum SerializationTag {
  kSerializationTagUndefined,
  kSerializationTagNull,
  kSerializationTagTrue,
  kSerializationTagFalse,
  kSerializationTagNumber,
  kSerializationTagString,
  kSerializationTagArray,
  kSerializationTagObject,
  kSerializationTagArrayBuffer,
  kSerializationTagTransferredArrayBuffer,
  kSerializationTagTransferredSharedArrayBuffer,
};


class SerializationData {
 public:
  SerializationData() {}
  ~SerializationData();

  void WriteTag(SerializationTag tag);
  void WriteMemory(const void* p, int length);
  void WriteArrayBufferContents(const ArrayBuffer::Contents& contents);
  void WriteSharedArrayBufferContents(
      const SharedArrayBuffer::Contents& contents);

  template <typename T>
  void Write(const T& data) {
    WriteMemory(&data, sizeof(data));
  }

  SerializationTag ReadTag(int* offset) const;
  void ReadMemory(void* p, int length, int* offset) const;
  void ReadArrayBufferContents(ArrayBuffer::Contents* contents,
                               int* offset) const;
  void ReadSharedArrayBufferContents(SharedArrayBuffer::Contents* contents,
                                     int* offset) const;

  template <typename T>
  T Read(int* offset) const {
    T value;
    ReadMemory(&value, sizeof(value), offset);
    return value;
  }

 private:
201 202 203
  i::List<uint8_t> data_;
  i::List<ArrayBuffer::Contents> array_buffer_contents_;
  i::List<SharedArrayBuffer::Contents> shared_array_buffer_contents_;
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
};


class SerializationDataQueue {
 public:
  void Enqueue(SerializationData* data);
  bool Dequeue(SerializationData** data);
  bool IsEmpty();
  void Clear();

 private:
  base::Mutex mutex_;
  i::List<SerializationData*> data_;
};


class Worker {
 public:
  Worker();
  ~Worker();

225 226 227
  // Run the given script on this Worker. This function should only be called
  // once, and should only be called by the thread that created the Worker.
  void StartExecuteInThread(const char* script);
binji's avatar
binji committed
228 229
  // Post a message to the worker's incoming message queue. The worker will
  // take ownership of the SerializationData.
230
  // This function should only be called by the thread that created the Worker.
231
  void PostMessage(SerializationData* data);
binji's avatar
binji committed
232 233 234 235
  // Synchronously retrieve messages from the worker's outgoing message queue.
  // If there is no message in the queue, block until a message is available.
  // If there are no messages in the queue and the worker is no longer running,
  // return nullptr.
236
  // This function should only be called by the thread that created the Worker.
237
  SerializationData* GetMessage();
binji's avatar
binji committed
238 239
  // Terminate the worker's event loop. Messages from the worker that have been
  // queued can still be read via GetMessage().
240
  // This function can be called by any thread.
241
  void Terminate();
binji's avatar
binji committed
242
  // Terminate and join the thread.
243
  // This function can be called by any thread.
binji's avatar
binji committed
244
  void WaitForThread();
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267

 private:
  class WorkerThread : public base::Thread {
   public:
    explicit WorkerThread(Worker* worker)
        : base::Thread(base::Thread::Options("WorkerThread")),
          worker_(worker) {}

    virtual void Run() { worker_->ExecuteInThread(); }

   private:
    Worker* worker_;
  };

  void ExecuteInThread();
  static void PostMessageOut(const v8::FunctionCallbackInfo<v8::Value>& args);

  base::Semaphore in_semaphore_;
  base::Semaphore out_semaphore_;
  SerializationDataQueue in_queue_;
  SerializationDataQueue out_queue_;
  base::Thread* thread_;
  char* script_;
268
  base::Atomic32 running_;
269 270 271
};
#endif  // !V8_SHARED

272 273 274

class ShellOptions {
 public:
275 276 277 278
  ShellOptions()
      : script_executed(false),
        send_idle_notification(false),
        invoke_weak_callbacks(false),
279
        omit_quit(false),
280 281
        stress_opt(false),
        stress_deopt(false),
binji's avatar
binji committed
282
        stress_runs(1),
283 284 285 286 287 288 289 290 291 292 293
        interactive_shell(false),
        test_shell(false),
        dump_heap_constants(false),
        expected_to_throw(false),
        mock_arraybuffer_allocator(false),
        num_isolates(1),
        compile_options(v8::ScriptCompiler::kNoCompileOptions),
        isolate_sources(NULL),
        icu_data_file(NULL),
        natives_blob(NULL),
        snapshot_blob(NULL) {}
294

295 296 297
  ~ShellOptions() {
    delete[] isolate_sources;
  }
298

299 300 301 302
  bool use_interactive_shell() {
    return (interactive_shell || !script_executed) && !test_shell;
  }

303
  bool script_executed;
304
  bool send_idle_notification;
305
  bool invoke_weak_callbacks;
306
  bool omit_quit;
307 308
  bool stress_opt;
  bool stress_deopt;
binji's avatar
binji committed
309
  int stress_runs;
310 311
  bool interactive_shell;
  bool test_shell;
312
  bool dump_heap_constants;
313
  bool expected_to_throw;
314
  bool mock_arraybuffer_allocator;
315
  int num_isolates;
316
  v8::ScriptCompiler::CompileOptions compile_options;
317
  SourceGroup* isolate_sources;
318
  const char* icu_data_file;
319 320
  const char* natives_blob;
  const char* snapshot_blob;
321 322
};

323
#ifdef V8_SHARED
324 325 326
class Shell {
#else
class Shell : public i::AllStatic {
327
#endif  // V8_SHARED
328

329
 public:
330 331
  enum SourceType { SCRIPT, MODULE };

332
  static MaybeLocal<Script> CompileString(
333
      Isolate* isolate, Local<String> source, Local<Value> name,
334 335
      v8::ScriptCompiler::CompileOptions compile_options,
      SourceType source_type);
336 337
  static bool ExecuteString(Isolate* isolate, Local<String> source,
                            Local<Value> name, bool print_result,
338 339
                            bool report_exceptions,
                            SourceType source_type = SCRIPT);
340
  static const char* ToCString(const v8::String::Utf8Value& value);
341
  static void ReportException(Isolate* isolate, TryCatch* try_catch);
342
  static Local<String> ReadFile(Isolate* isolate, const char* name);
343
  static Local<Context> CreateEvaluationContext(Isolate* isolate);
binji's avatar
binji committed
344
  static int RunMain(Isolate* isolate, int argc, char* argv[], bool last_run);
345
  static int Main(int argc, char* argv[]);
346
  static void Exit(int exit_code);
347
  static void OnExit(Isolate* isolate);
348
  static void CollectGarbage(Isolate* isolate);
349
  static void EmptyMessageQueues(Isolate* isolate);
350

351
#ifndef V8_SHARED
352
  // TODO(binji): stupid implementation for now. Is there an easy way to hash an
lpy's avatar
lpy committed
353
  // object for use in base::HashMap? By pointer?
354 355
  typedef i::List<Local<Object>> ObjectList;
  static bool SerializeValue(Isolate* isolate, Local<Value> value,
356 357 358 359 360 361 362
                             const ObjectList& to_transfer,
                             ObjectList* seen_objects,
                             SerializationData* out_data);
  static MaybeLocal<Value> DeserializeValue(Isolate* isolate,
                                            const SerializationData& data,
                                            int* offset);
  static void CleanupWorkers();
363
  static int* LookupCounter(const char* name);
364 365 366 367 368
  static void* CreateHistogram(const char* name,
                               int min,
                               int max,
                               size_t buckets);
  static void AddHistogramSample(void* histogram, int sample);
369
  static void MapCounters(v8::Isolate* isolate, const char* name);
370

371
  static void PerformanceNow(const v8::FunctionCallbackInfo<v8::Value>& args);
372
#endif  // !V8_SHARED
373

374 375 376 377
  static void RealmCurrent(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void RealmOwner(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void RealmGlobal(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args);
378 379
  static void RealmCreateAllowCrossRealmAccess(
      const v8::FunctionCallbackInfo<v8::Value>& args);
380 381 382 383 384
  static void RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void RealmSwitch(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void RealmEval(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void RealmSharedGet(Local<String> property,
                             const  PropertyCallbackInfo<Value>& info);
385 386
  static void RealmSharedSet(Local<String> property,
                             Local<Value> value,
387 388 389 390
                             const  PropertyCallbackInfo<void>& info);

  static void Print(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void Write(const v8::FunctionCallbackInfo<v8::Value>& args);
391
  static void QuitOnce(v8::FunctionCallbackInfo<v8::Value>* args);
392 393 394 395
  static void Quit(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void Version(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void Read(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void ReadBuffer(const v8::FunctionCallbackInfo<v8::Value>& args);
396
  static Local<String> ReadFromStdin(Isolate* isolate);
397 398
  static void ReadLine(const v8::FunctionCallbackInfo<v8::Value>& args) {
    args.GetReturnValue().Set(ReadFromStdin(args.GetIsolate()));
399
  }
400
  static void Load(const v8::FunctionCallbackInfo<v8::Value>& args);
401 402 403 404 405
  static void WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void WorkerPostMessage(
      const v8::FunctionCallbackInfo<v8::Value>& args);
  static void WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args);
406 407 408 409 410 411
  // The OS object on the global object contains methods for performing
  // operating system calls:
  //
  // os.system("program_name", ["arg1", "arg2", ...], timeout1, timeout2) will
  // run the command, passing the arguments to the program.  The standard output
  // of the program will be picked up and returned as a multiline string.  If
412 413 414 415 416 417 418
  // timeout1 is present then it should be a number.  -1 indicates no timeout
  // and a positive number is used as a timeout in milliseconds that limits the
  // time spent waiting between receiving output characters from the program.
  // timeout2, if present, should be a number indicating the limit in
  // milliseconds on the total running time of the program.  Exceptions are
  // thrown on timeouts or other errors or if the exit status of the program
  // indicates an error.
419 420 421 422 423 424
  //
  // os.chdir(dir) changes directory to the given directory.  Throws an
  // exception/ on error.
  //
  // os.setenv(variable, value) sets an environment variable.  Repeated calls to
  // this method leak memory due to the API of setenv in the standard C library.
425 426 427 428 429 430 431
  //
  // os.umask(alue) calls the umask system call and returns the old umask.
  //
  // os.mkdirp(name, mask) creates a directory.  The mask (if present) is anded
  // with the current umask.  Intermediate directories are created if necessary.
  // An exception is not thrown if the directory already exists.  Analogous to
  // the "mkdir -p" command.
432 433 434 435 436 437 438
  static void System(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void ChangeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void SetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void UnsetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void SetUMask(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void MakeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void RemoveDirectory(const v8::FunctionCallbackInfo<v8::Value>& args);
439

440
  static void AddOSMethods(v8::Isolate* isolate,
441
                           Local<ObjectTemplate> os_template);
442

443
  static const char* kPrompt;
444
  static ShellOptions options;
445
  static ArrayBuffer::Allocator* array_buffer_allocator;
446

447
 private:
448
  static Global<Context> evaluation_context_;
449
  static base::OnceType quit_once_;
450
#ifndef V8_SHARED
yangguo's avatar
yangguo committed
451
  static Global<Function> stringify_function_;
452
  static CounterMap* counter_map_;
453 454 455 456
  // We statically allocate a set of local counters to be used if we
  // don't want to store the stats in a memory-mapped file
  static CounterCollection local_counters_;
  static CounterCollection* counters_;
457
  static base::OS::MemoryMappedFile* counters_file_;
458
  static base::LazyMutex context_mutex_;
459
  static const base::TimeTicks kInitialTicks;
460

461
  static base::LazyMutex workers_mutex_;
462
  static bool allow_new_workers_;
463 464
  static i::List<Worker*> workers_;
  static i::List<SharedArrayBuffer::Contents> externalized_shared_contents_;
465

466
  static void WriteIgnitionDispatchCountersFile(v8::Isolate* isolate);
467
  static Counter* GetCounter(const char* name, bool is_histogram);
yangguo's avatar
yangguo committed
468
  static Local<String> Stringify(Isolate* isolate, Local<Value> value);
469
#endif  // !V8_SHARED
470 471
  static void Initialize(Isolate* isolate);
  static void RunShell(Isolate* isolate);
472
  static bool SetOptions(int argc, char* argv[]);
473
  static Local<ObjectTemplate> CreateGlobalTemplate(Isolate* isolate);
474 475
  static MaybeLocal<Context> CreateRealm(
      const v8::FunctionCallbackInfo<v8::Value>& args);
476 477 478 479 480 481 482
};


}  // namespace v8


#endif  // V8_D8_H_