13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdlib.h>
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "execution.h"
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "factory.h"
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "macro-assembler.h"
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "global-handles.h"
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "cctest.h"
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing namespace v8::internal;
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic v8::Persistent<v8::Context> env;
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void InitializeVM() {
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (env.IsEmpty()) env = v8::Context::New();
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope scope;
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env->Enter();
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void CheckMap(Map* map, int type, int instance_size) {
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(map->IsHeapObject());
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(HEAP->Contains(map));
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(HEAP->meta_map(), map->map());
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(type, map->instance_type());
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(instance_size, map->instance_size());
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(HeapMaps) {
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
3744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CheckMap(HEAP->meta_map(), MAP_TYPE, Map::kSize);
3844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CheckMap(HEAP->heap_number_map(), HEAP_NUMBER_TYPE, HeapNumber::kSize);
3944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CheckMap(HEAP->fixed_array_map(), FIXED_ARRAY_TYPE, kVariableSizeSentinel);
4044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CheckMap(HEAP->string_map(), STRING_TYPE, kVariableSizeSentinel);
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void CheckOddball(Object* obj, const char* string) {
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(obj->IsOddball());
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool exc;
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void CheckSmi(int value, const char* string) {
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool exc;
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* print_string =
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *Execution::ToString(Handle<Object>(Smi::FromInt(value)), &exc);
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void CheckNumber(double value, const char* string) {
6144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Object* obj = HEAP->NumberFromDouble(value)->ToObjectChecked();
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(obj->IsNumber());
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool exc;
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void CheckFindCodeObject() {
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test FindCodeObject
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ assm.
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Assembler assm(Isolate::Current(), NULL, 0);
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ nop();  // supported on all architectures
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CodeDesc desc;
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assm.GetCode(&desc);
7944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Object* code = HEAP->CreateCode(
805913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      desc,
815913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      Code::ComputeFlags(Code::STUB),
8244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(code->IsCode());
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HeapObject* obj = HeapObject::cast(code);
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address obj_addr = obj->address();
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < obj->Size(); i += kPointerSize) {
8944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Object* found = HEAP->FindCodeObject(obj_addr + i);
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(code, found);
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Object* copy = HEAP->CreateCode(
945913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      desc,
955913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      Code::ComputeFlags(Code::STUB),
9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(copy->IsCode());
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HeapObject* obj_copy = HeapObject::cast(copy);
9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Object* not_right = HEAP->FindCodeObject(obj_copy->address() +
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           obj_copy->Size() / 2);
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(not_right != code);
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(HeapObjects) {
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope sc;
10944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Object* value = HEAP->NumberFromDouble(1.000123)->ToObjectChecked();
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsHeapNumber());
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsNumber());
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1.000123, value->Number());
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  value = HEAP->NumberFromDouble(1.0)->ToObjectChecked();
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsSmi());
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsNumber());
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1.0, value->Number());
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  value = HEAP->NumberFromInt32(1024)->ToObjectChecked();
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsSmi());
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsNumber());
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1024.0, value->Number());
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  value = HEAP->NumberFromInt32(Smi::kMinValue)->ToObjectChecked();
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsSmi());
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsNumber());
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(Smi::kMinValue, Smi::cast(value)->value());
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  value = HEAP->NumberFromInt32(Smi::kMaxValue)->ToObjectChecked();
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsSmi());
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsNumber());
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value());
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#ifndef V8_TARGET_ARCH_X64
1353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // TODO(lrn): We need a NumberFromIntptr function in order to test this.
13644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  value = HEAP->NumberFromInt32(Smi::kMinValue - 1)->ToObjectChecked();
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsHeapNumber());
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsNumber());
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number());
1403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#endif
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MaybeObject* maybe_value =
14344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HEAP->NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1);
1445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  value = maybe_value->ToObjectChecked();
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsHeapNumber());
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(value->IsNumber());
1473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(static_cast<double>(static_cast<uint32_t>(Smi::kMaxValue) + 1),
1483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block           value->Number());
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // nan oddball checks
15144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(HEAP->nan_value()->IsNumber());
15244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(isnan(HEAP->nan_value()->Number()));
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> s = FACTORY->NewStringFromAscii(CStrVector("fisk hest "));
1556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(s->IsString());
1566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(10, s->length());
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  String* object_symbol = String::cast(HEAP->Object_symbol());
15944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(
16044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Isolate::Current()->context()->global()->HasLocalProperty(object_symbol));
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check ToString for oddballs
16344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CheckOddball(HEAP->true_value(), "true");
16444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CheckOddball(HEAP->false_value(), "false");
16544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CheckOddball(HEAP->null_value(), "null");
16644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CheckOddball(HEAP->undefined_value(), "undefined");
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check ToString for Smis
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckSmi(0, "0");
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckSmi(42, "42");
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckSmi(-42, "-42");
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check ToString for Numbers
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckNumber(1.1, "1.1");
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckFindCodeObject();
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(Tagging) {
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int request = 24;
1837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(request, static_cast<int>(OBJECT_POINTER_ALIGN(request)));
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(Smi::FromInt(42)->IsSmi());
185f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK(Failure::RetryAfterGC(NEW_SPACE)->IsFailure());
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(NEW_SPACE,
187f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch           Failure::RetryAfterGC(NEW_SPACE)->allocation_space());
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(OLD_POINTER_SPACE,
189f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch           Failure::RetryAfterGC(OLD_POINTER_SPACE)->allocation_space());
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(Failure::Exception()->IsFailure());
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(Smi::FromInt(Smi::kMinValue)->IsSmi());
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(Smi::FromInt(Smi::kMaxValue)->IsSmi());
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(GarbageCollection) {
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope sc;
2006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check GC.
20144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(NEW_SPACE);
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction");
20444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot");
20544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> prop_namex = FACTORY->LookupAsciiSymbol("theSlotx");
20644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> obj_name = FACTORY->LookupAsciiSymbol("theObject");
2076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  {
2096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    v8::HandleScope inner_scope;
2106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Allocate a function and keep it in global object's property.
2116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSFunction> function =
21244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        FACTORY->NewFunction(name, FACTORY->undefined_value());
2136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Map> initial_map =
21444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
2156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    function->set_initial_map(*initial_map);
21644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Isolate::Current()->context()->global()->SetProperty(
217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        *name, *function, NONE, kNonStrictMode)->ToObjectChecked();
2186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Allocate an object.  Unrooted after leaving the scope.
21944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<JSObject> obj = FACTORY->NewJSObject(function);
220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    obj->SetProperty(
221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    obj->SetProperty(
223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        *prop_namex, Smi::FromInt(24), NONE, kNonStrictMode)->ToObjectChecked();
2246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
2266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex));
2276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(NEW_SPACE);
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Function should be alive.
23244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(Isolate::Current()->context()->global()->HasLocalProperty(*name));
2336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check function is retained.
23444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Object* func_value = Isolate::Current()->context()->global()->
23544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      GetProperty(*name)->ToObjectChecked();
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(func_value->IsJSFunction());
2376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSFunction> function(JSFunction::cast(func_value));
2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  {
2406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope inner_scope;
2416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Allocate another object, make it reachable from global.
24244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<JSObject> obj = FACTORY->NewJSObject(function);
24344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Isolate::Current()->context()->global()->SetProperty(
244e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        *obj_name, *obj, NONE, kNonStrictMode)->ToObjectChecked();
245e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    obj->SetProperty(
246e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
2476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // After gc, it should survive.
25044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(NEW_SPACE);
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(Isolate::Current()->context()->global()->HasLocalProperty(*obj_name));
25344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(Isolate::Current()->context()->global()->
25444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        GetProperty(*obj_name)->ToObjectChecked()->IsJSObject());
25544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Object* obj = Isolate::Current()->context()->global()->
25644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      GetProperty(*obj_name)->ToObjectChecked();
2575913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  JSObject* js_obj = JSObject::cast(obj);
2585913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  CHECK_EQ(Smi::FromInt(23), js_obj->GetProperty(*prop_name));
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void VerifyStringAllocation(const char* string) {
2636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::HandleScope scope;
26444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> s = FACTORY->NewStringFromUtf8(CStrVector(string));
265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(StrLength(string), s->length());
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int index = 0; index < s->length(); index++) {
2676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(index));
2686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(String) {
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  VerifyStringAllocation("a");
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  VerifyStringAllocation("ab");
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  VerifyStringAllocation("abc");
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  VerifyStringAllocation("abcd");
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  VerifyStringAllocation("fiskerdrengen er paa havet");
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(LocalHandles) {
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope scope;
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* name = "Kasper the spunky";
28844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> string = FACTORY->NewStringFromAscii(CStrVector(name));
289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(StrLength(name), string->length());
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(GlobalHandles) {
294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  InitializeVM();
29569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  GlobalHandles* global_handles = Isolate::Current()->global_handles();
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Object> h1;
2986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Object> h2;
2996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Object> h3;
3006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Object> h4;
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  {
3036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
3046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk"));
30644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Object> u = FACTORY->NewNumber(1.12344);
3076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    h1 = global_handles->Create(*i);
30944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    h2 = global_handles->Create(*u);
31044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    h3 = global_handles->Create(*i);
31144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    h4 = global_handles->Create(*u);
3126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // after gc, it should survive
31544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(NEW_SPACE);
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK((*h1)->IsString());
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK((*h2)->IsHeapNumber());
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK((*h3)->IsString());
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK((*h4)->IsHeapNumber());
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(*h3, *h1);
32344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->Destroy(h1.location());
32444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->Destroy(h3.location());
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(*h4, *h2);
32744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->Destroy(h2.location());
32844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->Destroy(h4.location());
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool WeakPointerCleared = false;
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void TestWeakGlobalHandleCallback(v8::Persistent<v8::Value> handle,
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                         void* id) {
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (1234 == reinterpret_cast<intptr_t>(id)) WeakPointerCleared = true;
33750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  handle.Dispose();
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(WeakGlobalHandlesScavenge) {
342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  InitializeVM();
34369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  GlobalHandles* global_handles = Isolate::Current()->global_handles();
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  WeakPointerCleared = false;
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Object> h1;
3486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Object> h2;
3496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  {
3516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk"));
35444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Object> u = FACTORY->NewNumber(1.12344);
3556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
35644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    h1 = global_handles->Create(*i);
35744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    h2 = global_handles->Create(*u);
3586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
36044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->MakeWeak(h2.location(),
36144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           reinterpret_cast<void*>(1234),
36244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           &TestWeakGlobalHandleCallback);
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scavenge treats weak pointers as normal roots.
36544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->PerformScavenge();
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK((*h1)->IsString());
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK((*h2)->IsHeapNumber());
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!WeakPointerCleared);
37144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(!global_handles->IsNearDeath(h2.location()));
37244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(!global_handles->IsNearDeath(h1.location()));
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->Destroy(h1.location());
37544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->Destroy(h2.location());
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(WeakGlobalHandlesMark) {
380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  InitializeVM();
38169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  GlobalHandles* global_handles = Isolate::Current()->global_handles();
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  WeakPointerCleared = false;
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Object> h1;
3866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Object> h2;
3876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  {
3896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk"));
39244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Object> u = FACTORY->NewNumber(1.12344);
3936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
39444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    h1 = global_handles->Create(*i);
39544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    h2 = global_handles->Create(*u);
3966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(OLD_POINTER_SPACE);
39944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(NEW_SPACE);
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the object is promoted.
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->MakeWeak(h2.location(),
40344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           reinterpret_cast<void*>(1234),
40444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           &TestWeakGlobalHandleCallback);
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!GlobalHandles::IsNearDeath(h1.location()));
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!GlobalHandles::IsNearDeath(h2.location()));
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(OLD_POINTER_SPACE);
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK((*h1)->IsString());
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(WeakPointerCleared);
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!GlobalHandles::IsNearDeath(h1.location()));
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
41544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->Destroy(h1.location());
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DeleteWeakGlobalHandle) {
419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  InitializeVM();
42069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  GlobalHandles* global_handles = Isolate::Current()->global_handles();
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  WeakPointerCleared = false;
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Object> h;
4256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  {
4276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
4286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
42944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk"));
43044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    h = global_handles->Create(*i);
4316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
43344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->MakeWeak(h.location(),
43444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           reinterpret_cast<void*>(1234),
43544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           &TestWeakGlobalHandleCallback);
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scanvenge does not recognize weak reference.
43844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->PerformScavenge();
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!WeakPointerCleared);
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mark-compact treats weak reference properly.
44344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectGarbage(OLD_POINTER_SPACE);
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(WeakPointerCleared);
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* not_so_random_string_table[] = {
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "abstract",
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "boolean",
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "break",
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "byte",
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "case",
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "catch",
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "char",
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "class",
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "const",
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "continue",
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "debugger",
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "default",
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "delete",
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "do",
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "double",
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "else",
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "enum",
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "export",
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "extends",
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "false",
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "final",
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "finally",
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "float",
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "for",
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "function",
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "goto",
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "if",
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "implements",
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "import",
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "in",
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "instanceof",
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "int",
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "interface",
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "long",
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "native",
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "new",
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "null",
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "package",
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "private",
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "protected",
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "public",
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "return",
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "short",
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "static",
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "super",
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "switch",
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "synchronized",
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "this",
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "throw",
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "throws",
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "transient",
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "true",
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "try",
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "typeof",
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "var",
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "void",
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "volatile",
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "while",
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "with",
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  0
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void CheckSymbols(const char** strings) {
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (const char* string = *strings; *strings != 0; string = *strings++) {
5145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    Object* a;
51544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MaybeObject* maybe_a = HEAP->LookupAsciiSymbol(string);
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // LookupAsciiSymbol may return a failure if a GC is needed.
5175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (!maybe_a->ToObject(&a)) continue;
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(a->IsSymbol());
5195913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    Object* b;
52044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MaybeObject* maybe_b = HEAP->LookupAsciiSymbol(string);
5215913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (!maybe_b->ToObject(&b)) continue;
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(b, a);
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(String::cast(b)->IsEqualTo(CStrVector(string)));
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(SymbolTable) {
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckSymbols(not_so_random_string_table);
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckSymbols(not_so_random_string_table);
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(FunctionAllocation) {
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope sc;
54044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction");
5416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSFunction> function =
54244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      FACTORY->NewFunction(name, FACTORY->undefined_value());
5436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Map> initial_map =
54444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
5456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  function->set_initial_map(*initial_map);
5466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
54744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot");
54844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<JSObject> obj = FACTORY->NewJSObject(function);
549e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  obj->SetProperty(
550e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
5516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that we can add properties to function objects.
553e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  function->SetProperty(
554e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      *prop_name, Smi::FromInt(24), NONE, kNonStrictMode)->ToObjectChecked();
5556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(Smi::FromInt(24), function->GetProperty(*prop_name));
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ObjectProperties) {
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope sc;
56344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  String* object_symbol = String::cast(HEAP->Object_symbol());
56444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Object* raw_object = Isolate::Current()->context()->global()->
56544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      GetProperty(object_symbol)->ToObjectChecked();
5665913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  JSFunction* object_function = JSFunction::cast(raw_object);
5676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSFunction> constructor(object_function);
56844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<JSObject> obj = FACTORY->NewJSObject(constructor);
56944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> first = FACTORY->LookupAsciiSymbol("first");
57044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> second = FACTORY->LookupAsciiSymbol("second");
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // check for empty
5736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(!obj->HasLocalProperty(*first));
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // add first
576e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  obj->SetProperty(
577e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
5786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(obj->HasLocalProperty(*first));
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // delete first
5816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION));
5826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(!obj->HasLocalProperty(*first));
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // add first and then second
585e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  obj->SetProperty(
586e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
587e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  obj->SetProperty(
588e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
5896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(obj->HasLocalProperty(*first));
5906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(obj->HasLocalProperty(*second));
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // delete first and then second
5936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION));
5946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(obj->HasLocalProperty(*second));
5956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(obj->DeleteProperty(*second, JSObject::NORMAL_DELETION));
5966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(!obj->HasLocalProperty(*first));
5976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(!obj->HasLocalProperty(*second));
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // add first and then second
600e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  obj->SetProperty(
601e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
602e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  obj->SetProperty(
603e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
6046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(obj->HasLocalProperty(*first));
6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(obj->HasLocalProperty(*second));
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // delete second and then first
6086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(obj->DeleteProperty(*second, JSObject::NORMAL_DELETION));
6096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(obj->HasLocalProperty(*first));
6106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION));
6116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(!obj->HasLocalProperty(*first));
6126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(!obj->HasLocalProperty(*second));
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // check string and symbol match
6153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const char* string1 = "fisk";
61644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> s1 = FACTORY->NewStringFromAscii(CStrVector(string1));
617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  obj->SetProperty(
618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      *s1, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
61944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> s1_symbol = FACTORY->LookupAsciiSymbol(string1);
6206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(obj->HasLocalProperty(*s1_symbol));
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // check symbol and string match
6233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const char* string2 = "fugl";
62444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> s2_symbol = FACTORY->LookupAsciiSymbol(string2);
625e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  obj->SetProperty(
626e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      *s2_symbol, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
62744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> s2 = FACTORY->NewStringFromAscii(CStrVector(string2));
6286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(obj->HasLocalProperty(*s2));
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(JSObjectMaps) {
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope sc;
63644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction");
6376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSFunction> function =
63844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      FACTORY->NewFunction(name, FACTORY->undefined_value());
6396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Map> initial_map =
64044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
6416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  function->set_initial_map(*initial_map);
6426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
64344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot");
64444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<JSObject> obj = FACTORY->NewJSObject(function);
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set a propery
647e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  obj->SetProperty(
648e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
6496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the map has changed
6526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(*initial_map != obj->map());
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(JSArray) {
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope sc;
66044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> name = FACTORY->LookupAsciiSymbol("Array");
66144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Object* raw_object = Isolate::Current()->context()->global()->
66244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      GetProperty(*name)->ToObjectChecked();
6636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSFunction> function = Handle<JSFunction>(
6645913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      JSFunction::cast(raw_object));
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate the object.
66744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<JSObject> object = FACTORY->NewJSObject(function);
6686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> array = Handle<JSArray>::cast(object);
66980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // We just initialized the VM, no heap allocation failure yet.
6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  array->Initialize(0)->ToObjectChecked();
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set array length to 0.
6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  array->SetElementsLength(Smi::FromInt(0))->ToObjectChecked();
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(Smi::FromInt(0), array->length());
6753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Must be in fast mode.
6763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(array->HasFastTypeElements());
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array[length] = name.
6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  array->SetElement(0, *name, NONE, kNonStrictMode)->ToObjectChecked();
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(Smi::FromInt(1), array->length());
6816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(array->GetElement(0), *name);
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Set array length with larger than smi value.
6846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Object> length =
68544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      FACTORY->NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1);
6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  array->SetElementsLength(*length)->ToObjectChecked();
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint32_t int_length = 0;
6897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK(length->ToArrayIndex(&int_length));
6906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(*length, array->length());
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(array->HasDictionaryElements());  // Must be in slow mode.
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array[length] = name.
6943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  array->SetElement(int_length, *name, NONE, kNonStrictMode)->ToObjectChecked();
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint32_t new_int_length = 0;
6967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK(array->length()->ToArrayIndex(&new_int_length));
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(static_cast<double>(int_length), new_int_length - 1);
6986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(array->GetElement(int_length), *name);
6996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(array->GetElement(0), *name);
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(JSObjectCopy) {
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope sc;
70744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  String* object_symbol = String::cast(HEAP->Object_symbol());
70844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Object* raw_object = Isolate::Current()->context()->global()->
70944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      GetProperty(object_symbol)->ToObjectChecked();
7105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  JSFunction* object_function = JSFunction::cast(raw_object);
7116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSFunction> constructor(object_function);
71244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<JSObject> obj = FACTORY->NewJSObject(constructor);
71344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> first = FACTORY->LookupAsciiSymbol("first");
71444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> second = FACTORY->LookupAsciiSymbol("second");
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
716e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  obj->SetProperty(
717e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
718e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  obj->SetProperty(
719e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  obj->SetElement(0, *first, NONE, kNonStrictMode)->ToObjectChecked();
7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  obj->SetElement(1, *second, NONE, kNonStrictMode)->ToObjectChecked();
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make the clone.
7256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSObject> clone = Copy(obj);
7266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(!clone.is_identical_to(obj));
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(obj->GetElement(0), clone->GetElement(0));
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(obj->GetElement(1), clone->GetElement(1));
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*first));
7326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*second));
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Flip the values.
735e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  clone->SetProperty(
736e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      *first, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
737e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  clone->SetProperty(
738e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      *second, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  clone->SetElement(0, *second, NONE, kNonStrictMode)->ToObjectChecked();
7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  clone->SetElement(1, *first, NONE, kNonStrictMode)->ToObjectChecked();
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(obj->GetElement(1), clone->GetElement(0));
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(obj->GetElement(0), clone->GetElement(1));
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*first));
7476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*second));
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(StringAllocation) {
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const unsigned char chars[] = { 0xe5, 0xa4, 0xa7 };
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int length = 0; length < 100; length++) {
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::HandleScope scope;
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char* non_ascii = NewArray<char>(3 * length + 1);
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char* ascii = NewArray<char>(length + 1);
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    non_ascii[3 * length] = 0;
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ascii[length] = 0;
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 0; i < length; i++) {
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ascii[i] = 'a';
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      non_ascii[3 * i] = chars[0];
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      non_ascii[3 * i + 1] = chars[1];
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      non_ascii[3 * i + 2] = chars[2];
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<String> non_ascii_sym =
76944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        FACTORY->LookupSymbol(Vector<const char>(non_ascii, 3 * length));
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(length, non_ascii_sym->length());
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<String> ascii_sym =
77244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        FACTORY->LookupSymbol(Vector<const char>(ascii, length));
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(length, ascii_sym->length());
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<String> non_ascii_str =
77544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        FACTORY->NewStringFromUtf8(Vector<const char>(non_ascii, 3 * length));
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    non_ascii_str->Hash();
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(length, non_ascii_str->length());
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<String> ascii_str =
77944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        FACTORY->NewStringFromUtf8(Vector<const char>(ascii, length));
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ascii_str->Hash();
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(length, ascii_str->length());
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    DeleteArray(non_ascii);
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    DeleteArray(ascii);
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int ObjectsFoundInHeap(Handle<Object> objs[], int size) {
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Count the number of objects found in the heap.
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int found_count = 0;
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HeapIterator iterator;
792d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 0; i < size; i++) {
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (*objs[i] == obj) {
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        found_count++;
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return found_count;
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(Iteration) {
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InitializeVM();
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope scope;
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Array of objects to scan haep for.
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int objs_count = 6;
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> objs[objs_count];
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int next_objs_index = 0;
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate a JS array to OLD_POINTER_SPACE and NEW_SPACE
81344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  objs[next_objs_index++] = FACTORY->NewJSArray(10);
8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  objs[next_objs_index++] = FACTORY->NewJSArray(10, FAST_ELEMENTS, TENURED);
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate a small string to OLD_DATA_SPACE and NEW_SPACE
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  objs[next_objs_index++] =
81844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      FACTORY->NewStringFromAscii(CStrVector("abcdefghij"));
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  objs[next_objs_index++] =
82044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      FACTORY->NewStringFromAscii(CStrVector("abcdefghij"), TENURED);
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate a large string (for large object space).
8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int large_size = Page::kMaxNonCodeHeapObjectSize + 1;
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char* str = new char[large_size];
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < large_size - 1; ++i) str[i] = 'a';
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  str[large_size - 1] = '\0';
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  objs[next_objs_index++] =
82844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      FACTORY->NewStringFromAscii(CStrVector(str), TENURED);
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  delete[] str;
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Add a Map object to look for.
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  objs[next_objs_index++] = Handle<Map>(HeapObject::cast(*objs[0])->map());
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(objs_count, next_objs_index);
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(objs_count, ObjectsFoundInHeap(objs, objs_count));
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
8376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8396ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockTEST(EmptyHandleEscapeFrom) {
8406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  InitializeVM();
8416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::HandleScope scope;
8436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSObject> runaway;
8446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  {
8466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      v8::HandleScope nested;
8476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<JSObject> empty;
8486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      runaway = empty.EscapeFrom(&nested);
8496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(runaway.is_null());
8526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8556ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic int LenFromSize(int size) {
8566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return (size - FixedArray::kHeaderSize) / kPointerSize;
8576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8606ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockTEST(Regression39128) {
8616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Test case for crbug.com/39128.
8626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  InitializeVM();
8636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Increase the chance of 'bump-the-pointer' allocation in old space.
8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(Heap::kNoGCFlags);
8666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::HandleScope scope;
8686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // The plan: create JSObject which references objects in new space.
8706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Then clone this object (forcing it to go into old space) and check
8717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // that region dirty marks are updated correctly.
8726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Step 1: prepare a map for the object.  We add 1 inobject property to it.
87444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<JSFunction> object_ctor(
87544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Isolate::Current()->global_context()->object_function());
8766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(object_ctor->has_initial_map());
8776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Map> object_map(object_ctor->initial_map());
8786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Create a map with single inobject property.
87944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Map> my_map = FACTORY->CopyMap(object_map, 1);
8806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int n_properties = my_map->inobject_properties();
8816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_GT(n_properties, 0);
8826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int object_size = my_map->instance_size();
8846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Step 2: allocate a lot of objects so to almost fill new space: we need
8866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // just enough room to allocate JSObject and thus fill the newspace.
8876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int allocation_amount = Min(FixedArray::kMaxSize,
88944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              HEAP->MaxObjectSizeInNewSpace());
8906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int allocation_len = LenFromSize(allocation_amount);
89144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  NewSpace* new_space = HEAP->new_space();
8926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address* top_addr = new_space->allocation_top_address();
8936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address* limit_addr = new_space->allocation_limit_address();
8946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  while ((*limit_addr - *top_addr) > allocation_amount) {
89544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    CHECK(!HEAP->always_allocate());
89644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Object* array = HEAP->AllocateFixedArray(allocation_len)->ToObjectChecked();
89744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    CHECK(!array->IsFailure());
8986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CHECK(new_space->Contains(array));
8996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Step 3: now allocate fixed array and JSObject to fill the whole new space.
9026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int to_fill = static_cast<int>(*limit_addr - *top_addr - object_size);
9036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int fixed_array_len = LenFromSize(to_fill);
9046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(fixed_array_len < FixedArray::kMaxLength);
9056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
90644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(!HEAP->always_allocate());
90744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Object* array = HEAP->AllocateFixedArray(fixed_array_len)->ToObjectChecked();
90844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(!array->IsFailure());
9096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(new_space->Contains(array));
9106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
91144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Object* object = HEAP->AllocateJSObjectFromMap(*my_map)->ToObjectChecked();
9126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK(new_space->Contains(object));
9136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  JSObject* jsobject = JSObject::cast(object);
9147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(0, FixedArray::cast(jsobject->elements())->length());
9156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(0, jsobject->properties()->length());
9166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Create a reference to object in new space in jsobject.
9176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  jsobject->FastPropertyAtPut(-1, array);
9186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(0, static_cast<int>(*limit_addr - *top_addr));
9206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Step 4: clone jsobject, but force always allocate first to create a clone
9226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // in old pointer space.
92344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Address old_pointer_space_top = HEAP->old_pointer_space()->top();
9246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  AlwaysAllocateScope aa_scope;
92544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Object* clone_obj = HEAP->CopyJSObject(jsobject)->ToObjectChecked();
9266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  JSObject* clone = JSObject::cast(clone_obj);
9276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (clone->address() != old_pointer_space_top) {
9286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Alas, got allocated from free list, we cannot do checks.
9296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return;
9306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
93144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(HEAP->old_pointer_space()->Contains(clone->address()));
9327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
9337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
934f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
9357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTEST(TestCodeFlushing) {
9367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  i::FLAG_allow_natives_syntax = true;
9377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // If we do not flush code this test is invalid.
9387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (!FLAG_flush_code) return;
9397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  InitializeVM();
9407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::HandleScope scope;
9417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const char* source = "function foo() {"
9427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                       "  var x = 42;"
9437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                       "  var y = 42;"
9447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                       "  var z = x + y;"
9457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                       "};"
9467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                       "foo()";
94744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> foo_name = FACTORY->LookupAsciiSymbol("foo");
9487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
9497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // This compile will add the code to the compilation cache.
950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { v8::HandleScope scope;
951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(source);
952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
9537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
9547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check function is compiled.
95544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Object* func_value = Isolate::Current()->context()->global()->
95644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      GetProperty(*foo_name)->ToObjectChecked();
9577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK(func_value->IsJSFunction());
9587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Handle<JSFunction> function(JSFunction::cast(func_value));
9597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK(function->shared()->is_compiled());
9607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
9613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(1609) Currently incremental marker does not support code flushing.
9623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
9633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
9647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
9657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK(function->shared()->is_compiled());
966756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
9673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
9683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
9693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
9723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
9737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
9747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // foo should no longer be in the compilation cache
975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!function->shared()->is_compiled() || function->IsOptimized());
976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!function->is_compiled() || function->IsOptimized());
9777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Call foo to get it recompiled.
9787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CompileRun("foo()");
9797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK(function->shared()->is_compiled());
980756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK(function->is_compiled());
9816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
982f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
983f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
984f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// Count the number of global contexts in the weak list of global contexts.
985f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochstatic int CountGlobalContexts() {
986f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  int count = 0;
98744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Object* object = HEAP->global_contexts_list();
988f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  while (!object->IsUndefined()) {
989f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    count++;
990f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    object = Context::cast(object)->get(Context::NEXT_CONTEXT_LINK);
991f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
992f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  return count;
993f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
994f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
995f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Count the number of user functions in the weak list of optimized
997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// functions attached to a global context.
998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic int CountOptimizedUserFunctions(v8::Handle<v8::Context> context) {
999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int count = 0;
1000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<Context> icontext = v8::Utils::OpenHandle(*context);
1001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Object* object = icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST);
1002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (object->IsJSFunction() && !JSFunction::cast(object)->IsBuiltin()) {
1003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    count++;
1004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    object = JSFunction::cast(object)->next_function_link();
1005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return count;
1007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1010f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(TestInternalWeakLists) {
101144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::V8::Initialize();
101244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1013f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  static const int kNumTestContexts = 10;
1014f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1015f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::HandleScope scope;
1016f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::Persistent<v8::Context> ctx[kNumTestContexts];
1017f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1018f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_EQ(0, CountGlobalContexts());
1019f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1020f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Create a number of global contests which gets linked together.
1021f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  for (int i = 0; i < kNumTestContexts; i++) {
1022f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    ctx[i] = v8::Context::New();
1023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bool opt = (FLAG_always_opt && i::V8::UseCrankshaft());
1025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1026f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    CHECK_EQ(i + 1, CountGlobalContexts());
1027f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1028f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    ctx[i]->Enter();
1029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Create a handle scope so no function objects get stuch in the outer
1031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // handle scope
1032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    v8::HandleScope scope;
1033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    const char* source = "function f1() { };"
1034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                         "function f2() { };"
1035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                         "function f3() { };"
1036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                         "function f4() { };"
1037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                         "function f5() { };";
1038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(source);
1039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_EQ(0, CountOptimizedUserFunctions(ctx[i]));
1040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("f1()");
1041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_EQ(opt ? 1 : 0, CountOptimizedUserFunctions(ctx[i]));
1042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("f2()");
1043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i]));
1044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("f3()");
1045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i]));
1046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("f4()");
1047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i]));
1048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("f5()");
1049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i]));
1050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Remove function f1, and
1052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("f1=null");
1053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Scavenge treats these references as strong.
1055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; j < 10; j++) {
105644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HEAP->PerformScavenge();
1057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i]));
1058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Mark compact handles the weak references.
10613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i]));
1063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Get rid of f3 and f5 in the same way.
1065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("f3=null");
1066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; j < 10; j++) {
106744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HEAP->PerformScavenge();
1068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i]));
1069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
10703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i]));
1072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("f5=null");
1073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int j = 0; j < 10; j++) {
107444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HEAP->PerformScavenge();
1075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i]));
1076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
10773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i]));
1079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1080f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    ctx[i]->Exit();
1081f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
1082f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1083f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Force compilation cache cleanup.
10843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1085f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1086f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Dispose the global contexts one by one.
1087f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  for (int i = 0; i < kNumTestContexts; i++) {
1088f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    ctx[i].Dispose();
1089f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    ctx[i].Clear();
1090f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1091f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    // Scavenge treats these references as strong.
1092f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    for (int j = 0; j < 10; j++) {
109344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HEAP->PerformScavenge();
1094f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      CHECK_EQ(kNumTestContexts - i, CountGlobalContexts());
1095f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    }
1096f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1097f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    // Mark compact handles the weak references.
10983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1099f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    CHECK_EQ(kNumTestContexts - i - 1, CountGlobalContexts());
1100f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
1101f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1102f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_EQ(0, CountGlobalContexts());
1103f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
1104f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1105f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1106f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// Count the number of global contexts in the weak list of global contexts
1107f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// causing a GC after the specified number of elements.
1108f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochstatic int CountGlobalContextsWithGC(int n) {
1109f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  int count = 0;
111044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Object> object(HEAP->global_contexts_list());
1111f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  while (!object->IsUndefined()) {
1112f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    count++;
11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (count == n) HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1114f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    object =
1115f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch        Handle<Object>(Context::cast(*object)->get(Context::NEXT_CONTEXT_LINK));
1116f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
1117f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  return count;
1118f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
1119f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1120f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Count the number of user functions in the weak list of optimized
1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// functions attached to a global context causing a GC after the
1123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// specified number of elements.
1124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic int CountOptimizedUserFunctionsWithGC(v8::Handle<v8::Context> context,
1125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             int n) {
1126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int count = 0;
1127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<Context> icontext = v8::Utils::OpenHandle(*context);
1128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<Object> object(icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST));
1129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (object->IsJSFunction() &&
1130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         !Handle<JSFunction>::cast(object)->IsBuiltin()) {
1131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    count++;
11323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (count == n) HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    object = Handle<Object>(
1134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Object::cast(JSFunction::cast(*object)->next_function_link()));
1135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return count;
1137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1140f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(TestInternalWeakListsTraverseWithGC) {
114144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::V8::Initialize();
114244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1143f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  static const int kNumTestContexts = 10;
1144f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1145f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::HandleScope scope;
1146f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::Persistent<v8::Context> ctx[kNumTestContexts];
1147f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1148f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_EQ(0, CountGlobalContexts());
1149f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1150f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Create an number of contexts and check the length of the weak list both
1151f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // with and without GCs while iterating the list.
1152f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  for (int i = 0; i < kNumTestContexts; i++) {
1153f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    ctx[i] = v8::Context::New();
1154f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    CHECK_EQ(i + 1, CountGlobalContexts());
1155f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    CHECK_EQ(i + 1, CountGlobalContextsWithGC(i / 2 + 1));
1156f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
1157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool opt = (FLAG_always_opt && i::V8::UseCrankshaft());
1159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Compile a number of functions the length of the weak list of optimized
1161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // functions both with and without GCs while iterating the list.
1162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ctx[0]->Enter();
1163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const char* source = "function f1() { };"
1164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       "function f2() { };"
1165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       "function f3() { };"
1166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       "function f4() { };"
1167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       "function f5() { };";
1168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompileRun(source);
1169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(0, CountOptimizedUserFunctions(ctx[0]));
1170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompileRun("f1()");
1171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(opt ? 1 : 0, CountOptimizedUserFunctions(ctx[0]));
1172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(opt ? 1 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 1));
1173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompileRun("f2()");
1174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[0]));
1175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 1));
1176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompileRun("f3()");
1177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[0]));
1178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 1));
1179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompileRun("f4()");
1180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[0]));
1181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 2));
1182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompileRun("f5()");
1183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[0]));
1184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 4));
1185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ctx[0]->Exit();
1187f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
11888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
11898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
11903ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(TestSizeOfObjects) {
11913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::Initialize();
11923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get initial heap size after several full GCs, which will stabilize
11943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the heap size and return with sweeping finished completely.
11953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(Heap::kNoGCFlags);
11963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(Heap::kNoGCFlags);
11973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(Heap::kNoGCFlags);
11983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(Heap::kNoGCFlags);
11993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(HEAP->old_pointer_space()->IsSweepingComplete());
12003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int initial_size = static_cast<int>(HEAP->SizeOfObjects());
12013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
12033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Allocate objects on several different old-space pages so that
12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // lazy sweeping kicks in for subsequent GC runs.
12053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    AlwaysAllocateScope always_allocate;
12063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int filler_size = static_cast<int>(FixedArray::SizeFor(8192));
12073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 1; i <= 100; i++) {
12083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HEAP->AllocateFixedArray(8192, TENURED)->ToObjectChecked();
12093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CHECK_EQ(initial_size + i * filler_size,
12103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               static_cast<int>(HEAP->SizeOfObjects()));
12113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
12123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The heap size should go back to initial size after a full GC, even
12153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // though sweeping didn't finish yet.
12163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(Heap::kNoGCFlags);
12173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!HEAP->old_pointer_space()->IsSweepingComplete());
12183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(initial_size, static_cast<int>(HEAP->SizeOfObjects()));
12193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Advancing the sweeper step-wise should not change the heap size.
12213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (!HEAP->old_pointer_space()->IsSweepingComplete()) {
12223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HEAP->old_pointer_space()->AdvanceSweeper(KB);
12233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(initial_size, static_cast<int>(HEAP->SizeOfObjects()));
12243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) WangTEST(TestSizeOfObjectsVsHeapIteratorPrecision) {
12298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  InitializeVM();
12303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->EnsureHeapIsIterable();
123144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  intptr_t size_of_objects_1 = HEAP->SizeOfObjects();
12323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HeapIterator iterator;
12338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  intptr_t size_of_objects_2 = 0;
12348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  for (HeapObject* obj = iterator.next();
12358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang       obj != NULL;
12368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang       obj = iterator.next()) {
12378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    size_of_objects_2 += obj->Size();
12388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
12393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Delta must be within 5% of the larger result.
12403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(gc): Tighten this up by distinguishing between byte
12413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // arrays that are real and those that merely mark free space
12423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // on the heap.
12438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (size_of_objects_1 > size_of_objects_2) {
12448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    intptr_t delta = size_of_objects_1 - size_of_objects_2;
12458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    PrintF("Heap::SizeOfObjects: %" V8_PTR_PREFIX "d, "
12468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang           "Iterator: %" V8_PTR_PREFIX "d, "
12478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang           "delta: %" V8_PTR_PREFIX "d\n",
12488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang           size_of_objects_1, size_of_objects_2, delta);
12493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_GT(size_of_objects_1 / 20, delta);
12508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  } else {
12518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    intptr_t delta = size_of_objects_2 - size_of_objects_1;
12528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    PrintF("Heap::SizeOfObjects: %" V8_PTR_PREFIX "d, "
12538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang           "Iterator: %" V8_PTR_PREFIX "d, "
12548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang           "delta: %" V8_PTR_PREFIX "d\n",
12558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang           size_of_objects_1, size_of_objects_2, delta);
12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_GT(size_of_objects_2 / 20, delta);
12578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
12588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
1259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
12613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void FillUpNewSpace(NewSpace* new_space) {
12623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Fill up new space to the point that it is completely full. Make sure
12633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // that the scavenger does not undo the filling.
12643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::HandleScope scope;
12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AlwaysAllocateScope always_allocate;
12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t available = new_space->EffectiveCapacity() - new_space->Size();
12673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t number_of_fillers = (available / FixedArray::SizeFor(1000)) - 10;
12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (intptr_t i = 0; i < number_of_fillers; i++) {
12693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK(HEAP->InNewSpace(*FACTORY->NewFixedArray(1000, NOT_TENURED)));
1270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
12713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1272592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(GrowAndShrinkNewSpace) {
12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InitializeVM();
12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  NewSpace* new_space = HEAP->new_space();
12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Explicitly growing should double the space capacity.
12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t old_capacity, new_capacity;
12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  old_capacity = new_space->Capacity();
12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  new_space->Grow();
12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  new_capacity = new_space->Capacity();
12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(2 * old_capacity == new_capacity);
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  old_capacity = new_space->Capacity();
12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FillUpNewSpace(new_space);
12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  new_capacity = new_space->Capacity();
12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(old_capacity == new_capacity);
12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Explicitly shrinking should not affect space capacity.
12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  old_capacity = new_space->Capacity();
12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  new_space->Shrink();
12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  new_capacity = new_space->Capacity();
12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(old_capacity == new_capacity);
12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Let the scavenger empty the new space.
12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectGarbage(NEW_SPACE);
12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_LE(new_space->Size(), old_capacity);
12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Explicitly shrinking should halve the space capacity.
13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  old_capacity = new_space->Capacity();
13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  new_space->Shrink();
13033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  new_capacity = new_space->Capacity();
13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(old_capacity == 2 * new_capacity);
13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Consecutive shrinking should not affect space capacity.
13073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  old_capacity = new_space->Capacity();
13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  new_space->Shrink();
13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  new_space->Shrink();
13103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  new_space->Shrink();
13113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  new_capacity = new_space->Capacity();
13123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(old_capacity == new_capacity);
13133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
13143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13163ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(CollectingAllAvailableGarbageShrinksNewSpace) {
1317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  InitializeVM();
1318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
13193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  NewSpace* new_space = HEAP->new_space();
13203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t old_capacity, new_capacity;
13213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  old_capacity = new_space->Capacity();
13223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  new_space->Grow();
13233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  new_capacity = new_space->Capacity();
13243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(2 * old_capacity == new_capacity);
13253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FillUpNewSpace(new_space);
13263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllAvailableGarbage();
13273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  new_capacity = new_space->Capacity();
13283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(old_capacity == new_capacity);
13293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
13303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic int NumberOfGlobalObjects() {
13333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int count = 0;
13343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HeapIterator iterator;
13353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
13363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (obj->IsGlobalObject()) count++;
13373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
13383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return count;
13393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
13403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Test that we don't embed maps from foreign contexts into
13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// optimized code.
13443ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(LeakGlobalContextViaMap) {
13453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::FLAG_allow_natives_syntax = true;
13463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::HandleScope outer_scope;
13473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Persistent<v8::Context> ctx1 = v8::Context::New();
13483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Persistent<v8::Context> ctx2 = v8::Context::New();
13493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ctx1->Enter();
13503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllAvailableGarbage();
13523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(4, NumberOfGlobalObjects());
13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
13553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::HandleScope inner_scope;
13563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CompileRun("var v = {x: 42}");
13573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v"));
13583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx2->Enter();
13593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx2->Global()->Set(v8_str("o"), v);
13603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::Local<v8::Value> res = CompileRun(
13613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "function f() { return o.x; }"
13623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "for (var i = 0; i < 10; ++i) f();"
13633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "%OptimizeFunctionOnNextCall(f);"
13643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "f();");
13653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(42, res->Int32Value());
13663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0));
13673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx2->Exit();
13683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx1->Exit();
13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx1.Dispose();
1370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
13713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllAvailableGarbage();
13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(2, NumberOfGlobalObjects());
13733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ctx2.Dispose();
13743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllAvailableGarbage();
13753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(0, NumberOfGlobalObjects());
13763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
13773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Test that we don't embed functions from foreign contexts into
13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// optimized code.
13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(LeakGlobalContextViaFunction) {
13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::FLAG_allow_natives_syntax = true;
13833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::HandleScope outer_scope;
13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Persistent<v8::Context> ctx1 = v8::Context::New();
13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Persistent<v8::Context> ctx2 = v8::Context::New();
13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ctx1->Enter();
13873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllAvailableGarbage();
13893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(4, NumberOfGlobalObjects());
13903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
13923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::HandleScope inner_scope;
13933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CompileRun("var v = function() { return 42; }");
13943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v"));
13953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx2->Enter();
13963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx2->Global()->Set(v8_str("o"), v);
13973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::Local<v8::Value> res = CompileRun(
13983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "function f(x) { return x(); }"
13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "for (var i = 0; i < 10; ++i) f(o);"
14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "%OptimizeFunctionOnNextCall(f);"
14013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "f(o);");
14023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(42, res->Int32Value());
14033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0));
14043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx2->Exit();
14053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx1->Exit();
14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx1.Dispose();
1407592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
14083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllAvailableGarbage();
14093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(2, NumberOfGlobalObjects());
14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ctx2.Dispose();
14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllAvailableGarbage();
14123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(0, NumberOfGlobalObjects());
14133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
14143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14163ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(LeakGlobalContextViaMapKeyed) {
14173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::FLAG_allow_natives_syntax = true;
14183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::HandleScope outer_scope;
14193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Persistent<v8::Context> ctx1 = v8::Context::New();
14203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Persistent<v8::Context> ctx2 = v8::Context::New();
14213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ctx1->Enter();
14223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllAvailableGarbage();
14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(4, NumberOfGlobalObjects());
14253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1426592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::HandleScope inner_scope;
14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CompileRun("var v = [42, 43]");
14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v"));
14303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx2->Enter();
14313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx2->Global()->Set(v8_str("o"), v);
14323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::Local<v8::Value> res = CompileRun(
14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "function f() { return o[0]; }"
14343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "for (var i = 0; i < 10; ++i) f();"
14353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "%OptimizeFunctionOnNextCall(f);"
14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "f();");
14373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(42, res->Int32Value());
14383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0));
14393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx2->Exit();
14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx1->Exit();
14413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx1.Dispose();
1442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
14433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllAvailableGarbage();
14443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(2, NumberOfGlobalObjects());
14453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ctx2.Dispose();
14463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllAvailableGarbage();
14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(0, NumberOfGlobalObjects());
14483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
14493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14513ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(LeakGlobalContextViaMapProto) {
14523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::FLAG_allow_natives_syntax = true;
14533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::HandleScope outer_scope;
14543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Persistent<v8::Context> ctx1 = v8::Context::New();
14553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Persistent<v8::Context> ctx2 = v8::Context::New();
14563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ctx1->Enter();
14573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllAvailableGarbage();
14593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(4, NumberOfGlobalObjects());
14603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::HandleScope inner_scope;
14633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CompileRun("var v = { y: 42}");
14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v"));
14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx2->Enter();
14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx2->Global()->Set(v8_str("o"), v);
14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::Local<v8::Value> res = CompileRun(
14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "function f() {"
14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "  var p = {x: 42};"
14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "  p.__proto__ = o;"
14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "  return p.x;"
14723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "}"
14733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "for (var i = 0; i < 10; ++i) f();"
14743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "%OptimizeFunctionOnNextCall(f);"
14753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "f();");
14763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(42, res->Int32Value());
14773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0));
14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx2->Exit();
14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx1->Exit();
14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ctx1.Dispose();
14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllAvailableGarbage();
14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(2, NumberOfGlobalObjects());
14843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ctx2.Dispose();
14853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllAvailableGarbage();
14863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(0, NumberOfGlobalObjects());
14873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
14883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14903ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(InstanceOfStubWriteBarrier) {
14913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::FLAG_allow_natives_syntax = true;
14923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
14933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::FLAG_verify_heap = true;
14943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
14953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InitializeVM();
14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!i::V8::UseCrankshaft()) return;
14973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::HandleScope outer_scope;
14983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
15003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::HandleScope scope;
15013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CompileRun(
15023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "function foo () { }"
15033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "function mkbar () { return new (new Function(\"\")) (); }"
15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "function f (x) { return (x instanceof foo); }"
15053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "function g () { f(mkbar()); }"
15063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "f(new foo()); f(new foo());"
15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "%OptimizeFunctionOnNextCall(f);"
15083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "f(new foo()); g();");
15093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
15103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  IncrementalMarking* marking = HEAP->incremental_marking();
15123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  marking->Abort();
15133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  marking->Start();
15143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSFunction> f =
15163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v8::Utils::OpenHandle(
15173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          *v8::Handle<v8::Function>::Cast(
15183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              v8::Context::GetCurrent()->Global()->Get(v8_str("f"))));
15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(f->IsOptimized());
15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (!Marking::IsBlack(Marking::MarkBitFrom(f->code())) &&
15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         !marking->IsStopped()) {
15248f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch    // Discard any pending GC requests otherwise we will get GC when we enter
15258f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch    // code below.
15268f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch    marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(marking->IsMarking());
15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::HandleScope scope;
15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::Handle<v8::Object> global = v8::Context::GetCurrent()->Global();
15343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::Handle<v8::Function> g =
15353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        v8::Handle<v8::Function>::Cast(global->Get(v8_str("g")));
15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    g->Call(global, 0, NULL);
15373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->incremental_marking()->set_should_hurry(true);
15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectGarbage(OLD_POINTER_SPACE);
15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(PrototypeTransitionClearing) {
15453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InitializeVM();
15463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::HandleScope scope;
15473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
15493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var base = {};"
15503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var live = [];"
15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "for (var i = 0; i < 10; i++) {"
15523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  var object = {};"
15533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  var prototype = {};"
15543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  object.__proto__ = prototype;"
15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  if (i >= 3) live.push(object, prototype);"
15563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "}");
15573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSObject> baseObject =
15593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v8::Utils::OpenHandle(
15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          *v8::Handle<v8::Object>::Cast(
15613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              v8::Context::GetCurrent()->Global()->Get(v8_str("base"))));
15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Verify that only dead prototype transitions are cleared.
15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(10, baseObject->map()->NumberOfProtoTransitions());
15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(Heap::kNoGCFlags);
15663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(10 - 3, baseObject->map()->NumberOfProtoTransitions());
15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Verify that prototype transitions array was compacted.
15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FixedArray* trans = baseObject->map()->prototype_transitions();
15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < 10 - 3; i++) {
15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int j = Map::kProtoTransitionHeaderSize +
15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        i * Map::kProtoTransitionElementsPerEntry;
15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK(trans->get(j + Map::kProtoTransitionMapOffset)->IsMap());
15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK(trans->get(j + Map::kProtoTransitionPrototypeOffset)->IsJSObject());
15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Make sure next prototype is placed on an old-space evacuation candidate.
15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSObject> prototype;
15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PagedSpace* space = HEAP->old_pointer_space();
15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  do {
15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    prototype = FACTORY->NewJSArray(32 * KB, FAST_ELEMENTS, TENURED);
15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } while (space->FirstPage() == space->LastPage() ||
15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      !space->LastPage()->Contains(prototype->address()));
15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Add a prototype on an evacuation candidate and verify that transition
15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // clearing correctly records slots in prototype transition array.
15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::FLAG_always_compact = true;
15883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Map> map(baseObject->map());
15893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!space->LastPage()->Contains(map->prototype_transitions()->address()));
15903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(space->LastPage()->Contains(prototype->address()));
15913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  baseObject->SetPrototype(*prototype, false)->ToObjectChecked();
15923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(map->GetPrototypeTransition(*prototype)->IsMap());
15933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(Heap::kNoGCFlags);
15943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(map->GetPrototypeTransition(*prototype)->IsMap());
1595c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
15968f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch
15978f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch
15988f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben MurdochTEST(ResetSharedFunctionInfoCountersDuringIncrementalMarking) {
15998f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  i::FLAG_allow_natives_syntax = true;
16008f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch#ifdef DEBUG
16018f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  i::FLAG_verify_heap = true;
16028f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch#endif
16038f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  InitializeVM();
16048f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  if (!i::V8::UseCrankshaft()) return;
16058f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  v8::HandleScope outer_scope;
16068f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch
16078f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  {
16088f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch    v8::HandleScope scope;
16098f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch    CompileRun(
16108f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch        "function f () {"
16118f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch        "  var s = 0;"
16128f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch        "  for (var i = 0; i < 100; i++)  s += i;"
16138f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch        "  return s;"
16148f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch        "}"
16158f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch        "f(); f();"
16168f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch        "%OptimizeFunctionOnNextCall(f);"
16178f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch        "f();");
16188f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  }
16198f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  Handle<JSFunction> f =
16208f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch      v8::Utils::OpenHandle(
16218f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch          *v8::Handle<v8::Function>::Cast(
16228f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch              v8::Context::GetCurrent()->Global()->Get(v8_str("f"))));
16238f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  CHECK(f->IsOptimized());
16248f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch
16258f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  IncrementalMarking* marking = HEAP->incremental_marking();
16268f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  marking->Abort();
16278f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  marking->Start();
16288f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch
16298f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  // The following two calls will increment HEAP->global_ic_age().
16308f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  const int kLongIdlePauseInMs = 1000;
16318f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  v8::V8::ContextDisposedNotification();
16328f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  v8::V8::IdleNotification(kLongIdlePauseInMs);
16338f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch
16348f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  while (!marking->IsStopped() && !marking->IsComplete()) {
16358f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch    marking->Step(1 * MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
16368f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  }
16378f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch
16388f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  CHECK_EQ(HEAP->global_ic_age(), f->shared()->ic_age());
16398f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  CHECK_EQ(0, f->shared()->opt_count());
16408f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  CHECK_EQ(0, f->shared()->code()->profiler_ticks());
16418f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch}
16428f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch
16438f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch
16448f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben MurdochTEST(ResetSharedFunctionInfoCountersDuringMarkSweep) {
16458f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  i::FLAG_allow_natives_syntax = true;
16468f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch#ifdef DEBUG
16478f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  i::FLAG_verify_heap = true;
16488f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch#endif
16498f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  InitializeVM();
16508f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  if (!i::V8::UseCrankshaft()) return;
16518f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  v8::HandleScope outer_scope;
16528f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch
16538f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  {
16548f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch    v8::HandleScope scope;
16558f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch    CompileRun(
16568f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch        "function f () {"
16578f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch        "  var s = 0;"
16588f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch        "  for (var i = 0; i < 100; i++)  s += i;"
16598f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch        "  return s;"
16608f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch        "}"
16618f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch        "f(); f();"
16628f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch        "%OptimizeFunctionOnNextCall(f);"
16638f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch        "f();");
16648f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  }
16658f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  Handle<JSFunction> f =
16668f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch      v8::Utils::OpenHandle(
16678f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch          *v8::Handle<v8::Function>::Cast(
16688f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch              v8::Context::GetCurrent()->Global()->Get(v8_str("f"))));
16698f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  CHECK(f->IsOptimized());
16708f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch
16718f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  HEAP->incremental_marking()->Abort();
16728f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch
16738f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  // The following two calls will increment HEAP->global_ic_age().
16748f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  // Since incremental marking is off, IdleNotification will do full GC.
16758f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  const int kLongIdlePauseInMs = 1000;
16768f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  v8::V8::ContextDisposedNotification();
16778f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  v8::V8::IdleNotification(kLongIdlePauseInMs);
16788f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch
16798f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  CHECK_EQ(HEAP->global_ic_age(), f->shared()->ic_age());
16808f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  CHECK_EQ(0, f->shared()->opt_count());
16818f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  CHECK_EQ(0, f->shared()->code()->profiler_ticks());
16828f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch}
1683