blob: 8f4441ac7730fd7ea2b76ae646d78757acba6df4 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2007-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#include <signal.h>
29
30#include "sys/stat.h"
31#include "v8.h"
32
33#include "debug.h"
34#include "ic-inl.h"
35#include "runtime.h"
36#include "serialize.h"
37#include "scopeinfo.h"
38#include "snapshot.h"
39#include "cctest.h"
40
41using namespace v8::internal;
42
43static const unsigned kCounters = 256;
44static int local_counters[kCounters];
45static const char* local_counter_names[kCounters];
46
47
48static unsigned CounterHash(const char* s) {
49 unsigned hash = 0;
50 while (*++s) {
51 hash |= hash << 5;
52 hash += *s;
53 }
54 return hash;
55}
56
57
58// Callback receiver to track counters in test.
59static int* counter_function(const char* name) {
60 unsigned hash = CounterHash(name) % kCounters;
61 unsigned original_hash = hash;
62 USE(original_hash);
63 while (true) {
64 if (local_counter_names[hash] == name) {
65 return &local_counters[hash];
66 }
67 if (local_counter_names[hash] == 0) {
68 local_counter_names[hash] = name;
69 return &local_counters[hash];
70 }
71 if (strcmp(local_counter_names[hash], name) == 0) {
72 return &local_counters[hash];
73 }
74 hash = (hash + 1) % kCounters;
75 ASSERT(hash != original_hash); // Hash table has been filled up.
76 }
77}
78
79
80template <class T>
81static Address AddressOf(T id) {
82 return ExternalReference(id).address();
83}
84
85
86template <class T>
87static uint32_t Encode(const ExternalReferenceEncoder& encoder, T id) {
88 return encoder.Encode(AddressOf(id));
89}
90
91
92static int make_code(TypeCode type, int id) {
93 return static_cast<uint32_t>(type) << kReferenceTypeShift | id;
94}
95
96
97static int register_code(int reg) {
98 return Debug::k_register_address << kDebugIdShift | reg;
99}
100
101
102TEST(ExternalReferenceEncoder) {
103 StatsTable::SetCounterFunction(counter_function);
104 Heap::Setup(false);
105 ExternalReferenceEncoder encoder;
106 CHECK_EQ(make_code(BUILTIN, Builtins::ArrayCode),
107 Encode(encoder, Builtins::ArrayCode));
108 CHECK_EQ(make_code(RUNTIME_FUNCTION, Runtime::kAbort),
109 Encode(encoder, Runtime::kAbort));
110 CHECK_EQ(make_code(IC_UTILITY, IC::kLoadCallbackProperty),
111 Encode(encoder, IC_Utility(IC::kLoadCallbackProperty)));
112 CHECK_EQ(make_code(DEBUG_ADDRESS, register_code(3)),
113 Encode(encoder, Debug_Address(Debug::k_register_address, 3)));
114 ExternalReference keyed_load_function_prototype =
115 ExternalReference(&Counters::keyed_load_function_prototype);
116 CHECK_EQ(make_code(STATS_COUNTER, Counters::k_keyed_load_function_prototype),
117 encoder.Encode(keyed_load_function_prototype.address()));
118 ExternalReference passed_function =
119 ExternalReference::builtin_passed_function();
120 CHECK_EQ(make_code(UNCLASSIFIED, 1),
121 encoder.Encode(passed_function.address()));
122 ExternalReference the_hole_value_location =
123 ExternalReference::the_hole_value_location();
124 CHECK_EQ(make_code(UNCLASSIFIED, 2),
125 encoder.Encode(the_hole_value_location.address()));
Steve Blockd0582a62009-12-15 09:54:21 +0000126 ExternalReference stack_limit_address =
127 ExternalReference::address_of_stack_limit();
Steve Blocka7e24c12009-10-30 11:49:00 +0000128 CHECK_EQ(make_code(UNCLASSIFIED, 4),
Steve Blockd0582a62009-12-15 09:54:21 +0000129 encoder.Encode(stack_limit_address.address()));
130 ExternalReference real_stack_limit_address =
131 ExternalReference::address_of_real_stack_limit();
132 CHECK_EQ(make_code(UNCLASSIFIED, 5),
133 encoder.Encode(real_stack_limit_address.address()));
134 CHECK_EQ(make_code(UNCLASSIFIED, 11),
Steve Blocka7e24c12009-10-30 11:49:00 +0000135 encoder.Encode(ExternalReference::debug_break().address()));
Steve Blockd0582a62009-12-15 09:54:21 +0000136 CHECK_EQ(make_code(UNCLASSIFIED, 7),
Steve Blocka7e24c12009-10-30 11:49:00 +0000137 encoder.Encode(ExternalReference::new_space_start().address()));
138 CHECK_EQ(make_code(UNCLASSIFIED, 3),
139 encoder.Encode(ExternalReference::roots_address().address()));
140}
141
142
143TEST(ExternalReferenceDecoder) {
144 StatsTable::SetCounterFunction(counter_function);
145 Heap::Setup(false);
146 ExternalReferenceDecoder decoder;
147 CHECK_EQ(AddressOf(Builtins::ArrayCode),
148 decoder.Decode(make_code(BUILTIN, Builtins::ArrayCode)));
149 CHECK_EQ(AddressOf(Runtime::kAbort),
150 decoder.Decode(make_code(RUNTIME_FUNCTION, Runtime::kAbort)));
151 CHECK_EQ(AddressOf(IC_Utility(IC::kLoadCallbackProperty)),
152 decoder.Decode(make_code(IC_UTILITY, IC::kLoadCallbackProperty)));
153 CHECK_EQ(AddressOf(Debug_Address(Debug::k_register_address, 3)),
154 decoder.Decode(make_code(DEBUG_ADDRESS, register_code(3))));
155 ExternalReference keyed_load_function =
156 ExternalReference(&Counters::keyed_load_function_prototype);
157 CHECK_EQ(keyed_load_function.address(),
158 decoder.Decode(
159 make_code(STATS_COUNTER,
160 Counters::k_keyed_load_function_prototype)));
161 CHECK_EQ(ExternalReference::builtin_passed_function().address(),
162 decoder.Decode(make_code(UNCLASSIFIED, 1)));
163 CHECK_EQ(ExternalReference::the_hole_value_location().address(),
164 decoder.Decode(make_code(UNCLASSIFIED, 2)));
Steve Blockd0582a62009-12-15 09:54:21 +0000165 CHECK_EQ(ExternalReference::address_of_stack_limit().address(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000166 decoder.Decode(make_code(UNCLASSIFIED, 4)));
Steve Blockd0582a62009-12-15 09:54:21 +0000167 CHECK_EQ(ExternalReference::address_of_real_stack_limit().address(),
168 decoder.Decode(make_code(UNCLASSIFIED, 5)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000169 CHECK_EQ(ExternalReference::debug_break().address(),
Steve Blockd0582a62009-12-15 09:54:21 +0000170 decoder.Decode(make_code(UNCLASSIFIED, 11)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000171 CHECK_EQ(ExternalReference::new_space_start().address(),
Steve Blockd0582a62009-12-15 09:54:21 +0000172 decoder.Decode(make_code(UNCLASSIFIED, 7)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000173}
174
175
176static void Serialize() {
Steve Blockd0582a62009-12-15 09:54:21 +0000177 // We have to create one context. One reason for this is so that the builtins
178 // can be loaded from v8natives.js and their addresses can be processed. This
179 // will clear the pending fixups array, which would otherwise contain GC roots
180 // that would confuse the serialization/deserialization process.
181 v8::Persistent<v8::Context> env = v8::Context::New();
182 env.Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +0000183 Snapshot::WriteToFile(FLAG_testing_serialization_file);
184}
185
186
Steve Blockd0582a62009-12-15 09:54:21 +0000187// Test that the whole heap can be serialized.
Steve Blocka7e24c12009-10-30 11:49:00 +0000188TEST(Serialize) {
Steve Blockd0582a62009-12-15 09:54:21 +0000189 Serializer::Enable();
190 v8::V8::Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +0000191 Serialize();
192}
193
194
Steve Blockd0582a62009-12-15 09:54:21 +0000195// Test that heap serialization is non-destructive.
196TEST(SerializeTwice) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000197 Serializer::Enable();
Steve Blockd0582a62009-12-15 09:54:21 +0000198 v8::V8::Initialize();
199 Serialize();
200 Serialize();
Steve Blocka7e24c12009-10-30 11:49:00 +0000201}
202
Steve Blockd0582a62009-12-15 09:54:21 +0000203
Steve Blocka7e24c12009-10-30 11:49:00 +0000204//----------------------------------------------------------------------------
205// Tests that the heap can be deserialized.
206
207static void Deserialize() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000208 CHECK(Snapshot::Initialize(FLAG_testing_serialization_file));
209}
210
211
212static void SanityCheck() {
213 v8::HandleScope scope;
214#ifdef DEBUG
215 Heap::Verify();
216#endif
217 CHECK(Top::global()->IsJSObject());
218 CHECK(Top::global_context()->IsContext());
219 CHECK(Top::special_function_table()->IsFixedArray());
220 CHECK(Heap::symbol_table()->IsSymbolTable());
221 CHECK(!Factory::LookupAsciiSymbol("Empty")->IsFailure());
222}
223
224
225DEPENDENT_TEST(Deserialize, Serialize) {
226 v8::HandleScope scope;
227
228 Deserialize();
229
Steve Blockd0582a62009-12-15 09:54:21 +0000230 v8::Persistent<v8::Context> env = v8::Context::New();
231 env->Enter();
232
Steve Blocka7e24c12009-10-30 11:49:00 +0000233 SanityCheck();
234}
235
Steve Blockd0582a62009-12-15 09:54:21 +0000236
237DEPENDENT_TEST(DeserializeFromSecondSerialization, SerializeTwice) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000238 v8::HandleScope scope;
239
240 Deserialize();
241
Steve Blockd0582a62009-12-15 09:54:21 +0000242 v8::Persistent<v8::Context> env = v8::Context::New();
243 env->Enter();
244
245 SanityCheck();
246}
247
248
249DEPENDENT_TEST(DeserializeAndRunScript2, Serialize) {
250 v8::HandleScope scope;
251
252 Deserialize();
253
254 v8::Persistent<v8::Context> env = v8::Context::New();
255 env->Enter();
256
Steve Blocka7e24c12009-10-30 11:49:00 +0000257 const char* c_source = "\"1234\".length";
258 v8::Local<v8::String> source = v8::String::New(c_source);
259 v8::Local<v8::Script> script = v8::Script::Compile(source);
260 CHECK_EQ(4, script->Run()->Int32Value());
261}
262
263
Steve Blockd0582a62009-12-15 09:54:21 +0000264DEPENDENT_TEST(DeserializeFromSecondSerializationAndRunScript2,
265 SerializeTwice) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000266 v8::HandleScope scope;
267
268 Deserialize();
269
Steve Blockd0582a62009-12-15 09:54:21 +0000270 v8::Persistent<v8::Context> env = v8::Context::New();
271 env->Enter();
272
273 const char* c_source = "\"1234\".length";
Steve Blocka7e24c12009-10-30 11:49:00 +0000274 v8::Local<v8::String> source = v8::String::New(c_source);
275 v8::Local<v8::Script> script = v8::Script::Compile(source);
Steve Blockd0582a62009-12-15 09:54:21 +0000276 CHECK_EQ(4, script->Run()->Int32Value());
Steve Blocka7e24c12009-10-30 11:49:00 +0000277}
278
279
Steve Block3ce2e202009-11-05 08:53:23 +0000280TEST(TestThatAlwaysSucceeds) {
281}
282
283
284TEST(TestThatAlwaysFails) {
285 bool ArtificialFailure = false;
286 CHECK(ArtificialFailure);
287}
288
289
290DEPENDENT_TEST(DependentTestThatAlwaysFails, TestThatAlwaysSucceeds) {
291 bool ArtificialFailure2 = false;
292 CHECK(ArtificialFailure2);
293}