1// Copyright 2006-2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28// The common functionality when building with or without snapshots.
29
30#include "v8.h"
31
32#include "api.h"
33#include "serialize.h"
34#include "snapshot.h"
35#include "platform.h"
36
37namespace v8 {
38namespace internal {
39
40
41static void ReserveSpaceForSnapshot(Deserializer* deserializer,
42                                    const char* file_name) {
43  int file_name_length = StrLength(file_name) + 10;
44  Vector<char> name = Vector<char>::New(file_name_length + 1);
45  OS::SNPrintF(name, "%s.size", file_name);
46  FILE* fp = OS::FOpen(name.start(), "r");
47  CHECK_NE(NULL, fp);
48  int new_size, pointer_size, data_size, code_size, map_size, cell_size,
49      property_cell_size;
50#ifdef _MSC_VER
51  // Avoid warning about unsafe fscanf from MSVC.
52  // Please note that this is only fine if %c and %s are not being used.
53#define fscanf fscanf_s
54#endif
55  CHECK_EQ(1, fscanf(fp, "new %d\n", &new_size));
56  CHECK_EQ(1, fscanf(fp, "pointer %d\n", &pointer_size));
57  CHECK_EQ(1, fscanf(fp, "data %d\n", &data_size));
58  CHECK_EQ(1, fscanf(fp, "code %d\n", &code_size));
59  CHECK_EQ(1, fscanf(fp, "map %d\n", &map_size));
60  CHECK_EQ(1, fscanf(fp, "cell %d\n", &cell_size));
61  CHECK_EQ(1, fscanf(fp, "property cell %d\n", &property_cell_size));
62#ifdef _MSC_VER
63#undef fscanf
64#endif
65  fclose(fp);
66  deserializer->set_reservation(NEW_SPACE, new_size);
67  deserializer->set_reservation(OLD_POINTER_SPACE, pointer_size);
68  deserializer->set_reservation(OLD_DATA_SPACE, data_size);
69  deserializer->set_reservation(CODE_SPACE, code_size);
70  deserializer->set_reservation(MAP_SPACE, map_size);
71  deserializer->set_reservation(CELL_SPACE, cell_size);
72  deserializer->set_reservation(PROPERTY_CELL_SPACE,
73                                property_cell_size);
74  name.Dispose();
75}
76
77
78void Snapshot::ReserveSpaceForLinkedInSnapshot(Deserializer* deserializer) {
79  deserializer->set_reservation(NEW_SPACE, new_space_used_);
80  deserializer->set_reservation(OLD_POINTER_SPACE, pointer_space_used_);
81  deserializer->set_reservation(OLD_DATA_SPACE, data_space_used_);
82  deserializer->set_reservation(CODE_SPACE, code_space_used_);
83  deserializer->set_reservation(MAP_SPACE, map_space_used_);
84  deserializer->set_reservation(CELL_SPACE, cell_space_used_);
85  deserializer->set_reservation(PROPERTY_CELL_SPACE,
86                                property_cell_space_used_);
87}
88
89
90bool Snapshot::Initialize(const char* snapshot_file) {
91  if (snapshot_file) {
92    int len;
93    byte* str = ReadBytes(snapshot_file, &len);
94    if (!str) return false;
95    bool success;
96    {
97      SnapshotByteSource source(str, len);
98      Deserializer deserializer(&source);
99      ReserveSpaceForSnapshot(&deserializer, snapshot_file);
100      success = V8::Initialize(&deserializer);
101    }
102    DeleteArray(str);
103    return success;
104  } else if (size_ > 0) {
105    ElapsedTimer timer;
106    if (FLAG_profile_deserialization) {
107      timer.Start();
108    }
109    SnapshotByteSource source(raw_data_, raw_size_);
110    Deserializer deserializer(&source);
111    ReserveSpaceForLinkedInSnapshot(&deserializer);
112    bool success = V8::Initialize(&deserializer);
113    if (FLAG_profile_deserialization) {
114      double ms = timer.Elapsed().InMillisecondsF();
115      PrintF("[Snapshot loading and deserialization took %0.3f ms]\n", ms);
116    }
117    return success;
118  }
119  return false;
120}
121
122
123bool Snapshot::HaveASnapshotToStartFrom() {
124  return size_ != 0;
125}
126
127
128Handle<Context> Snapshot::NewContextFromSnapshot(Isolate* isolate) {
129  if (context_size_ == 0) {
130    return Handle<Context>();
131  }
132  SnapshotByteSource source(context_raw_data_,
133                            context_raw_size_);
134  Deserializer deserializer(&source);
135  Object* root;
136  deserializer.set_reservation(NEW_SPACE, context_new_space_used_);
137  deserializer.set_reservation(OLD_POINTER_SPACE, context_pointer_space_used_);
138  deserializer.set_reservation(OLD_DATA_SPACE, context_data_space_used_);
139  deserializer.set_reservation(CODE_SPACE, context_code_space_used_);
140  deserializer.set_reservation(MAP_SPACE, context_map_space_used_);
141  deserializer.set_reservation(CELL_SPACE, context_cell_space_used_);
142  deserializer.set_reservation(PROPERTY_CELL_SPACE,
143                               context_property_cell_space_used_);
144  deserializer.DeserializePartial(isolate, &root);
145  CHECK(root->IsContext());
146  return Handle<Context>(Context::cast(root));
147}
148
149} }  // namespace v8::internal
150