blob: 195fef49b8b936e301cda62d97b61e2582b6c3e0 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002
3#include <stdlib.h>
4
5#include "v8.h"
6
7#include "execution.h"
8#include "factory.h"
9#include "macro-assembler.h"
10#include "global-handles.h"
11#include "cctest.h"
12
13using namespace v8::internal;
14
15static v8::Persistent<v8::Context> env;
16
17static void InitializeVM() {
18 if (env.IsEmpty()) env = v8::Context::New();
19 v8::HandleScope scope;
20 env->Enter();
21}
22
23
24static void CheckMap(Map* map, int type, int instance_size) {
25 CHECK(map->IsHeapObject());
26#ifdef DEBUG
27 CHECK(Heap::Contains(map));
28#endif
29 CHECK_EQ(Heap::meta_map(), map->map());
30 CHECK_EQ(type, map->instance_type());
31 CHECK_EQ(instance_size, map->instance_size());
32}
33
34
35TEST(HeapMaps) {
36 InitializeVM();
37 CheckMap(Heap::meta_map(), MAP_TYPE, Map::kSize);
38 CheckMap(Heap::heap_number_map(), HEAP_NUMBER_TYPE, HeapNumber::kSize);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000039 CheckMap(Heap::fixed_array_map(), FIXED_ARRAY_TYPE, FixedArray::kHeaderSize);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000040 CheckMap(Heap::string_map(), STRING_TYPE, SeqTwoByteString::kAlignedSize);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000041}
42
43
44static void CheckOddball(Object* obj, const char* string) {
45 CHECK(obj->IsOddball());
46 bool exc;
47 Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
48 CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
49}
50
51
52static void CheckSmi(int value, const char* string) {
53 bool exc;
54 Object* print_string =
55 *Execution::ToString(Handle<Object>(Smi::FromInt(value)), &exc);
56 CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
57}
58
59
60static void CheckNumber(double value, const char* string) {
61 Object* obj = Heap::NumberFromDouble(value);
62 CHECK(obj->IsNumber());
63 bool exc;
64 Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
65 CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
66}
67
68
69static void CheckFindCodeObject() {
70 // Test FindCodeObject
71#define __ assm.
72
73 Assembler assm(NULL, 0);
74
75 __ nop(); // supported on all architectures
76
77 CodeDesc desc;
78 assm.GetCode(&desc);
kasperl@chromium.org061ef742009-02-27 12:16:20 +000079 Object* code = Heap::CreateCode(desc,
80 NULL,
81 Code::ComputeFlags(Code::STUB),
82 Handle<Object>(Heap::undefined_value()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000083 CHECK(code->IsCode());
84
85 HeapObject* obj = HeapObject::cast(code);
86 Address obj_addr = obj->address();
87
88 for (int i = 0; i < obj->Size(); i += kPointerSize) {
89 Object* found = Heap::FindCodeObject(obj_addr + i);
90 CHECK_EQ(code, found);
91 }
92
kasperl@chromium.org061ef742009-02-27 12:16:20 +000093 Object* copy = Heap::CreateCode(desc,
94 NULL,
95 Code::ComputeFlags(Code::STUB),
96 Handle<Object>(Heap::undefined_value()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000097 CHECK(copy->IsCode());
98 HeapObject* obj_copy = HeapObject::cast(copy);
99 Object* not_right = Heap::FindCodeObject(obj_copy->address() +
100 obj_copy->Size() / 2);
101 CHECK(not_right != code);
102}
103
104
105TEST(HeapObjects) {
106 InitializeVM();
107
108 v8::HandleScope sc;
109 Object* value = Heap::NumberFromDouble(1.000123);
110 CHECK(value->IsHeapNumber());
111 CHECK(value->IsNumber());
112 CHECK_EQ(1.000123, value->Number());
113
114 value = Heap::NumberFromDouble(1.0);
115 CHECK(value->IsSmi());
116 CHECK(value->IsNumber());
117 CHECK_EQ(1.0, value->Number());
118
119 value = Heap::NumberFromInt32(1024);
120 CHECK(value->IsSmi());
121 CHECK(value->IsNumber());
122 CHECK_EQ(1024.0, value->Number());
123
124 value = Heap::NumberFromInt32(Smi::kMinValue);
125 CHECK(value->IsSmi());
126 CHECK(value->IsNumber());
127 CHECK_EQ(Smi::kMinValue, Smi::cast(value)->value());
128
129 value = Heap::NumberFromInt32(Smi::kMaxValue);
130 CHECK(value->IsSmi());
131 CHECK(value->IsNumber());
132 CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value());
133
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000134#ifndef V8_TARGET_ARCH_X64
135 // TODO(lrn): We need a NumberFromIntptr function in order to test this.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000136 value = Heap::NumberFromInt32(Smi::kMinValue - 1);
137 CHECK(value->IsHeapNumber());
138 CHECK(value->IsNumber());
139 CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000140#endif
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000141
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000142 value = Heap::NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000143 CHECK(value->IsHeapNumber());
144 CHECK(value->IsNumber());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000145 CHECK_EQ(static_cast<double>(static_cast<uint32_t>(Smi::kMaxValue) + 1),
146 value->Number());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000147
148 // nan oddball checks
149 CHECK(Heap::nan_value()->IsNumber());
150 CHECK(isnan(Heap::nan_value()->Number()));
151
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000152 Handle<String> s = Factory::NewStringFromAscii(CStrVector("fisk hest "));
153 CHECK(s->IsString());
154 CHECK_EQ(10, s->length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000155
156 String* object_symbol = String::cast(Heap::Object_symbol());
157 CHECK(Top::context()->global()->HasLocalProperty(object_symbol));
158
159 // Check ToString for oddballs
160 CheckOddball(Heap::true_value(), "true");
161 CheckOddball(Heap::false_value(), "false");
162 CheckOddball(Heap::null_value(), "null");
163 CheckOddball(Heap::undefined_value(), "undefined");
164
165 // Check ToString for Smis
166 CheckSmi(0, "0");
167 CheckSmi(42, "42");
168 CheckSmi(-42, "-42");
169
170 // Check ToString for Numbers
171 CheckNumber(1.1, "1.1");
172
173 CheckFindCodeObject();
174}
175
176
177TEST(Tagging) {
178 InitializeVM();
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000179 int request = 24;
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000180 CHECK_EQ(request, static_cast<int>(OBJECT_POINTER_ALIGN(request)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000181 CHECK(Smi::FromInt(42)->IsSmi());
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000182 CHECK(Failure::RetryAfterGC(request, NEW_SPACE)->IsFailure());
183 CHECK_EQ(request, Failure::RetryAfterGC(request, NEW_SPACE)->requested());
184 CHECK_EQ(NEW_SPACE,
185 Failure::RetryAfterGC(request, NEW_SPACE)->allocation_space());
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000186 CHECK_EQ(OLD_POINTER_SPACE,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000187 Failure::RetryAfterGC(request,
188 OLD_POINTER_SPACE)->allocation_space());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000189 CHECK(Failure::Exception()->IsFailure());
190 CHECK(Smi::FromInt(Smi::kMinValue)->IsSmi());
191 CHECK(Smi::FromInt(Smi::kMaxValue)->IsSmi());
192}
193
194
195TEST(GarbageCollection) {
196 InitializeVM();
197
198 v8::HandleScope sc;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000199 // Check GC.
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000200 int free_bytes = Heap::MaxObjectSizeInPagedSpace();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000201 CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));
202
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000203 Handle<String> name = Factory::LookupAsciiSymbol("theFunction");
204 Handle<String> prop_name = Factory::LookupAsciiSymbol("theSlot");
205 Handle<String> prop_namex = Factory::LookupAsciiSymbol("theSlotx");
206 Handle<String> obj_name = Factory::LookupAsciiSymbol("theObject");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000207
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000208 {
209 v8::HandleScope inner_scope;
210 // Allocate a function and keep it in global object's property.
211 Handle<JSFunction> function =
212 Factory::NewFunction(name, Factory::undefined_value());
213 Handle<Map> initial_map =
214 Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
215 function->set_initial_map(*initial_map);
216 Top::context()->global()->SetProperty(*name, *function, NONE);
217 // Allocate an object. Unrooted after leaving the scope.
218 Handle<JSObject> obj = Factory::NewJSObject(function);
219 obj->SetProperty(*prop_name, Smi::FromInt(23), NONE);
220 obj->SetProperty(*prop_namex, Smi::FromInt(24), NONE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000221
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000222 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
223 CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex));
224 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000225
226 CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));
227
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000228 // Function should be alive.
229 CHECK(Top::context()->global()->HasLocalProperty(*name));
230 // Check function is retained.
231 Object* func_value = Top::context()->global()->GetProperty(*name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000232 CHECK(func_value->IsJSFunction());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000233 Handle<JSFunction> function(JSFunction::cast(func_value));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000234
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000235 {
236 HandleScope inner_scope;
237 // Allocate another object, make it reachable from global.
238 Handle<JSObject> obj = Factory::NewJSObject(function);
239 Top::context()->global()->SetProperty(*obj_name, *obj, NONE);
240 obj->SetProperty(*prop_name, Smi::FromInt(23), NONE);
241 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000242
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000243 // After gc, it should survive.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000244 CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));
245
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000246 CHECK(Top::context()->global()->HasLocalProperty(*obj_name));
247 CHECK(Top::context()->global()->GetProperty(*obj_name)->IsJSObject());
248 JSObject* obj =
249 JSObject::cast(Top::context()->global()->GetProperty(*obj_name));
250 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000251}
252
253
254static void VerifyStringAllocation(const char* string) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000255 v8::HandleScope scope;
256 Handle<String> s = Factory::NewStringFromUtf8(CStrVector(string));
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000257 CHECK_EQ(StrLength(string), s->length());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000258 for (int index = 0; index < s->length(); index++) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000259 CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(index));
260 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000261}
262
263
264TEST(String) {
265 InitializeVM();
266
267 VerifyStringAllocation("a");
268 VerifyStringAllocation("ab");
269 VerifyStringAllocation("abc");
270 VerifyStringAllocation("abcd");
271 VerifyStringAllocation("fiskerdrengen er paa havet");
272}
273
274
275TEST(LocalHandles) {
276 InitializeVM();
277
278 v8::HandleScope scope;
279 const char* name = "Kasper the spunky";
280 Handle<String> string = Factory::NewStringFromAscii(CStrVector(name));
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000281 CHECK_EQ(StrLength(name), string->length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000282}
283
284
285TEST(GlobalHandles) {
286 InitializeVM();
287
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000288 Handle<Object> h1;
289 Handle<Object> h2;
290 Handle<Object> h3;
291 Handle<Object> h4;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000292
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000293 {
294 HandleScope scope;
295
296 Handle<Object> i = Factory::NewStringFromAscii(CStrVector("fisk"));
297 Handle<Object> u = Factory::NewNumber(1.12344);
298
299 h1 = GlobalHandles::Create(*i);
300 h2 = GlobalHandles::Create(*u);
301 h3 = GlobalHandles::Create(*i);
302 h4 = GlobalHandles::Create(*u);
303 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000304
305 // after gc, it should survive
306 CHECK(Heap::CollectGarbage(0, NEW_SPACE));
307
308 CHECK((*h1)->IsString());
309 CHECK((*h2)->IsHeapNumber());
310 CHECK((*h3)->IsString());
311 CHECK((*h4)->IsHeapNumber());
312
313 CHECK_EQ(*h3, *h1);
314 GlobalHandles::Destroy(h1.location());
315 GlobalHandles::Destroy(h3.location());
316
317 CHECK_EQ(*h4, *h2);
318 GlobalHandles::Destroy(h2.location());
319 GlobalHandles::Destroy(h4.location());
320}
321
322
323static bool WeakPointerCleared = false;
324
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000325static void TestWeakGlobalHandleCallback(v8::Persistent<v8::Value> handle,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000326 void* id) {
327 USE(handle);
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000328 if (1234 == reinterpret_cast<intptr_t>(id)) WeakPointerCleared = true;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000329}
330
331
332TEST(WeakGlobalHandlesScavenge) {
333 InitializeVM();
334
335 WeakPointerCleared = false;
336
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000337 Handle<Object> h1;
338 Handle<Object> h2;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000339
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000340 {
341 HandleScope scope;
342
343 Handle<Object> i = Factory::NewStringFromAscii(CStrVector("fisk"));
344 Handle<Object> u = Factory::NewNumber(1.12344);
345
346 h1 = GlobalHandles::Create(*i);
347 h2 = GlobalHandles::Create(*u);
348 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000349
350 GlobalHandles::MakeWeak(h2.location(),
351 reinterpret_cast<void*>(1234),
352 &TestWeakGlobalHandleCallback);
353
354 // Scavenge treats weak pointers as normal roots.
355 Heap::PerformScavenge();
356
357 CHECK((*h1)->IsString());
358 CHECK((*h2)->IsHeapNumber());
359
360 CHECK(!WeakPointerCleared);
361 CHECK(!GlobalHandles::IsNearDeath(h2.location()));
362 CHECK(!GlobalHandles::IsNearDeath(h1.location()));
363
364 GlobalHandles::Destroy(h1.location());
365 GlobalHandles::Destroy(h2.location());
366}
367
368
369TEST(WeakGlobalHandlesMark) {
370 InitializeVM();
371
372 WeakPointerCleared = false;
373
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000374 Handle<Object> h1;
375 Handle<Object> h2;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000376
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000377 {
378 HandleScope scope;
379
380 Handle<Object> i = Factory::NewStringFromAscii(CStrVector("fisk"));
381 Handle<Object> u = Factory::NewNumber(1.12344);
382
383 h1 = GlobalHandles::Create(*i);
384 h2 = GlobalHandles::Create(*u);
385 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000386
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000387 CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000388 CHECK(Heap::CollectGarbage(0, NEW_SPACE));
389 // Make sure the object is promoted.
390
391 GlobalHandles::MakeWeak(h2.location(),
392 reinterpret_cast<void*>(1234),
393 &TestWeakGlobalHandleCallback);
394 CHECK(!GlobalHandles::IsNearDeath(h1.location()));
395 CHECK(!GlobalHandles::IsNearDeath(h2.location()));
396
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000397 CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000398
399 CHECK((*h1)->IsString());
400
401 CHECK(WeakPointerCleared);
402 CHECK(!GlobalHandles::IsNearDeath(h1.location()));
403 CHECK(GlobalHandles::IsNearDeath(h2.location()));
404
405 GlobalHandles::Destroy(h1.location());
406 GlobalHandles::Destroy(h2.location());
407}
408
409static void TestDeleteWeakGlobalHandleCallback(
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000410 v8::Persistent<v8::Value> handle,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000411 void* id) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000412 if (1234 == reinterpret_cast<intptr_t>(id)) WeakPointerCleared = true;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000413 handle.Dispose();
414}
415
416TEST(DeleteWeakGlobalHandle) {
417 InitializeVM();
418
419 WeakPointerCleared = false;
420
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000421 Handle<Object> h;
422
423 {
424 HandleScope scope;
425
426 Handle<Object> i = Factory::NewStringFromAscii(CStrVector("fisk"));
427 h = GlobalHandles::Create(*i);
428 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000429
430 GlobalHandles::MakeWeak(h.location(),
431 reinterpret_cast<void*>(1234),
432 &TestDeleteWeakGlobalHandleCallback);
433
434 // Scanvenge does not recognize weak reference.
435 Heap::PerformScavenge();
436
437 CHECK(!WeakPointerCleared);
438
439 // Mark-compact treats weak reference properly.
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000440 CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000441
442 CHECK(WeakPointerCleared);
443}
444
445static const char* not_so_random_string_table[] = {
446 "abstract",
447 "boolean",
448 "break",
449 "byte",
450 "case",
451 "catch",
452 "char",
453 "class",
454 "const",
455 "continue",
456 "debugger",
457 "default",
458 "delete",
459 "do",
460 "double",
461 "else",
462 "enum",
463 "export",
464 "extends",
465 "false",
466 "final",
467 "finally",
468 "float",
469 "for",
470 "function",
471 "goto",
472 "if",
473 "implements",
474 "import",
475 "in",
476 "instanceof",
477 "int",
478 "interface",
479 "long",
480 "native",
481 "new",
482 "null",
483 "package",
484 "private",
485 "protected",
486 "public",
487 "return",
488 "short",
489 "static",
490 "super",
491 "switch",
492 "synchronized",
493 "this",
494 "throw",
495 "throws",
496 "transient",
497 "true",
498 "try",
499 "typeof",
500 "var",
501 "void",
502 "volatile",
503 "while",
504 "with",
505 0
506};
507
508
509static void CheckSymbols(const char** strings) {
510 for (const char* string = *strings; *strings != 0; string = *strings++) {
511 Object* a = Heap::LookupAsciiSymbol(string);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000512 // LookupAsciiSymbol may return a failure if a GC is needed.
513 if (a->IsFailure()) continue;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000514 CHECK(a->IsSymbol());
515 Object* b = Heap::LookupAsciiSymbol(string);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000516 if (b->IsFailure()) continue;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000517 CHECK_EQ(b, a);
518 CHECK(String::cast(b)->IsEqualTo(CStrVector(string)));
519 }
520}
521
522
523TEST(SymbolTable) {
524 InitializeVM();
525
526 CheckSymbols(not_so_random_string_table);
527 CheckSymbols(not_so_random_string_table);
528}
529
530
531TEST(FunctionAllocation) {
532 InitializeVM();
533
534 v8::HandleScope sc;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000535 Handle<String> name = Factory::LookupAsciiSymbol("theFunction");
536 Handle<JSFunction> function =
537 Factory::NewFunction(name, Factory::undefined_value());
538 Handle<Map> initial_map =
539 Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
540 function->set_initial_map(*initial_map);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000541
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000542 Handle<String> prop_name = Factory::LookupAsciiSymbol("theSlot");
543 Handle<JSObject> obj = Factory::NewJSObject(function);
544 obj->SetProperty(*prop_name, Smi::FromInt(23), NONE);
545 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000546 // Check that we can add properties to function objects.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000547 function->SetProperty(*prop_name, Smi::FromInt(24), NONE);
548 CHECK_EQ(Smi::FromInt(24), function->GetProperty(*prop_name));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000549}
550
551
552TEST(ObjectProperties) {
553 InitializeVM();
554
555 v8::HandleScope sc;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000556 String* object_symbol = String::cast(Heap::Object_symbol());
557 JSFunction* object_function =
558 JSFunction::cast(Top::context()->global()->GetProperty(object_symbol));
559 Handle<JSFunction> constructor(object_function);
560 Handle<JSObject> obj = Factory::NewJSObject(constructor);
561 Handle<String> first = Factory::LookupAsciiSymbol("first");
562 Handle<String> second = Factory::LookupAsciiSymbol("second");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000563
564 // check for empty
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000565 CHECK(!obj->HasLocalProperty(*first));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000566
567 // add first
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000568 obj->SetProperty(*first, Smi::FromInt(1), NONE);
569 CHECK(obj->HasLocalProperty(*first));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000570
571 // delete first
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000572 CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION));
573 CHECK(!obj->HasLocalProperty(*first));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000574
575 // add first and then second
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000576 obj->SetProperty(*first, Smi::FromInt(1), NONE);
577 obj->SetProperty(*second, Smi::FromInt(2), NONE);
578 CHECK(obj->HasLocalProperty(*first));
579 CHECK(obj->HasLocalProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000580
581 // delete first and then second
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000582 CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION));
583 CHECK(obj->HasLocalProperty(*second));
584 CHECK(obj->DeleteProperty(*second, JSObject::NORMAL_DELETION));
585 CHECK(!obj->HasLocalProperty(*first));
586 CHECK(!obj->HasLocalProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000587
588 // add first and then second
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000589 obj->SetProperty(*first, Smi::FromInt(1), NONE);
590 obj->SetProperty(*second, Smi::FromInt(2), NONE);
591 CHECK(obj->HasLocalProperty(*first));
592 CHECK(obj->HasLocalProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000593
594 // delete second and then first
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000595 CHECK(obj->DeleteProperty(*second, JSObject::NORMAL_DELETION));
596 CHECK(obj->HasLocalProperty(*first));
597 CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION));
598 CHECK(!obj->HasLocalProperty(*first));
599 CHECK(!obj->HasLocalProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000600
601 // check string and symbol match
602 static const char* string1 = "fisk";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000603 Handle<String> s1 = Factory::NewStringFromAscii(CStrVector(string1));
604 obj->SetProperty(*s1, Smi::FromInt(1), NONE);
605 Handle<String> s1_symbol = Factory::LookupAsciiSymbol(string1);
606 CHECK(obj->HasLocalProperty(*s1_symbol));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000607
608 // check symbol and string match
609 static const char* string2 = "fugl";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000610 Handle<String> s2_symbol = Factory::LookupAsciiSymbol(string2);
611 obj->SetProperty(*s2_symbol, Smi::FromInt(1), NONE);
612 Handle<String> s2 = Factory::NewStringFromAscii(CStrVector(string2));
613 CHECK(obj->HasLocalProperty(*s2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000614}
615
616
617TEST(JSObjectMaps) {
618 InitializeVM();
619
620 v8::HandleScope sc;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000621 Handle<String> name = Factory::LookupAsciiSymbol("theFunction");
622 Handle<JSFunction> function =
623 Factory::NewFunction(name, Factory::undefined_value());
624 Handle<Map> initial_map =
625 Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
626 function->set_initial_map(*initial_map);
627
628 Handle<String> prop_name = Factory::LookupAsciiSymbol("theSlot");
629 Handle<JSObject> obj = Factory::NewJSObject(function);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000630
631 // Set a propery
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000632 obj->SetProperty(*prop_name, Smi::FromInt(23), NONE);
633 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000634
635 // Check the map has changed
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000636 CHECK(*initial_map != obj->map());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000637}
638
639
640TEST(JSArray) {
641 InitializeVM();
642
643 v8::HandleScope sc;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000644 Handle<String> name = Factory::LookupAsciiSymbol("Array");
645 Handle<JSFunction> function = Handle<JSFunction>(
646 JSFunction::cast(Top::context()->global()->GetProperty(*name)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000647
648 // Allocate the object.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000649 Handle<JSObject> object = Factory::NewJSObject(function);
650 Handle<JSArray> array = Handle<JSArray>::cast(object);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000651 array->Initialize(0);
652
653 // Set array length to 0.
654 array->SetElementsLength(Smi::FromInt(0));
655 CHECK_EQ(Smi::FromInt(0), array->length());
656 CHECK(array->HasFastElements()); // Must be in fast mode.
657
658 // array[length] = name.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000659 array->SetElement(0, *name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000660 CHECK_EQ(Smi::FromInt(1), array->length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000661 CHECK_EQ(array->GetElement(0), *name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000662
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000663 // Set array length with larger than smi value.
664 Handle<Object> length =
665 Factory::NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1);
666 array->SetElementsLength(*length);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000667
668 uint32_t int_length = 0;
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000669 CHECK(length->ToArrayIndex(&int_length));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000670 CHECK_EQ(*length, array->length());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000671 CHECK(array->HasDictionaryElements()); // Must be in slow mode.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000672
673 // array[length] = name.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000674 array->SetElement(int_length, *name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000675 uint32_t new_int_length = 0;
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000676 CHECK(array->length()->ToArrayIndex(&new_int_length));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000677 CHECK_EQ(static_cast<double>(int_length), new_int_length - 1);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000678 CHECK_EQ(array->GetElement(int_length), *name);
679 CHECK_EQ(array->GetElement(0), *name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000680}
681
682
683TEST(JSObjectCopy) {
684 InitializeVM();
685
686 v8::HandleScope sc;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000687 String* object_symbol = String::cast(Heap::Object_symbol());
688 JSFunction* object_function =
689 JSFunction::cast(Top::context()->global()->GetProperty(object_symbol));
690 Handle<JSFunction> constructor(object_function);
691 Handle<JSObject> obj = Factory::NewJSObject(constructor);
692 Handle<String> first = Factory::LookupAsciiSymbol("first");
693 Handle<String> second = Factory::LookupAsciiSymbol("second");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000694
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000695 obj->SetProperty(*first, Smi::FromInt(1), NONE);
696 obj->SetProperty(*second, Smi::FromInt(2), NONE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000697
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000698 obj->SetElement(0, *first);
699 obj->SetElement(1, *second);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000700
701 // Make the clone.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000702 Handle<JSObject> clone = Copy(obj);
703 CHECK(!clone.is_identical_to(obj));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000704
705 CHECK_EQ(obj->GetElement(0), clone->GetElement(0));
706 CHECK_EQ(obj->GetElement(1), clone->GetElement(1));
707
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000708 CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*first));
709 CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000710
711 // Flip the values.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000712 clone->SetProperty(*first, Smi::FromInt(2), NONE);
713 clone->SetProperty(*second, Smi::FromInt(1), NONE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000714
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000715 clone->SetElement(0, *second);
716 clone->SetElement(1, *first);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000717
718 CHECK_EQ(obj->GetElement(1), clone->GetElement(0));
719 CHECK_EQ(obj->GetElement(0), clone->GetElement(1));
720
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000721 CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*first));
722 CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000723}
724
725
726TEST(StringAllocation) {
727 InitializeVM();
728
729
730 const unsigned char chars[] = { 0xe5, 0xa4, 0xa7 };
731 for (int length = 0; length < 100; length++) {
732 v8::HandleScope scope;
733 char* non_ascii = NewArray<char>(3 * length + 1);
734 char* ascii = NewArray<char>(length + 1);
735 non_ascii[3 * length] = 0;
736 ascii[length] = 0;
737 for (int i = 0; i < length; i++) {
738 ascii[i] = 'a';
739 non_ascii[3 * i] = chars[0];
740 non_ascii[3 * i + 1] = chars[1];
741 non_ascii[3 * i + 2] = chars[2];
742 }
743 Handle<String> non_ascii_sym =
744 Factory::LookupSymbol(Vector<const char>(non_ascii, 3 * length));
745 CHECK_EQ(length, non_ascii_sym->length());
746 Handle<String> ascii_sym =
747 Factory::LookupSymbol(Vector<const char>(ascii, length));
748 CHECK_EQ(length, ascii_sym->length());
749 Handle<String> non_ascii_str =
750 Factory::NewStringFromUtf8(Vector<const char>(non_ascii, 3 * length));
751 non_ascii_str->Hash();
752 CHECK_EQ(length, non_ascii_str->length());
753 Handle<String> ascii_str =
754 Factory::NewStringFromUtf8(Vector<const char>(ascii, length));
755 ascii_str->Hash();
756 CHECK_EQ(length, ascii_str->length());
757 DeleteArray(non_ascii);
758 DeleteArray(ascii);
759 }
760}
761
762
763static int ObjectsFoundInHeap(Handle<Object> objs[], int size) {
764 // Count the number of objects found in the heap.
765 int found_count = 0;
766 HeapIterator iterator;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000767 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000768 for (int i = 0; i < size; i++) {
769 if (*objs[i] == obj) {
770 found_count++;
771 }
772 }
773 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000774 return found_count;
775}
776
777
778TEST(Iteration) {
779 InitializeVM();
780 v8::HandleScope scope;
781
782 // Array of objects to scan haep for.
783 const int objs_count = 6;
784 Handle<Object> objs[objs_count];
785 int next_objs_index = 0;
786
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000787 // Allocate a JS array to OLD_POINTER_SPACE and NEW_SPACE
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000788 objs[next_objs_index++] = Factory::NewJSArray(10);
789 objs[next_objs_index++] = Factory::NewJSArray(10, TENURED);
790
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000791 // Allocate a small string to OLD_DATA_SPACE and NEW_SPACE
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000792 objs[next_objs_index++] =
793 Factory::NewStringFromAscii(CStrVector("abcdefghij"));
794 objs[next_objs_index++] =
795 Factory::NewStringFromAscii(CStrVector("abcdefghij"), TENURED);
796
797 // Allocate a large string (for large object space).
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000798 int large_size = Heap::MaxObjectSizeInPagedSpace() + 1;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000799 char* str = new char[large_size];
800 for (int i = 0; i < large_size - 1; ++i) str[i] = 'a';
801 str[large_size - 1] = '\0';
802 objs[next_objs_index++] =
803 Factory::NewStringFromAscii(CStrVector(str), TENURED);
804 delete[] str;
805
806 // Add a Map object to look for.
807 objs[next_objs_index++] = Handle<Map>(HeapObject::cast(*objs[0])->map());
808
809 CHECK_EQ(objs_count, next_objs_index);
810 CHECK_EQ(objs_count, ObjectsFoundInHeap(objs, objs_count));
811}
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000812
813
814TEST(LargeObjectSpaceContains) {
815 InitializeVM();
816
817 int free_bytes = Heap::MaxObjectSizeInPagedSpace();
818 CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));
819
820 Address current_top = Heap::new_space()->top();
821 Page* page = Page::FromAddress(current_top);
822 Address current_page = page->address();
823 Address next_page = current_page + Page::kPageSize;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000824 int bytes_to_page = static_cast<int>(next_page - current_top);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000825 if (bytes_to_page <= FixedArray::kHeaderSize) {
826 // Alas, need to cross another page to be able to
827 // put desired value.
828 next_page += Page::kPageSize;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000829 bytes_to_page = static_cast<int>(next_page - current_top);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000830 }
831 CHECK(bytes_to_page > FixedArray::kHeaderSize);
832
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000833 intptr_t* flags_ptr = &Page::FromAddress(next_page)->flags_;
fschneider@chromium.org013f3e12010-04-26 13:27:52 +0000834 Address flags_addr = reinterpret_cast<Address>(flags_ptr);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000835
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000836 int bytes_to_allocate =
fschneider@chromium.org013f3e12010-04-26 13:27:52 +0000837 static_cast<int>(flags_addr - current_top) + kPointerSize;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000838
839 int n_elements = (bytes_to_allocate - FixedArray::kHeaderSize) /
840 kPointerSize;
841 CHECK_EQ(bytes_to_allocate, FixedArray::SizeFor(n_elements));
842 FixedArray* array = FixedArray::cast(
843 Heap::AllocateFixedArray(n_elements));
844
845 int index = n_elements - 1;
fschneider@chromium.org013f3e12010-04-26 13:27:52 +0000846 CHECK_EQ(flags_ptr,
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000847 HeapObject::RawField(array, FixedArray::OffsetOfElementAt(index)));
848 array->set(index, Smi::FromInt(0));
849 // This chould have turned next page into LargeObjectPage:
850 // CHECK(Page::FromAddress(next_page)->IsLargeObjectPage());
851
852 HeapObject* addr = HeapObject::FromAddress(next_page + 2 * kPointerSize);
853 CHECK(Heap::new_space()->Contains(addr));
854 CHECK(!Heap::lo_space()->Contains(addr));
855}
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000856
857
858TEST(EmptyHandleEscapeFrom) {
859 InitializeVM();
860
861 v8::HandleScope scope;
862 Handle<JSObject> runaway;
863
864 {
865 v8::HandleScope nested;
866 Handle<JSObject> empty;
867 runaway = empty.EscapeFrom(&nested);
868 }
869
870 CHECK(runaway.is_null());
871}
872
873
874static int LenFromSize(int size) {
875 return (size - FixedArray::kHeaderSize) / kPointerSize;
876}
877
878
879TEST(Regression39128) {
880 // Test case for crbug.com/39128.
881 InitializeVM();
882
883 // Increase the chance of 'bump-the-pointer' allocation in old space.
884 bool force_compaction = true;
885 Heap::CollectAllGarbage(force_compaction);
886
887 v8::HandleScope scope;
888
889 // The plan: create JSObject which references objects in new space.
890 // Then clone this object (forcing it to go into old space) and check
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000891 // that region dirty marks are updated correctly.
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000892
893 // Step 1: prepare a map for the object. We add 1 inobject property to it.
894 Handle<JSFunction> object_ctor(Top::global_context()->object_function());
895 CHECK(object_ctor->has_initial_map());
896 Handle<Map> object_map(object_ctor->initial_map());
897 // Create a map with single inobject property.
898 Handle<Map> my_map = Factory::CopyMap(object_map, 1);
899 int n_properties = my_map->inobject_properties();
900 CHECK_GT(n_properties, 0);
901
902 int object_size = my_map->instance_size();
903
904 // Step 2: allocate a lot of objects so to almost fill new space: we need
905 // just enough room to allocate JSObject and thus fill the newspace.
906
907 int allocation_amount = Min(FixedArray::kMaxSize,
908 Heap::MaxObjectSizeInNewSpace());
909 int allocation_len = LenFromSize(allocation_amount);
910 NewSpace* new_space = Heap::new_space();
911 Address* top_addr = new_space->allocation_top_address();
912 Address* limit_addr = new_space->allocation_limit_address();
913 while ((*limit_addr - *top_addr) > allocation_amount) {
914 CHECK(!Heap::always_allocate());
915 Object* array = Heap::AllocateFixedArray(allocation_len);
916 CHECK(!array->IsFailure());
917 CHECK(new_space->Contains(array));
918 }
919
920 // Step 3: now allocate fixed array and JSObject to fill the whole new space.
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000921 int to_fill = static_cast<int>(*limit_addr - *top_addr - object_size);
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000922 int fixed_array_len = LenFromSize(to_fill);
923 CHECK(fixed_array_len < FixedArray::kMaxLength);
924
925 CHECK(!Heap::always_allocate());
926 Object* array = Heap::AllocateFixedArray(fixed_array_len);
927 CHECK(!array->IsFailure());
928 CHECK(new_space->Contains(array));
929
930 Object* object = Heap::AllocateJSObjectFromMap(*my_map);
931 CHECK(!object->IsFailure());
932 CHECK(new_space->Contains(object));
933 JSObject* jsobject = JSObject::cast(object);
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000934 CHECK_EQ(0, FixedArray::cast(jsobject->elements())->length());
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000935 CHECK_EQ(0, jsobject->properties()->length());
936 // Create a reference to object in new space in jsobject.
937 jsobject->FastPropertyAtPut(-1, array);
938
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000939 CHECK_EQ(0, static_cast<int>(*limit_addr - *top_addr));
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000940
941 // Step 4: clone jsobject, but force always allocate first to create a clone
942 // in old pointer space.
943 Address old_pointer_space_top = Heap::old_pointer_space()->top();
944 AlwaysAllocateScope aa_scope;
945 Object* clone_obj = Heap::CopyJSObject(jsobject);
946 CHECK(!object->IsFailure());
947 JSObject* clone = JSObject::cast(clone_obj);
948 if (clone->address() != old_pointer_space_top) {
949 // Alas, got allocated from free list, we cannot do checks.
950 return;
951 }
952 CHECK(Heap::old_pointer_space()->Contains(clone->address()));
953
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000954 // Step 5: verify validity of region dirty marks.
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000955 Address clone_addr = clone->address();
956 Page* page = Page::FromAddress(clone_addr);
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000957 // Check that region covering inobject property 1 is marked dirty.
958 CHECK(page->IsRegionDirty(clone_addr + (object_size - kPointerSize)));
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000959}
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000960
961TEST(TestCodeFlushing) {
962 i::FLAG_allow_natives_syntax = true;
ricow@chromium.orgfd0930e2010-06-11 10:37:34 +0000963 // If we do not flush code this test is invalid.
964 if (!FLAG_flush_code) return;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000965 InitializeVM();
966 v8::HandleScope scope;
967 const char* source = "function foo() {"
968 " var x = 42;"
969 " var y = 42;"
970 " var z = x + y;"
971 "};"
972 "foo()";
973 Handle<String> foo_name = Factory::LookupAsciiSymbol("foo");
974
975 // This compile will add the code to the compilation cache.
976 CompileRun(source);
977
978 // Check function is compiled.
979 Object* func_value = Top::context()->global()->GetProperty(*foo_name);
980 CHECK(func_value->IsJSFunction());
981 Handle<JSFunction> function(JSFunction::cast(func_value));
982 CHECK(function->shared()->is_compiled());
983
984 Heap::CollectAllGarbage(true);
985 Heap::CollectAllGarbage(true);
986
987 // foo should still be in the compilation cache and therefore not
988 // have been removed.
989 CHECK(function->shared()->is_compiled());
990 Heap::CollectAllGarbage(true);
991 Heap::CollectAllGarbage(true);
992 Heap::CollectAllGarbage(true);
993 Heap::CollectAllGarbage(true);
994
995 // foo should no longer be in the compilation cache
996 CHECK(!function->shared()->is_compiled());
997 // Call foo to get it recompiled.
998 CompileRun("foo()");
999 CHECK(function->shared()->is_compiled());
1000}