blob: eec024f3fd1acc1b735913ec87073f0396cab109 [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);
erik.corry@gmail.com145eff52010-08-23 11:36:18 +000039 CheckMap(Heap::fixed_array_map(), FIXED_ARRAY_TYPE, kVariableSizeSentinel);
40 CheckMap(Heap::string_map(), STRING_TYPE, kVariableSizeSentinel);
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,
kasperl@chromium.org061ef742009-02-27 12:16:20 +000080 Code::ComputeFlags(Code::STUB),
81 Handle<Object>(Heap::undefined_value()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000082 CHECK(code->IsCode());
83
84 HeapObject* obj = HeapObject::cast(code);
85 Address obj_addr = obj->address();
86
87 for (int i = 0; i < obj->Size(); i += kPointerSize) {
88 Object* found = Heap::FindCodeObject(obj_addr + i);
89 CHECK_EQ(code, found);
90 }
91
kasperl@chromium.org061ef742009-02-27 12:16:20 +000092 Object* copy = Heap::CreateCode(desc,
kasperl@chromium.org061ef742009-02-27 12:16:20 +000093 Code::ComputeFlags(Code::STUB),
94 Handle<Object>(Heap::undefined_value()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000095 CHECK(copy->IsCode());
96 HeapObject* obj_copy = HeapObject::cast(copy);
97 Object* not_right = Heap::FindCodeObject(obj_copy->address() +
98 obj_copy->Size() / 2);
99 CHECK(not_right != code);
100}
101
102
103TEST(HeapObjects) {
104 InitializeVM();
105
106 v8::HandleScope sc;
107 Object* value = Heap::NumberFromDouble(1.000123);
108 CHECK(value->IsHeapNumber());
109 CHECK(value->IsNumber());
110 CHECK_EQ(1.000123, value->Number());
111
112 value = Heap::NumberFromDouble(1.0);
113 CHECK(value->IsSmi());
114 CHECK(value->IsNumber());
115 CHECK_EQ(1.0, value->Number());
116
117 value = Heap::NumberFromInt32(1024);
118 CHECK(value->IsSmi());
119 CHECK(value->IsNumber());
120 CHECK_EQ(1024.0, value->Number());
121
122 value = Heap::NumberFromInt32(Smi::kMinValue);
123 CHECK(value->IsSmi());
124 CHECK(value->IsNumber());
125 CHECK_EQ(Smi::kMinValue, Smi::cast(value)->value());
126
127 value = Heap::NumberFromInt32(Smi::kMaxValue);
128 CHECK(value->IsSmi());
129 CHECK(value->IsNumber());
130 CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value());
131
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000132#ifndef V8_TARGET_ARCH_X64
133 // TODO(lrn): We need a NumberFromIntptr function in order to test this.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000134 value = Heap::NumberFromInt32(Smi::kMinValue - 1);
135 CHECK(value->IsHeapNumber());
136 CHECK(value->IsNumber());
137 CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000138#endif
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000139
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000140 value = Heap::NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000141 CHECK(value->IsHeapNumber());
142 CHECK(value->IsNumber());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000143 CHECK_EQ(static_cast<double>(static_cast<uint32_t>(Smi::kMaxValue) + 1),
144 value->Number());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000145
146 // nan oddball checks
147 CHECK(Heap::nan_value()->IsNumber());
148 CHECK(isnan(Heap::nan_value()->Number()));
149
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000150 Handle<String> s = Factory::NewStringFromAscii(CStrVector("fisk hest "));
151 CHECK(s->IsString());
152 CHECK_EQ(10, s->length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000153
154 String* object_symbol = String::cast(Heap::Object_symbol());
155 CHECK(Top::context()->global()->HasLocalProperty(object_symbol));
156
157 // Check ToString for oddballs
158 CheckOddball(Heap::true_value(), "true");
159 CheckOddball(Heap::false_value(), "false");
160 CheckOddball(Heap::null_value(), "null");
161 CheckOddball(Heap::undefined_value(), "undefined");
162
163 // Check ToString for Smis
164 CheckSmi(0, "0");
165 CheckSmi(42, "42");
166 CheckSmi(-42, "-42");
167
168 // Check ToString for Numbers
169 CheckNumber(1.1, "1.1");
170
171 CheckFindCodeObject();
172}
173
174
175TEST(Tagging) {
176 InitializeVM();
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000177 int request = 24;
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000178 CHECK_EQ(request, static_cast<int>(OBJECT_POINTER_ALIGN(request)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000179 CHECK(Smi::FromInt(42)->IsSmi());
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000180 CHECK(Failure::RetryAfterGC(request, NEW_SPACE)->IsFailure());
181 CHECK_EQ(request, Failure::RetryAfterGC(request, NEW_SPACE)->requested());
182 CHECK_EQ(NEW_SPACE,
183 Failure::RetryAfterGC(request, NEW_SPACE)->allocation_space());
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000184 CHECK_EQ(OLD_POINTER_SPACE,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000185 Failure::RetryAfterGC(request,
186 OLD_POINTER_SPACE)->allocation_space());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000187 CHECK(Failure::Exception()->IsFailure());
188 CHECK(Smi::FromInt(Smi::kMinValue)->IsSmi());
189 CHECK(Smi::FromInt(Smi::kMaxValue)->IsSmi());
190}
191
192
193TEST(GarbageCollection) {
194 InitializeVM();
195
196 v8::HandleScope sc;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000197 // Check GC.
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000198 int free_bytes = Heap::MaxObjectSizeInPagedSpace();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000199 CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));
200
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000201 Handle<String> name = Factory::LookupAsciiSymbol("theFunction");
202 Handle<String> prop_name = Factory::LookupAsciiSymbol("theSlot");
203 Handle<String> prop_namex = Factory::LookupAsciiSymbol("theSlotx");
204 Handle<String> obj_name = Factory::LookupAsciiSymbol("theObject");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000205
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000206 {
207 v8::HandleScope inner_scope;
208 // Allocate a function and keep it in global object's property.
209 Handle<JSFunction> function =
210 Factory::NewFunction(name, Factory::undefined_value());
211 Handle<Map> initial_map =
212 Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
213 function->set_initial_map(*initial_map);
214 Top::context()->global()->SetProperty(*name, *function, NONE);
215 // Allocate an object. Unrooted after leaving the scope.
216 Handle<JSObject> obj = Factory::NewJSObject(function);
217 obj->SetProperty(*prop_name, Smi::FromInt(23), NONE);
218 obj->SetProperty(*prop_namex, Smi::FromInt(24), NONE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000219
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000220 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
221 CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex));
222 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000223
224 CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));
225
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000226 // Function should be alive.
227 CHECK(Top::context()->global()->HasLocalProperty(*name));
228 // Check function is retained.
229 Object* func_value = Top::context()->global()->GetProperty(*name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000230 CHECK(func_value->IsJSFunction());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000231 Handle<JSFunction> function(JSFunction::cast(func_value));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000232
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000233 {
234 HandleScope inner_scope;
235 // Allocate another object, make it reachable from global.
236 Handle<JSObject> obj = Factory::NewJSObject(function);
237 Top::context()->global()->SetProperty(*obj_name, *obj, NONE);
238 obj->SetProperty(*prop_name, Smi::FromInt(23), NONE);
239 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000240
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000241 // After gc, it should survive.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000242 CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));
243
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000244 CHECK(Top::context()->global()->HasLocalProperty(*obj_name));
245 CHECK(Top::context()->global()->GetProperty(*obj_name)->IsJSObject());
246 JSObject* obj =
247 JSObject::cast(Top::context()->global()->GetProperty(*obj_name));
248 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000249}
250
251
252static void VerifyStringAllocation(const char* string) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000253 v8::HandleScope scope;
254 Handle<String> s = Factory::NewStringFromUtf8(CStrVector(string));
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000255 CHECK_EQ(StrLength(string), s->length());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000256 for (int index = 0; index < s->length(); index++) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000257 CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(index));
258 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000259}
260
261
262TEST(String) {
263 InitializeVM();
264
265 VerifyStringAllocation("a");
266 VerifyStringAllocation("ab");
267 VerifyStringAllocation("abc");
268 VerifyStringAllocation("abcd");
269 VerifyStringAllocation("fiskerdrengen er paa havet");
270}
271
272
273TEST(LocalHandles) {
274 InitializeVM();
275
276 v8::HandleScope scope;
277 const char* name = "Kasper the spunky";
278 Handle<String> string = Factory::NewStringFromAscii(CStrVector(name));
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000279 CHECK_EQ(StrLength(name), string->length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000280}
281
282
283TEST(GlobalHandles) {
284 InitializeVM();
285
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000286 Handle<Object> h1;
287 Handle<Object> h2;
288 Handle<Object> h3;
289 Handle<Object> h4;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000290
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000291 {
292 HandleScope scope;
293
294 Handle<Object> i = Factory::NewStringFromAscii(CStrVector("fisk"));
295 Handle<Object> u = Factory::NewNumber(1.12344);
296
297 h1 = GlobalHandles::Create(*i);
298 h2 = GlobalHandles::Create(*u);
299 h3 = GlobalHandles::Create(*i);
300 h4 = GlobalHandles::Create(*u);
301 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000302
303 // after gc, it should survive
304 CHECK(Heap::CollectGarbage(0, NEW_SPACE));
305
306 CHECK((*h1)->IsString());
307 CHECK((*h2)->IsHeapNumber());
308 CHECK((*h3)->IsString());
309 CHECK((*h4)->IsHeapNumber());
310
311 CHECK_EQ(*h3, *h1);
312 GlobalHandles::Destroy(h1.location());
313 GlobalHandles::Destroy(h3.location());
314
315 CHECK_EQ(*h4, *h2);
316 GlobalHandles::Destroy(h2.location());
317 GlobalHandles::Destroy(h4.location());
318}
319
320
321static bool WeakPointerCleared = false;
322
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000323static void TestWeakGlobalHandleCallback(v8::Persistent<v8::Value> handle,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000324 void* id) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000325 if (1234 == reinterpret_cast<intptr_t>(id)) WeakPointerCleared = true;
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000326 handle.Dispose();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000327}
328
329
330TEST(WeakGlobalHandlesScavenge) {
331 InitializeVM();
332
333 WeakPointerCleared = false;
334
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000335 Handle<Object> h1;
336 Handle<Object> h2;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000337
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000338 {
339 HandleScope scope;
340
341 Handle<Object> i = Factory::NewStringFromAscii(CStrVector("fisk"));
342 Handle<Object> u = Factory::NewNumber(1.12344);
343
344 h1 = GlobalHandles::Create(*i);
345 h2 = GlobalHandles::Create(*u);
346 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000347
348 GlobalHandles::MakeWeak(h2.location(),
349 reinterpret_cast<void*>(1234),
350 &TestWeakGlobalHandleCallback);
351
352 // Scavenge treats weak pointers as normal roots.
353 Heap::PerformScavenge();
354
355 CHECK((*h1)->IsString());
356 CHECK((*h2)->IsHeapNumber());
357
358 CHECK(!WeakPointerCleared);
359 CHECK(!GlobalHandles::IsNearDeath(h2.location()));
360 CHECK(!GlobalHandles::IsNearDeath(h1.location()));
361
362 GlobalHandles::Destroy(h1.location());
363 GlobalHandles::Destroy(h2.location());
364}
365
366
367TEST(WeakGlobalHandlesMark) {
368 InitializeVM();
369
370 WeakPointerCleared = false;
371
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000372 Handle<Object> h1;
373 Handle<Object> h2;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000374
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000375 {
376 HandleScope scope;
377
378 Handle<Object> i = Factory::NewStringFromAscii(CStrVector("fisk"));
379 Handle<Object> u = Factory::NewNumber(1.12344);
380
381 h1 = GlobalHandles::Create(*i);
382 h2 = GlobalHandles::Create(*u);
383 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000384
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000385 CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000386 CHECK(Heap::CollectGarbage(0, NEW_SPACE));
387 // Make sure the object is promoted.
388
389 GlobalHandles::MakeWeak(h2.location(),
390 reinterpret_cast<void*>(1234),
391 &TestWeakGlobalHandleCallback);
392 CHECK(!GlobalHandles::IsNearDeath(h1.location()));
393 CHECK(!GlobalHandles::IsNearDeath(h2.location()));
394
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000395 CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000396
397 CHECK((*h1)->IsString());
398
399 CHECK(WeakPointerCleared);
400 CHECK(!GlobalHandles::IsNearDeath(h1.location()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000401
402 GlobalHandles::Destroy(h1.location());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000403}
404
405TEST(DeleteWeakGlobalHandle) {
406 InitializeVM();
407
408 WeakPointerCleared = false;
409
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000410 Handle<Object> h;
411
412 {
413 HandleScope scope;
414
415 Handle<Object> i = Factory::NewStringFromAscii(CStrVector("fisk"));
416 h = GlobalHandles::Create(*i);
417 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000418
419 GlobalHandles::MakeWeak(h.location(),
420 reinterpret_cast<void*>(1234),
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000421 &TestWeakGlobalHandleCallback);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000422
423 // Scanvenge does not recognize weak reference.
424 Heap::PerformScavenge();
425
426 CHECK(!WeakPointerCleared);
427
428 // Mark-compact treats weak reference properly.
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000429 CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000430
431 CHECK(WeakPointerCleared);
432}
433
434static const char* not_so_random_string_table[] = {
435 "abstract",
436 "boolean",
437 "break",
438 "byte",
439 "case",
440 "catch",
441 "char",
442 "class",
443 "const",
444 "continue",
445 "debugger",
446 "default",
447 "delete",
448 "do",
449 "double",
450 "else",
451 "enum",
452 "export",
453 "extends",
454 "false",
455 "final",
456 "finally",
457 "float",
458 "for",
459 "function",
460 "goto",
461 "if",
462 "implements",
463 "import",
464 "in",
465 "instanceof",
466 "int",
467 "interface",
468 "long",
469 "native",
470 "new",
471 "null",
472 "package",
473 "private",
474 "protected",
475 "public",
476 "return",
477 "short",
478 "static",
479 "super",
480 "switch",
481 "synchronized",
482 "this",
483 "throw",
484 "throws",
485 "transient",
486 "true",
487 "try",
488 "typeof",
489 "var",
490 "void",
491 "volatile",
492 "while",
493 "with",
494 0
495};
496
497
498static void CheckSymbols(const char** strings) {
499 for (const char* string = *strings; *strings != 0; string = *strings++) {
500 Object* a = Heap::LookupAsciiSymbol(string);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000501 // LookupAsciiSymbol may return a failure if a GC is needed.
502 if (a->IsFailure()) continue;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000503 CHECK(a->IsSymbol());
504 Object* b = Heap::LookupAsciiSymbol(string);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000505 if (b->IsFailure()) continue;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000506 CHECK_EQ(b, a);
507 CHECK(String::cast(b)->IsEqualTo(CStrVector(string)));
508 }
509}
510
511
512TEST(SymbolTable) {
513 InitializeVM();
514
515 CheckSymbols(not_so_random_string_table);
516 CheckSymbols(not_so_random_string_table);
517}
518
519
520TEST(FunctionAllocation) {
521 InitializeVM();
522
523 v8::HandleScope sc;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000524 Handle<String> name = Factory::LookupAsciiSymbol("theFunction");
525 Handle<JSFunction> function =
526 Factory::NewFunction(name, Factory::undefined_value());
527 Handle<Map> initial_map =
528 Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
529 function->set_initial_map(*initial_map);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000530
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000531 Handle<String> prop_name = Factory::LookupAsciiSymbol("theSlot");
532 Handle<JSObject> obj = Factory::NewJSObject(function);
533 obj->SetProperty(*prop_name, Smi::FromInt(23), NONE);
534 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000535 // Check that we can add properties to function objects.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000536 function->SetProperty(*prop_name, Smi::FromInt(24), NONE);
537 CHECK_EQ(Smi::FromInt(24), function->GetProperty(*prop_name));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000538}
539
540
541TEST(ObjectProperties) {
542 InitializeVM();
543
544 v8::HandleScope sc;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000545 String* object_symbol = String::cast(Heap::Object_symbol());
546 JSFunction* object_function =
547 JSFunction::cast(Top::context()->global()->GetProperty(object_symbol));
548 Handle<JSFunction> constructor(object_function);
549 Handle<JSObject> obj = Factory::NewJSObject(constructor);
550 Handle<String> first = Factory::LookupAsciiSymbol("first");
551 Handle<String> second = Factory::LookupAsciiSymbol("second");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000552
553 // check for empty
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000554 CHECK(!obj->HasLocalProperty(*first));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000555
556 // add first
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000557 obj->SetProperty(*first, Smi::FromInt(1), NONE);
558 CHECK(obj->HasLocalProperty(*first));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000559
560 // delete first
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000561 CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION));
562 CHECK(!obj->HasLocalProperty(*first));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000563
564 // add first and then second
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000565 obj->SetProperty(*first, Smi::FromInt(1), NONE);
566 obj->SetProperty(*second, Smi::FromInt(2), NONE);
567 CHECK(obj->HasLocalProperty(*first));
568 CHECK(obj->HasLocalProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000569
570 // delete first and then second
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000571 CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION));
572 CHECK(obj->HasLocalProperty(*second));
573 CHECK(obj->DeleteProperty(*second, JSObject::NORMAL_DELETION));
574 CHECK(!obj->HasLocalProperty(*first));
575 CHECK(!obj->HasLocalProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000576
577 // add first and then second
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000578 obj->SetProperty(*first, Smi::FromInt(1), NONE);
579 obj->SetProperty(*second, Smi::FromInt(2), NONE);
580 CHECK(obj->HasLocalProperty(*first));
581 CHECK(obj->HasLocalProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000582
583 // delete second and then first
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000584 CHECK(obj->DeleteProperty(*second, JSObject::NORMAL_DELETION));
585 CHECK(obj->HasLocalProperty(*first));
586 CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION));
587 CHECK(!obj->HasLocalProperty(*first));
588 CHECK(!obj->HasLocalProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000589
590 // check string and symbol match
591 static const char* string1 = "fisk";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000592 Handle<String> s1 = Factory::NewStringFromAscii(CStrVector(string1));
593 obj->SetProperty(*s1, Smi::FromInt(1), NONE);
594 Handle<String> s1_symbol = Factory::LookupAsciiSymbol(string1);
595 CHECK(obj->HasLocalProperty(*s1_symbol));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000596
597 // check symbol and string match
598 static const char* string2 = "fugl";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000599 Handle<String> s2_symbol = Factory::LookupAsciiSymbol(string2);
600 obj->SetProperty(*s2_symbol, Smi::FromInt(1), NONE);
601 Handle<String> s2 = Factory::NewStringFromAscii(CStrVector(string2));
602 CHECK(obj->HasLocalProperty(*s2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000603}
604
605
606TEST(JSObjectMaps) {
607 InitializeVM();
608
609 v8::HandleScope sc;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000610 Handle<String> name = Factory::LookupAsciiSymbol("theFunction");
611 Handle<JSFunction> function =
612 Factory::NewFunction(name, Factory::undefined_value());
613 Handle<Map> initial_map =
614 Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
615 function->set_initial_map(*initial_map);
616
617 Handle<String> prop_name = Factory::LookupAsciiSymbol("theSlot");
618 Handle<JSObject> obj = Factory::NewJSObject(function);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000619
620 // Set a propery
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000621 obj->SetProperty(*prop_name, Smi::FromInt(23), NONE);
622 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000623
624 // Check the map has changed
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000625 CHECK(*initial_map != obj->map());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000626}
627
628
629TEST(JSArray) {
630 InitializeVM();
631
632 v8::HandleScope sc;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000633 Handle<String> name = Factory::LookupAsciiSymbol("Array");
634 Handle<JSFunction> function = Handle<JSFunction>(
635 JSFunction::cast(Top::context()->global()->GetProperty(*name)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000636
637 // Allocate the object.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000638 Handle<JSObject> object = Factory::NewJSObject(function);
639 Handle<JSArray> array = Handle<JSArray>::cast(object);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000640 Object* ok = array->Initialize(0);
641 // We just initialized the VM, no heap allocation failure yet.
642 CHECK(!ok->IsFailure());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000643
644 // Set array length to 0.
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000645 ok = array->SetElementsLength(Smi::FromInt(0));
646 CHECK(!ok->IsFailure());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000647 CHECK_EQ(Smi::FromInt(0), array->length());
648 CHECK(array->HasFastElements()); // Must be in fast mode.
649
650 // array[length] = name.
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000651 ok = array->SetElement(0, *name);
652 CHECK(!ok->IsFailure());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000653 CHECK_EQ(Smi::FromInt(1), array->length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000654 CHECK_EQ(array->GetElement(0), *name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000655
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000656 // Set array length with larger than smi value.
657 Handle<Object> length =
658 Factory::NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000659 ok = array->SetElementsLength(*length);
660 CHECK(!ok->IsFailure());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000661
662 uint32_t int_length = 0;
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000663 CHECK(length->ToArrayIndex(&int_length));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000664 CHECK_EQ(*length, array->length());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000665 CHECK(array->HasDictionaryElements()); // Must be in slow mode.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000666
667 // array[length] = name.
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000668 ok = array->SetElement(int_length, *name);
669 CHECK(!ok->IsFailure());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000670 uint32_t new_int_length = 0;
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000671 CHECK(array->length()->ToArrayIndex(&new_int_length));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000672 CHECK_EQ(static_cast<double>(int_length), new_int_length - 1);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000673 CHECK_EQ(array->GetElement(int_length), *name);
674 CHECK_EQ(array->GetElement(0), *name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000675}
676
677
678TEST(JSObjectCopy) {
679 InitializeVM();
680
681 v8::HandleScope sc;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000682 String* object_symbol = String::cast(Heap::Object_symbol());
683 JSFunction* object_function =
684 JSFunction::cast(Top::context()->global()->GetProperty(object_symbol));
685 Handle<JSFunction> constructor(object_function);
686 Handle<JSObject> obj = Factory::NewJSObject(constructor);
687 Handle<String> first = Factory::LookupAsciiSymbol("first");
688 Handle<String> second = Factory::LookupAsciiSymbol("second");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000689
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000690 obj->SetProperty(*first, Smi::FromInt(1), NONE);
691 obj->SetProperty(*second, Smi::FromInt(2), NONE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000692
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000693 Object* ok = obj->SetElement(0, *first);
694 CHECK(!ok->IsFailure());
695
696 ok = obj->SetElement(1, *second);
697 CHECK(!ok->IsFailure());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000698
699 // Make the clone.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000700 Handle<JSObject> clone = Copy(obj);
701 CHECK(!clone.is_identical_to(obj));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000702
703 CHECK_EQ(obj->GetElement(0), clone->GetElement(0));
704 CHECK_EQ(obj->GetElement(1), clone->GetElement(1));
705
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000706 CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*first));
707 CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000708
709 // Flip the values.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000710 clone->SetProperty(*first, Smi::FromInt(2), NONE);
711 clone->SetProperty(*second, Smi::FromInt(1), NONE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000712
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000713 ok = clone->SetElement(0, *second);
714 CHECK(!ok->IsFailure());
715 ok = clone->SetElement(1, *first);
716 CHECK(!ok->IsFailure());
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
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000987 CHECK(function->shared()->is_compiled());
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000988
989 Heap::CollectAllGarbage(true);
990 Heap::CollectAllGarbage(true);
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000991 Heap::CollectAllGarbage(true);
992 Heap::CollectAllGarbage(true);
993 Heap::CollectAllGarbage(true);
994 Heap::CollectAllGarbage(true);
995
996 // foo should no longer be in the compilation cache
997 CHECK(!function->shared()->is_compiled());
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000998 CHECK(!function->is_compiled());
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000999 // Call foo to get it recompiled.
1000 CompileRun("foo()");
1001 CHECK(function->shared()->is_compiled());
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001002 CHECK(function->is_compiled());
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00001003}