blob: 9d5e1f19f9b467a4ec4d248fb3fea41e2462f8f6 [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,
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);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000640 array->Initialize(0);
641
642 // Set array length to 0.
643 array->SetElementsLength(Smi::FromInt(0));
644 CHECK_EQ(Smi::FromInt(0), array->length());
645 CHECK(array->HasFastElements()); // Must be in fast mode.
646
647 // array[length] = name.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000648 array->SetElement(0, *name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000649 CHECK_EQ(Smi::FromInt(1), array->length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000650 CHECK_EQ(array->GetElement(0), *name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000651
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000652 // Set array length with larger than smi value.
653 Handle<Object> length =
654 Factory::NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1);
655 array->SetElementsLength(*length);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000656
657 uint32_t int_length = 0;
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000658 CHECK(length->ToArrayIndex(&int_length));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000659 CHECK_EQ(*length, array->length());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000660 CHECK(array->HasDictionaryElements()); // Must be in slow mode.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000661
662 // array[length] = name.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000663 array->SetElement(int_length, *name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000664 uint32_t new_int_length = 0;
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000665 CHECK(array->length()->ToArrayIndex(&new_int_length));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000666 CHECK_EQ(static_cast<double>(int_length), new_int_length - 1);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000667 CHECK_EQ(array->GetElement(int_length), *name);
668 CHECK_EQ(array->GetElement(0), *name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000669}
670
671
672TEST(JSObjectCopy) {
673 InitializeVM();
674
675 v8::HandleScope sc;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000676 String* object_symbol = String::cast(Heap::Object_symbol());
677 JSFunction* object_function =
678 JSFunction::cast(Top::context()->global()->GetProperty(object_symbol));
679 Handle<JSFunction> constructor(object_function);
680 Handle<JSObject> obj = Factory::NewJSObject(constructor);
681 Handle<String> first = Factory::LookupAsciiSymbol("first");
682 Handle<String> second = Factory::LookupAsciiSymbol("second");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000683
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000684 obj->SetProperty(*first, Smi::FromInt(1), NONE);
685 obj->SetProperty(*second, Smi::FromInt(2), NONE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000686
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000687 obj->SetElement(0, *first);
688 obj->SetElement(1, *second);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000689
690 // Make the clone.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000691 Handle<JSObject> clone = Copy(obj);
692 CHECK(!clone.is_identical_to(obj));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000693
694 CHECK_EQ(obj->GetElement(0), clone->GetElement(0));
695 CHECK_EQ(obj->GetElement(1), clone->GetElement(1));
696
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000697 CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*first));
698 CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000699
700 // Flip the values.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000701 clone->SetProperty(*first, Smi::FromInt(2), NONE);
702 clone->SetProperty(*second, Smi::FromInt(1), NONE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000703
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000704 clone->SetElement(0, *second);
705 clone->SetElement(1, *first);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000706
707 CHECK_EQ(obj->GetElement(1), clone->GetElement(0));
708 CHECK_EQ(obj->GetElement(0), clone->GetElement(1));
709
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000710 CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*first));
711 CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000712}
713
714
715TEST(StringAllocation) {
716 InitializeVM();
717
718
719 const unsigned char chars[] = { 0xe5, 0xa4, 0xa7 };
720 for (int length = 0; length < 100; length++) {
721 v8::HandleScope scope;
722 char* non_ascii = NewArray<char>(3 * length + 1);
723 char* ascii = NewArray<char>(length + 1);
724 non_ascii[3 * length] = 0;
725 ascii[length] = 0;
726 for (int i = 0; i < length; i++) {
727 ascii[i] = 'a';
728 non_ascii[3 * i] = chars[0];
729 non_ascii[3 * i + 1] = chars[1];
730 non_ascii[3 * i + 2] = chars[2];
731 }
732 Handle<String> non_ascii_sym =
733 Factory::LookupSymbol(Vector<const char>(non_ascii, 3 * length));
734 CHECK_EQ(length, non_ascii_sym->length());
735 Handle<String> ascii_sym =
736 Factory::LookupSymbol(Vector<const char>(ascii, length));
737 CHECK_EQ(length, ascii_sym->length());
738 Handle<String> non_ascii_str =
739 Factory::NewStringFromUtf8(Vector<const char>(non_ascii, 3 * length));
740 non_ascii_str->Hash();
741 CHECK_EQ(length, non_ascii_str->length());
742 Handle<String> ascii_str =
743 Factory::NewStringFromUtf8(Vector<const char>(ascii, length));
744 ascii_str->Hash();
745 CHECK_EQ(length, ascii_str->length());
746 DeleteArray(non_ascii);
747 DeleteArray(ascii);
748 }
749}
750
751
752static int ObjectsFoundInHeap(Handle<Object> objs[], int size) {
753 // Count the number of objects found in the heap.
754 int found_count = 0;
755 HeapIterator iterator;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000756 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000757 for (int i = 0; i < size; i++) {
758 if (*objs[i] == obj) {
759 found_count++;
760 }
761 }
762 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000763 return found_count;
764}
765
766
767TEST(Iteration) {
768 InitializeVM();
769 v8::HandleScope scope;
770
771 // Array of objects to scan haep for.
772 const int objs_count = 6;
773 Handle<Object> objs[objs_count];
774 int next_objs_index = 0;
775
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000776 // Allocate a JS array to OLD_POINTER_SPACE and NEW_SPACE
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000777 objs[next_objs_index++] = Factory::NewJSArray(10);
778 objs[next_objs_index++] = Factory::NewJSArray(10, TENURED);
779
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000780 // Allocate a small string to OLD_DATA_SPACE and NEW_SPACE
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000781 objs[next_objs_index++] =
782 Factory::NewStringFromAscii(CStrVector("abcdefghij"));
783 objs[next_objs_index++] =
784 Factory::NewStringFromAscii(CStrVector("abcdefghij"), TENURED);
785
786 // Allocate a large string (for large object space).
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000787 int large_size = Heap::MaxObjectSizeInPagedSpace() + 1;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000788 char* str = new char[large_size];
789 for (int i = 0; i < large_size - 1; ++i) str[i] = 'a';
790 str[large_size - 1] = '\0';
791 objs[next_objs_index++] =
792 Factory::NewStringFromAscii(CStrVector(str), TENURED);
793 delete[] str;
794
795 // Add a Map object to look for.
796 objs[next_objs_index++] = Handle<Map>(HeapObject::cast(*objs[0])->map());
797
798 CHECK_EQ(objs_count, next_objs_index);
799 CHECK_EQ(objs_count, ObjectsFoundInHeap(objs, objs_count));
800}
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000801
802
803TEST(LargeObjectSpaceContains) {
804 InitializeVM();
805
806 int free_bytes = Heap::MaxObjectSizeInPagedSpace();
807 CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));
808
809 Address current_top = Heap::new_space()->top();
810 Page* page = Page::FromAddress(current_top);
811 Address current_page = page->address();
812 Address next_page = current_page + Page::kPageSize;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000813 int bytes_to_page = static_cast<int>(next_page - current_top);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000814 if (bytes_to_page <= FixedArray::kHeaderSize) {
815 // Alas, need to cross another page to be able to
816 // put desired value.
817 next_page += Page::kPageSize;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000818 bytes_to_page = static_cast<int>(next_page - current_top);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000819 }
820 CHECK(bytes_to_page > FixedArray::kHeaderSize);
821
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000822 intptr_t* flags_ptr = &Page::FromAddress(next_page)->flags_;
fschneider@chromium.org013f3e12010-04-26 13:27:52 +0000823 Address flags_addr = reinterpret_cast<Address>(flags_ptr);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000824
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000825 int bytes_to_allocate =
fschneider@chromium.org013f3e12010-04-26 13:27:52 +0000826 static_cast<int>(flags_addr - current_top) + kPointerSize;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000827
828 int n_elements = (bytes_to_allocate - FixedArray::kHeaderSize) /
829 kPointerSize;
830 CHECK_EQ(bytes_to_allocate, FixedArray::SizeFor(n_elements));
831 FixedArray* array = FixedArray::cast(
832 Heap::AllocateFixedArray(n_elements));
833
834 int index = n_elements - 1;
fschneider@chromium.org013f3e12010-04-26 13:27:52 +0000835 CHECK_EQ(flags_ptr,
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000836 HeapObject::RawField(array, FixedArray::OffsetOfElementAt(index)));
837 array->set(index, Smi::FromInt(0));
838 // This chould have turned next page into LargeObjectPage:
839 // CHECK(Page::FromAddress(next_page)->IsLargeObjectPage());
840
841 HeapObject* addr = HeapObject::FromAddress(next_page + 2 * kPointerSize);
842 CHECK(Heap::new_space()->Contains(addr));
843 CHECK(!Heap::lo_space()->Contains(addr));
844}
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000845
846
847TEST(EmptyHandleEscapeFrom) {
848 InitializeVM();
849
850 v8::HandleScope scope;
851 Handle<JSObject> runaway;
852
853 {
854 v8::HandleScope nested;
855 Handle<JSObject> empty;
856 runaway = empty.EscapeFrom(&nested);
857 }
858
859 CHECK(runaway.is_null());
860}
861
862
863static int LenFromSize(int size) {
864 return (size - FixedArray::kHeaderSize) / kPointerSize;
865}
866
867
868TEST(Regression39128) {
869 // Test case for crbug.com/39128.
870 InitializeVM();
871
872 // Increase the chance of 'bump-the-pointer' allocation in old space.
873 bool force_compaction = true;
874 Heap::CollectAllGarbage(force_compaction);
875
876 v8::HandleScope scope;
877
878 // The plan: create JSObject which references objects in new space.
879 // Then clone this object (forcing it to go into old space) and check
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000880 // that region dirty marks are updated correctly.
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000881
882 // Step 1: prepare a map for the object. We add 1 inobject property to it.
883 Handle<JSFunction> object_ctor(Top::global_context()->object_function());
884 CHECK(object_ctor->has_initial_map());
885 Handle<Map> object_map(object_ctor->initial_map());
886 // Create a map with single inobject property.
887 Handle<Map> my_map = Factory::CopyMap(object_map, 1);
888 int n_properties = my_map->inobject_properties();
889 CHECK_GT(n_properties, 0);
890
891 int object_size = my_map->instance_size();
892
893 // Step 2: allocate a lot of objects so to almost fill new space: we need
894 // just enough room to allocate JSObject and thus fill the newspace.
895
896 int allocation_amount = Min(FixedArray::kMaxSize,
897 Heap::MaxObjectSizeInNewSpace());
898 int allocation_len = LenFromSize(allocation_amount);
899 NewSpace* new_space = Heap::new_space();
900 Address* top_addr = new_space->allocation_top_address();
901 Address* limit_addr = new_space->allocation_limit_address();
902 while ((*limit_addr - *top_addr) > allocation_amount) {
903 CHECK(!Heap::always_allocate());
904 Object* array = Heap::AllocateFixedArray(allocation_len);
905 CHECK(!array->IsFailure());
906 CHECK(new_space->Contains(array));
907 }
908
909 // Step 3: now allocate fixed array and JSObject to fill the whole new space.
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000910 int to_fill = static_cast<int>(*limit_addr - *top_addr - object_size);
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000911 int fixed_array_len = LenFromSize(to_fill);
912 CHECK(fixed_array_len < FixedArray::kMaxLength);
913
914 CHECK(!Heap::always_allocate());
915 Object* array = Heap::AllocateFixedArray(fixed_array_len);
916 CHECK(!array->IsFailure());
917 CHECK(new_space->Contains(array));
918
919 Object* object = Heap::AllocateJSObjectFromMap(*my_map);
920 CHECK(!object->IsFailure());
921 CHECK(new_space->Contains(object));
922 JSObject* jsobject = JSObject::cast(object);
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000923 CHECK_EQ(0, FixedArray::cast(jsobject->elements())->length());
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000924 CHECK_EQ(0, jsobject->properties()->length());
925 // Create a reference to object in new space in jsobject.
926 jsobject->FastPropertyAtPut(-1, array);
927
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000928 CHECK_EQ(0, static_cast<int>(*limit_addr - *top_addr));
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000929
930 // Step 4: clone jsobject, but force always allocate first to create a clone
931 // in old pointer space.
932 Address old_pointer_space_top = Heap::old_pointer_space()->top();
933 AlwaysAllocateScope aa_scope;
934 Object* clone_obj = Heap::CopyJSObject(jsobject);
935 CHECK(!object->IsFailure());
936 JSObject* clone = JSObject::cast(clone_obj);
937 if (clone->address() != old_pointer_space_top) {
938 // Alas, got allocated from free list, we cannot do checks.
939 return;
940 }
941 CHECK(Heap::old_pointer_space()->Contains(clone->address()));
942
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000943 // Step 5: verify validity of region dirty marks.
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000944 Address clone_addr = clone->address();
945 Page* page = Page::FromAddress(clone_addr);
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000946 // Check that region covering inobject property 1 is marked dirty.
947 CHECK(page->IsRegionDirty(clone_addr + (object_size - kPointerSize)));
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000948}
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000949
950TEST(TestCodeFlushing) {
951 i::FLAG_allow_natives_syntax = true;
ricow@chromium.orgfd0930e2010-06-11 10:37:34 +0000952 // If we do not flush code this test is invalid.
953 if (!FLAG_flush_code) return;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000954 InitializeVM();
955 v8::HandleScope scope;
956 const char* source = "function foo() {"
957 " var x = 42;"
958 " var y = 42;"
959 " var z = x + y;"
960 "};"
961 "foo()";
962 Handle<String> foo_name = Factory::LookupAsciiSymbol("foo");
963
964 // This compile will add the code to the compilation cache.
965 CompileRun(source);
966
967 // Check function is compiled.
968 Object* func_value = Top::context()->global()->GetProperty(*foo_name);
969 CHECK(func_value->IsJSFunction());
970 Handle<JSFunction> function(JSFunction::cast(func_value));
971 CHECK(function->shared()->is_compiled());
972
973 Heap::CollectAllGarbage(true);
974 Heap::CollectAllGarbage(true);
975
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000976 CHECK(function->shared()->is_compiled());
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000977
978 Heap::CollectAllGarbage(true);
979 Heap::CollectAllGarbage(true);
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000980 Heap::CollectAllGarbage(true);
981 Heap::CollectAllGarbage(true);
982 Heap::CollectAllGarbage(true);
983 Heap::CollectAllGarbage(true);
984
985 // foo should no longer be in the compilation cache
986 CHECK(!function->shared()->is_compiled());
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000987 CHECK(!function->is_compiled());
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000988 // Call foo to get it recompiled.
989 CompileRun("foo()");
990 CHECK(function->shared()->is_compiled());
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000991 CHECK(function->is_compiled());
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000992}