The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / test / cctest / test-heap.cc @ 40c0f755

History | View | Annotate | Download (23 KB)

1
// Copyright 2006-2008 the V8 project authors. All rights reserved.
2

    
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

    
13
using namespace v8::internal;
14

    
15
static v8::Persistent<v8::Context> env;
16

    
17
static void InitializeVM() {
18
  if (env.IsEmpty()) env = v8::Context::New();
19
  v8::HandleScope scope;
20
  env->Enter();
21
}
22

    
23

    
24
static 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

    
35
TEST(HeapMaps) {
36
  InitializeVM();
37
  CheckMap(Heap::meta_map(), MAP_TYPE, Map::kSize);
38
  CheckMap(Heap::heap_number_map(), HEAP_NUMBER_TYPE, HeapNumber::kSize);
39
  CheckMap(Heap::fixed_array_map(), FIXED_ARRAY_TYPE, Array::kHeaderSize);
40
  CheckMap(Heap::long_string_map(), LONG_STRING_TYPE,
41
           SeqTwoByteString::kHeaderSize);
42
}
43

    
44

    
45
static void CheckOddball(Object* obj, const char* string) {
46
  CHECK(obj->IsOddball());
47
  bool exc;
48
  Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
49
  CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
50
}
51

    
52

    
53
static void CheckSmi(int value, const char* string) {
54
  bool exc;
55
  Object* print_string =
56
      *Execution::ToString(Handle<Object>(Smi::FromInt(value)), &exc);
57
  CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
58
}
59

    
60

    
61
static void CheckNumber(double value, const char* string) {
62
  Object* obj = Heap::NumberFromDouble(value);
63
  CHECK(obj->IsNumber());
64
  bool exc;
65
  Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
66
  CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
67
}
68

    
69

    
70
static void CheckFindCodeObject() {
71
  // Test FindCodeObject
72
#define __ assm.
73

    
74
  Assembler assm(NULL, 0);
75

    
76
  __ nop();  // supported on all architectures
77

    
78
  CodeDesc desc;
79
  assm.GetCode(&desc);
80
  Object* code = Heap::CreateCode(desc,
81
                                  NULL,
82
                                  Code::ComputeFlags(Code::STUB),
83
                                  Handle<Object>(Heap::undefined_value()));
84
  CHECK(code->IsCode());
85

    
86
  HeapObject* obj = HeapObject::cast(code);
87
  Address obj_addr = obj->address();
88

    
89
  for (int i = 0; i < obj->Size(); i += kPointerSize) {
90
    Object* found = Heap::FindCodeObject(obj_addr + i);
91
    CHECK_EQ(code, found);
92
  }
93

    
94
  Object* copy = Heap::CreateCode(desc,
95
                                  NULL,
96
                                  Code::ComputeFlags(Code::STUB),
97
                                  Handle<Object>(Heap::undefined_value()));
98
  CHECK(copy->IsCode());
99
  HeapObject* obj_copy = HeapObject::cast(copy);
100
  Object* not_right = Heap::FindCodeObject(obj_copy->address() +
101
                                           obj_copy->Size() / 2);
102
  CHECK(not_right != code);
103
}
104

    
105

    
106
TEST(HeapObjects) {
107
  InitializeVM();
108

    
109
  v8::HandleScope sc;
110
  Object* value = Heap::NumberFromDouble(1.000123);
111
  CHECK(value->IsHeapNumber());
112
  CHECK(value->IsNumber());
113
  CHECK_EQ(1.000123, value->Number());
114

    
115
  value = Heap::NumberFromDouble(1.0);
116
  CHECK(value->IsSmi());
117
  CHECK(value->IsNumber());
118
  CHECK_EQ(1.0, value->Number());
119

    
120
  value = Heap::NumberFromInt32(1024);
121
  CHECK(value->IsSmi());
122
  CHECK(value->IsNumber());
123
  CHECK_EQ(1024.0, value->Number());
124

    
125
  value = Heap::NumberFromInt32(Smi::kMinValue);
126
  CHECK(value->IsSmi());
127
  CHECK(value->IsNumber());
128
  CHECK_EQ(Smi::kMinValue, Smi::cast(value)->value());
129

    
130
  value = Heap::NumberFromInt32(Smi::kMaxValue);
131
  CHECK(value->IsSmi());
132
  CHECK(value->IsNumber());
133
  CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value());
134

    
135
  value = Heap::NumberFromInt32(Smi::kMinValue - 1);
136
  CHECK(value->IsHeapNumber());
137
  CHECK(value->IsNumber());
138
  CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number());
139

    
140
  value = Heap::NumberFromInt32(Smi::kMaxValue + 1);
141
  CHECK(value->IsHeapNumber());
142
  CHECK(value->IsNumber());
143
  CHECK_EQ(static_cast<double>(Smi::kMaxValue + 1), value->Number());
144

    
145
  // nan oddball checks
146
  CHECK(Heap::nan_value()->IsNumber());
147
  CHECK(isnan(Heap::nan_value()->Number()));
148

    
149
  Object* str = Heap::AllocateStringFromAscii(CStrVector("fisk hest "));
150
  if (!str->IsFailure()) {
151
    String* s =  String::cast(str);
152
    CHECK(s->IsString());
153
    CHECK_EQ(10, s->length());
154
  } else {
155
    CHECK(false);
156
  }
157

    
158
  String* object_symbol = String::cast(Heap::Object_symbol());
159
  CHECK(Top::context()->global()->HasLocalProperty(object_symbol));
160

    
161
  // Check ToString for oddballs
162
  CheckOddball(Heap::true_value(), "true");
163
  CheckOddball(Heap::false_value(), "false");
164
  CheckOddball(Heap::null_value(), "null");
165
  CheckOddball(Heap::undefined_value(), "undefined");
166

    
167
  // Check ToString for Smis
168
  CheckSmi(0, "0");
169
  CheckSmi(42, "42");
170
  CheckSmi(-42, "-42");
171

    
172
  // Check ToString for Numbers
173
  CheckNumber(1.1, "1.1");
174

    
175
  CheckFindCodeObject();
176
}
177

    
178

    
179
TEST(Tagging) {
180
  InitializeVM();
181
  CHECK(Smi::FromInt(42)->IsSmi());
182
  CHECK(Failure::RetryAfterGC(12, NEW_SPACE)->IsFailure());
183
  CHECK_EQ(12, Failure::RetryAfterGC(12, NEW_SPACE)->requested());
184
  CHECK_EQ(NEW_SPACE, Failure::RetryAfterGC(12, NEW_SPACE)->allocation_space());
185
  CHECK_EQ(OLD_POINTER_SPACE,
186
           Failure::RetryAfterGC(12, OLD_POINTER_SPACE)->allocation_space());
187
  CHECK(Failure::Exception()->IsFailure());
188
  CHECK(Smi::FromInt(Smi::kMinValue)->IsSmi());
189
  CHECK(Smi::FromInt(Smi::kMaxValue)->IsSmi());
190
}
191

    
192

    
193
TEST(GarbageCollection) {
194
  InitializeVM();
195

    
196
  v8::HandleScope sc;
197
  // check GC when heap is empty
198
  int free_bytes = Heap::MaxHeapObjectSize();
199
  CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));
200

    
201
  // allocate a function and keep it in global object's property
202
  String* func_name  = String::cast(Heap::LookupAsciiSymbol("theFunction"));
203
  SharedFunctionInfo* function_share =
204
    SharedFunctionInfo::cast(Heap::AllocateSharedFunctionInfo(func_name));
205
  JSFunction* function =
206
      JSFunction::cast(Heap::AllocateFunction(*Top::function_map(),
207
                                              function_share,
208
                                              Heap::undefined_value()));
209
  Map* initial_map =
210
      Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize));
211
  function->set_initial_map(initial_map);
212
  Top::context()->global()->SetProperty(func_name, function, NONE);
213

    
214
  // allocate an object, but it is unrooted
215
  String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
216
  String* prop_namex = String::cast(Heap::LookupAsciiSymbol("theSlotx"));
217
  JSObject* obj = JSObject::cast(Heap::AllocateJSObject(function));
218
  obj->SetProperty(prop_name, Smi::FromInt(23), NONE);
219
  obj->SetProperty(prop_namex, Smi::FromInt(24), NONE);
220

    
221
  CHECK_EQ(Smi::FromInt(23), obj->GetProperty(prop_name));
222
  CHECK_EQ(Smi::FromInt(24), obj->GetProperty(prop_namex));
223

    
224
  CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));
225

    
226
  // function should be alive, func_name might be invalid after GC
227
  func_name  = String::cast(Heap::LookupAsciiSymbol("theFunction"));
228
  CHECK(Top::context()->global()->HasLocalProperty(func_name));
229
  // check function is retained
230
  Object* func_value = Top::context()->global()->GetProperty(func_name);
231
  CHECK(func_value->IsJSFunction());
232
  // old function pointer may not be valid
233
  function = JSFunction::cast(func_value);
234

    
235
  // allocate another object, make it reachable from global
236
  obj = JSObject::cast(Heap::AllocateJSObject(function));
237
  String* obj_name = String::cast(Heap::LookupAsciiSymbol("theObject"));
238
  Top::context()->global()->SetProperty(obj_name, obj, NONE);
239
  // set property
240
  prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
241
  obj->SetProperty(prop_name, Smi::FromInt(23), NONE);
242

    
243
  // after gc, it should survive
244
  CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));
245

    
246
  obj_name = String::cast(Heap::LookupAsciiSymbol("theObject"));
247
  CHECK(Top::context()->global()->HasLocalProperty(obj_name));
248
  CHECK(Top::context()->global()->GetProperty(obj_name)->IsJSObject());
249
  obj = JSObject::cast(Top::context()->global()->GetProperty(obj_name));
250
  prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
251
  CHECK_EQ(Smi::FromInt(23), obj->GetProperty(prop_name));
252
}
253

    
254

    
255
static void VerifyStringAllocation(const char* string) {
256
  String* s = String::cast(Heap::AllocateStringFromUtf8(CStrVector(string)));
257
  CHECK_EQ(static_cast<int>(strlen(string)), s->length());
258
  for (int index = 0; index < s->length(); index++) {
259
    CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(index));  }
260
}
261

    
262

    
263
TEST(String) {
264
  InitializeVM();
265

    
266
  VerifyStringAllocation("a");
267
  VerifyStringAllocation("ab");
268
  VerifyStringAllocation("abc");
269
  VerifyStringAllocation("abcd");
270
  VerifyStringAllocation("fiskerdrengen er paa havet");
271
}
272

    
273

    
274
TEST(LocalHandles) {
275
  InitializeVM();
276

    
277
  v8::HandleScope scope;
278
  const char* name = "Kasper the spunky";
279
  Handle<String> string = Factory::NewStringFromAscii(CStrVector(name));
280
  CHECK_EQ(static_cast<int>(strlen(name)), string->length());
281
}
282

    
283

    
284
TEST(GlobalHandles) {
285
  InitializeVM();
286

    
287
  Object* i = Heap::AllocateStringFromAscii(CStrVector("fisk"));
288
  Object* u = Heap::AllocateHeapNumber(1.12344);
289

    
290
  Handle<Object> h1 = GlobalHandles::Create(i);
291
  Handle<Object> h2 = GlobalHandles::Create(u);
292
  Handle<Object> h3 = GlobalHandles::Create(i);
293
  Handle<Object> h4 = GlobalHandles::Create(u);
294

    
295
  // after gc, it should survive
296
  CHECK(Heap::CollectGarbage(0, NEW_SPACE));
297

    
298
  CHECK((*h1)->IsString());
299
  CHECK((*h2)->IsHeapNumber());
300
  CHECK((*h3)->IsString());
301
  CHECK((*h4)->IsHeapNumber());
302

    
303
  CHECK_EQ(*h3, *h1);
304
  GlobalHandles::Destroy(h1.location());
305
  GlobalHandles::Destroy(h3.location());
306

    
307
  CHECK_EQ(*h4, *h2);
308
  GlobalHandles::Destroy(h2.location());
309
  GlobalHandles::Destroy(h4.location());
310
}
311

    
312

    
313
static bool WeakPointerCleared = false;
314

    
315
static void TestWeakGlobalHandleCallback(v8::Persistent<v8::Value> handle,
316
                                         void* id) {
317
  USE(handle);
318
  if (1234 == reinterpret_cast<int>(id)) WeakPointerCleared = true;
319
}
320

    
321

    
322
TEST(WeakGlobalHandlesScavenge) {
323
  InitializeVM();
324

    
325
  WeakPointerCleared = false;
326

    
327
  Object* i = Heap::AllocateStringFromAscii(CStrVector("fisk"));
328
  Object* u = Heap::AllocateHeapNumber(1.12344);
329

    
330
  Handle<Object> h1 = GlobalHandles::Create(i);
331
  Handle<Object> h2 = GlobalHandles::Create(u);
332

    
333
  GlobalHandles::MakeWeak(h2.location(),
334
                          reinterpret_cast<void*>(1234),
335
                          &TestWeakGlobalHandleCallback);
336

    
337
  // Scavenge treats weak pointers as normal roots.
338
  Heap::PerformScavenge();
339

    
340
  CHECK((*h1)->IsString());
341
  CHECK((*h2)->IsHeapNumber());
342

    
343
  CHECK(!WeakPointerCleared);
344
  CHECK(!GlobalHandles::IsNearDeath(h2.location()));
345
  CHECK(!GlobalHandles::IsNearDeath(h1.location()));
346

    
347
  GlobalHandles::Destroy(h1.location());
348
  GlobalHandles::Destroy(h2.location());
349
}
350

    
351

    
352
TEST(WeakGlobalHandlesMark) {
353
  InitializeVM();
354

    
355
  WeakPointerCleared = false;
356

    
357
  Object* i = Heap::AllocateStringFromAscii(CStrVector("fisk"));
358
  Object* u = Heap::AllocateHeapNumber(1.12344);
359

    
360
  Handle<Object> h1 = GlobalHandles::Create(i);
361
  Handle<Object> h2 = GlobalHandles::Create(u);
362

    
363
  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
364
  CHECK(Heap::CollectGarbage(0, NEW_SPACE));
365
  // Make sure the object is promoted.
366

    
367
  GlobalHandles::MakeWeak(h2.location(),
368
                          reinterpret_cast<void*>(1234),
369
                          &TestWeakGlobalHandleCallback);
370
  CHECK(!GlobalHandles::IsNearDeath(h1.location()));
371
  CHECK(!GlobalHandles::IsNearDeath(h2.location()));
372

    
373
  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
374

    
375
  CHECK((*h1)->IsString());
376

    
377
  CHECK(WeakPointerCleared);
378
  CHECK(!GlobalHandles::IsNearDeath(h1.location()));
379
  CHECK(GlobalHandles::IsNearDeath(h2.location()));
380

    
381
  GlobalHandles::Destroy(h1.location());
382
  GlobalHandles::Destroy(h2.location());
383
}
384

    
385
static void TestDeleteWeakGlobalHandleCallback(
386
    v8::Persistent<v8::Value> handle,
387
    void* id) {
388
  if (1234 == reinterpret_cast<int>(id)) WeakPointerCleared = true;
389
  handle.Dispose();
390
}
391

    
392
TEST(DeleteWeakGlobalHandle) {
393
  InitializeVM();
394

    
395
  WeakPointerCleared = false;
396

    
397
  Object* i = Heap::AllocateStringFromAscii(CStrVector("fisk"));
398
  Handle<Object> h = GlobalHandles::Create(i);
399

    
400
  GlobalHandles::MakeWeak(h.location(),
401
                          reinterpret_cast<void*>(1234),
402
                          &TestDeleteWeakGlobalHandleCallback);
403

    
404
  // Scanvenge does not recognize weak reference.
405
  Heap::PerformScavenge();
406

    
407
  CHECK(!WeakPointerCleared);
408

    
409
  // Mark-compact treats weak reference properly.
410
  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
411

    
412
  CHECK(WeakPointerCleared);
413
}
414

    
415
static const char* not_so_random_string_table[] = {
416
  "abstract",
417
  "boolean",
418
  "break",
419
  "byte",
420
  "case",
421
  "catch",
422
  "char",
423
  "class",
424
  "const",
425
  "continue",
426
  "debugger",
427
  "default",
428
  "delete",
429
  "do",
430
  "double",
431
  "else",
432
  "enum",
433
  "export",
434
  "extends",
435
  "false",
436
  "final",
437
  "finally",
438
  "float",
439
  "for",
440
  "function",
441
  "goto",
442
  "if",
443
  "implements",
444
  "import",
445
  "in",
446
  "instanceof",
447
  "int",
448
  "interface",
449
  "long",
450
  "native",
451
  "new",
452
  "null",
453
  "package",
454
  "private",
455
  "protected",
456
  "public",
457
  "return",
458
  "short",
459
  "static",
460
  "super",
461
  "switch",
462
  "synchronized",
463
  "this",
464
  "throw",
465
  "throws",
466
  "transient",
467
  "true",
468
  "try",
469
  "typeof",
470
  "var",
471
  "void",
472
  "volatile",
473
  "while",
474
  "with",
475
  0
476
};
477

    
478

    
479
static void CheckSymbols(const char** strings) {
480
  for (const char* string = *strings; *strings != 0; string = *strings++) {
481
    Object* a = Heap::LookupAsciiSymbol(string);
482
    CHECK(a->IsSymbol());
483
    Object* b = Heap::LookupAsciiSymbol(string);
484
    CHECK_EQ(b, a);
485
    CHECK(String::cast(b)->IsEqualTo(CStrVector(string)));
486
  }
487
}
488

    
489

    
490
TEST(SymbolTable) {
491
  InitializeVM();
492

    
493
  CheckSymbols(not_so_random_string_table);
494
  CheckSymbols(not_so_random_string_table);
495
}
496

    
497

    
498
TEST(FunctionAllocation) {
499
  InitializeVM();
500

    
501
  v8::HandleScope sc;
502
  String* name  = String::cast(Heap::LookupAsciiSymbol("theFunction"));
503
  SharedFunctionInfo* function_share =
504
    SharedFunctionInfo::cast(Heap::AllocateSharedFunctionInfo(name));
505
  JSFunction* function =
506
    JSFunction::cast(Heap::AllocateFunction(*Top::function_map(),
507
                                            function_share,
508
                                            Heap::undefined_value()));
509
  Map* initial_map =
510
      Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize));
511
  function->set_initial_map(initial_map);
512

    
513
  String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
514
  JSObject* obj = JSObject::cast(Heap::AllocateJSObject(function));
515
  obj->SetProperty(prop_name, Smi::FromInt(23), NONE);
516
  CHECK_EQ(Smi::FromInt(23), obj->GetProperty(prop_name));
517
  // Check that we can add properties to function objects.
518
  function->SetProperty(prop_name, Smi::FromInt(24), NONE);
519
  CHECK_EQ(Smi::FromInt(24), function->GetProperty(prop_name));
520
}
521

    
522

    
523
TEST(ObjectProperties) {
524
  InitializeVM();
525

    
526
  v8::HandleScope sc;
527
  JSFunction* constructor =
528
      JSFunction::cast(
529
          Top::context()->global()->GetProperty(String::cast(
530
                                                    Heap::Object_symbol())));
531
  JSObject* obj = JSObject::cast(Heap::AllocateJSObject(constructor));
532
  String* first = String::cast(Heap::LookupAsciiSymbol("first"));
533
  String* second = String::cast(Heap::LookupAsciiSymbol("second"));
534

    
535
  // check for empty
536
  CHECK(!obj->HasLocalProperty(first));
537

    
538
  // add first
539
  obj->SetProperty(first, Smi::FromInt(1), NONE);
540
  CHECK(obj->HasLocalProperty(first));
541

    
542
  // delete first
543
  CHECK(obj->DeleteProperty(first));
544
  CHECK(!obj->HasLocalProperty(first));
545

    
546
  // add first and then second
547
  obj->SetProperty(first, Smi::FromInt(1), NONE);
548
  obj->SetProperty(second, Smi::FromInt(2), NONE);
549
  CHECK(obj->HasLocalProperty(first));
550
  CHECK(obj->HasLocalProperty(second));
551

    
552
  // delete first and then second
553
  CHECK(obj->DeleteProperty(first));
554
  CHECK(obj->HasLocalProperty(second));
555
  CHECK(obj->DeleteProperty(second));
556
  CHECK(!obj->HasLocalProperty(first));
557
  CHECK(!obj->HasLocalProperty(second));
558

    
559
  // add first and then second
560
  obj->SetProperty(first, Smi::FromInt(1), NONE);
561
  obj->SetProperty(second, Smi::FromInt(2), NONE);
562
  CHECK(obj->HasLocalProperty(first));
563
  CHECK(obj->HasLocalProperty(second));
564

    
565
  // delete second and then first
566
  CHECK(obj->DeleteProperty(second));
567
  CHECK(obj->HasLocalProperty(first));
568
  CHECK(obj->DeleteProperty(first));
569
  CHECK(!obj->HasLocalProperty(first));
570
  CHECK(!obj->HasLocalProperty(second));
571

    
572
  // check string and symbol match
573
  static const char* string1 = "fisk";
574
  String* s1 =
575
      String::cast(Heap::AllocateStringFromAscii(CStrVector(string1)));
576
  obj->SetProperty(s1, Smi::FromInt(1), NONE);
577
  CHECK(obj->HasLocalProperty(String::cast(Heap::LookupAsciiSymbol(string1))));
578

    
579
  // check symbol and string match
580
  static const char* string2 = "fugl";
581
  String* s2 = String::cast(Heap::LookupAsciiSymbol(string2));
582
  obj->SetProperty(s2, Smi::FromInt(1), NONE);
583
  CHECK(obj->HasLocalProperty(
584
            String::cast(Heap::AllocateStringFromAscii(CStrVector(string2)))));
585
}
586

    
587

    
588
TEST(JSObjectMaps) {
589
  InitializeVM();
590

    
591
  v8::HandleScope sc;
592
  String* name  = String::cast(Heap::LookupAsciiSymbol("theFunction"));
593
  SharedFunctionInfo* function_share =
594
    SharedFunctionInfo::cast(Heap::AllocateSharedFunctionInfo(name));
595
  JSFunction* function =
596
    JSFunction::cast(Heap::AllocateFunction(*Top::function_map(),
597
                                            function_share,
598
                                            Heap::undefined_value()));
599
  Map* initial_map =
600
      Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize));
601
  function->set_initial_map(initial_map);
602
  String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
603
  JSObject* obj = JSObject::cast(Heap::AllocateJSObject(function));
604

    
605
  // Set a propery
606
  obj->SetProperty(prop_name, Smi::FromInt(23), NONE);
607
  CHECK_EQ(Smi::FromInt(23), obj->GetProperty(prop_name));
608

    
609
  // Check the map has changed
610
  CHECK(initial_map != obj->map());
611
}
612

    
613

    
614
TEST(JSArray) {
615
  InitializeVM();
616

    
617
  v8::HandleScope sc;
618
  String* name = String::cast(Heap::LookupAsciiSymbol("Array"));
619
  JSFunction* function =
620
      JSFunction::cast(Top::context()->global()->GetProperty(name));
621

    
622
  // Allocate the object.
623
  JSArray* array = JSArray::cast(Heap::AllocateJSObject(function));
624
  array->Initialize(0);
625

    
626
  // Set array length to 0.
627
  array->SetElementsLength(Smi::FromInt(0));
628
  CHECK_EQ(Smi::FromInt(0), array->length());
629
  CHECK(array->HasFastElements());  // Must be in fast mode.
630

    
631
  // array[length] = name.
632
  array->SetElement(0, name);
633
  CHECK_EQ(Smi::FromInt(1), array->length());
634
  CHECK_EQ(array->GetElement(0), name);
635

    
636
  // Set array length with larger than smi value.
637
  Object* length = Heap::NumberFromInt32(Smi::kMaxValue + 1);
638
  array->SetElementsLength(length);
639

    
640
  uint32_t int_length = 0;
641
  CHECK(Array::IndexFromObject(length, &int_length));
642
  CHECK_EQ(length, array->length());
643
  CHECK(!array->HasFastElements());  // Must be in slow mode.
644

    
645
  // array[length] = name.
646
  array->SetElement(int_length, name);
647
  uint32_t new_int_length = 0;
648
  CHECK(Array::IndexFromObject(array->length(), &new_int_length));
649
  CHECK_EQ(static_cast<double>(int_length), new_int_length - 1);
650
  CHECK_EQ(array->GetElement(int_length), name);
651
  CHECK_EQ(array->GetElement(0), name);
652
}
653

    
654

    
655
TEST(JSObjectCopy) {
656
  InitializeVM();
657

    
658
  v8::HandleScope sc;
659
  String* name = String::cast(Heap::Object_symbol());
660
  JSFunction* constructor =
661
      JSFunction::cast(Top::context()->global()->GetProperty(name));
662
  JSObject* obj = JSObject::cast(Heap::AllocateJSObject(constructor));
663
  String* first = String::cast(Heap::LookupAsciiSymbol("first"));
664
  String* second = String::cast(Heap::LookupAsciiSymbol("second"));
665

    
666
  obj->SetProperty(first, Smi::FromInt(1), NONE);
667
  obj->SetProperty(second, Smi::FromInt(2), NONE);
668

    
669
  obj->SetElement(0, first);
670
  obj->SetElement(1, second);
671

    
672
  // Make the clone.
673
  JSObject* clone = JSObject::cast(Heap::CopyJSObject(obj));
674
  CHECK(clone != obj);
675

    
676
  CHECK_EQ(obj->GetElement(0), clone->GetElement(0));
677
  CHECK_EQ(obj->GetElement(1), clone->GetElement(1));
678

    
679
  CHECK_EQ(obj->GetProperty(first), clone->GetProperty(first));
680
  CHECK_EQ(obj->GetProperty(second), clone->GetProperty(second));
681

    
682
  // Flip the values.
683
  clone->SetProperty(first, Smi::FromInt(2), NONE);
684
  clone->SetProperty(second, Smi::FromInt(1), NONE);
685

    
686
  clone->SetElement(0, second);
687
  clone->SetElement(1, first);
688

    
689
  CHECK_EQ(obj->GetElement(1), clone->GetElement(0));
690
  CHECK_EQ(obj->GetElement(0), clone->GetElement(1));
691

    
692
  CHECK_EQ(obj->GetProperty(second), clone->GetProperty(first));
693
  CHECK_EQ(obj->GetProperty(first), clone->GetProperty(second));
694
}
695

    
696

    
697
TEST(StringAllocation) {
698
  InitializeVM();
699

    
700

    
701
  const unsigned char chars[] = { 0xe5, 0xa4, 0xa7 };
702
  for (int length = 0; length < 100; length++) {
703
    v8::HandleScope scope;
704
    char* non_ascii = NewArray<char>(3 * length + 1);
705
    char* ascii = NewArray<char>(length + 1);
706
    non_ascii[3 * length] = 0;
707
    ascii[length] = 0;
708
    for (int i = 0; i < length; i++) {
709
      ascii[i] = 'a';
710
      non_ascii[3 * i] = chars[0];
711
      non_ascii[3 * i + 1] = chars[1];
712
      non_ascii[3 * i + 2] = chars[2];
713
    }
714
    Handle<String> non_ascii_sym =
715
        Factory::LookupSymbol(Vector<const char>(non_ascii, 3 * length));
716
    CHECK_EQ(length, non_ascii_sym->length());
717
    Handle<String> ascii_sym =
718
        Factory::LookupSymbol(Vector<const char>(ascii, length));
719
    CHECK_EQ(length, ascii_sym->length());
720
    Handle<String> non_ascii_str =
721
        Factory::NewStringFromUtf8(Vector<const char>(non_ascii, 3 * length));
722
    non_ascii_str->Hash();
723
    CHECK_EQ(length, non_ascii_str->length());
724
    Handle<String> ascii_str =
725
        Factory::NewStringFromUtf8(Vector<const char>(ascii, length));
726
    ascii_str->Hash();
727
    CHECK_EQ(length, ascii_str->length());
728
    DeleteArray(non_ascii);
729
    DeleteArray(ascii);
730
  }
731
}
732

    
733

    
734
static int ObjectsFoundInHeap(Handle<Object> objs[], int size) {
735
  // Count the number of objects found in the heap.
736
  int found_count = 0;
737
  HeapIterator iterator;
738
  while (iterator.has_next()) {
739
    HeapObject* obj = iterator.next();
740
    CHECK(obj != NULL);
741
    for (int i = 0; i < size; i++) {
742
      if (*objs[i] == obj) {
743
        found_count++;
744
      }
745
    }
746
  }
747
  CHECK(!iterator.has_next());
748
  return found_count;
749
}
750

    
751

    
752
TEST(Iteration) {
753
  InitializeVM();
754
  v8::HandleScope scope;
755

    
756
  // Array of objects to scan haep for.
757
  const int objs_count = 6;
758
  Handle<Object> objs[objs_count];
759
  int next_objs_index = 0;
760

    
761
  // Allocate a JS array to OLD_POINTER_SPACE and NEW_SPACE
762
  objs[next_objs_index++] = Factory::NewJSArray(10);
763
  objs[next_objs_index++] = Factory::NewJSArray(10, TENURED);
764

    
765
  // Allocate a small string to OLD_DATA_SPACE and NEW_SPACE
766
  objs[next_objs_index++] =
767
      Factory::NewStringFromAscii(CStrVector("abcdefghij"));
768
  objs[next_objs_index++] =
769
      Factory::NewStringFromAscii(CStrVector("abcdefghij"), TENURED);
770

    
771
  // Allocate a large string (for large object space).
772
  int large_size = Heap::MaxHeapObjectSize() + 1;
773
  char* str = new char[large_size];
774
  for (int i = 0; i < large_size - 1; ++i) str[i] = 'a';
775
  str[large_size - 1] = '\0';
776
  objs[next_objs_index++] =
777
      Factory::NewStringFromAscii(CStrVector(str), TENURED);
778
  delete[] str;
779

    
780
  // Add a Map object to look for.
781
  objs[next_objs_index++] = Handle<Map>(HeapObject::cast(*objs[0])->map());
782

    
783
  CHECK_EQ(objs_count, next_objs_index);
784
  CHECK_EQ(objs_count, ObjectsFoundInHeap(objs, objs_count));
785
}