blob: 8ed5bf76680b65f850e9517a1a9a9be14bc299ae [file] [log] [blame]
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001// Copyright 2011 the V8 project authors. All rights reserved.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002
3#include <stdlib.h>
4
5#include "v8.h"
6
7#include "execution.h"
8#include "factory.h"
9#include "macro-assembler.h"
10#include "global-handles.h"
11#include "cctest.h"
12
13using namespace v8::internal;
14
15static v8::Persistent<v8::Context> env;
16
17static void InitializeVM() {
18 if (env.IsEmpty()) env = v8::Context::New();
19 v8::HandleScope scope;
20 env->Enter();
21}
22
23
24static void CheckMap(Map* map, int type, int instance_size) {
25 CHECK(map->IsHeapObject());
26#ifdef DEBUG
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000027 CHECK(HEAP->Contains(map));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000028#endif
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000029 CHECK_EQ(HEAP->meta_map(), map->map());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000030 CHECK_EQ(type, map->instance_type());
31 CHECK_EQ(instance_size, map->instance_size());
32}
33
34
35TEST(HeapMaps) {
36 InitializeVM();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000037 CheckMap(HEAP->meta_map(), MAP_TYPE, Map::kSize);
38 CheckMap(HEAP->heap_number_map(), HEAP_NUMBER_TYPE, HeapNumber::kSize);
39 CheckMap(HEAP->fixed_array_map(), FIXED_ARRAY_TYPE, kVariableSizeSentinel);
40 CheckMap(HEAP->string_map(), STRING_TYPE, kVariableSizeSentinel);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000041}
42
43
44static void CheckOddball(Object* obj, const char* string) {
45 CHECK(obj->IsOddball());
46 bool exc;
47 Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
48 CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
49}
50
51
52static void CheckSmi(int value, const char* string) {
53 bool exc;
54 Object* print_string =
55 *Execution::ToString(Handle<Object>(Smi::FromInt(value)), &exc);
56 CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
57}
58
59
60static void CheckNumber(double value, const char* string) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000061 Object* obj = HEAP->NumberFromDouble(value)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000062 CHECK(obj->IsNumber());
63 bool exc;
64 Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
65 CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
66}
67
68
69static void CheckFindCodeObject() {
70 // Test FindCodeObject
71#define __ assm.
72
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000073 Assembler assm(Isolate::Current(), NULL, 0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000074
75 __ nop(); // supported on all architectures
76
77 CodeDesc desc;
78 assm.GetCode(&desc);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000079 Object* code = HEAP->CreateCode(
lrn@chromium.org303ada72010-10-27 09:33:13 +000080 desc,
81 Code::ComputeFlags(Code::STUB),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000082 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000083 CHECK(code->IsCode());
84
85 HeapObject* obj = HeapObject::cast(code);
86 Address obj_addr = obj->address();
87
88 for (int i = 0; i < obj->Size(); i += kPointerSize) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000089 Object* found = HEAP->FindCodeObject(obj_addr + i);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000090 CHECK_EQ(code, found);
91 }
92
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000093 Object* copy = HEAP->CreateCode(
lrn@chromium.org303ada72010-10-27 09:33:13 +000094 desc,
95 Code::ComputeFlags(Code::STUB),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000096 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000097 CHECK(copy->IsCode());
98 HeapObject* obj_copy = HeapObject::cast(copy);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000099 Object* not_right = HEAP->FindCodeObject(obj_copy->address() +
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000100 obj_copy->Size() / 2);
101 CHECK(not_right != code);
102}
103
104
105TEST(HeapObjects) {
106 InitializeVM();
107
108 v8::HandleScope sc;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000109 Object* value = HEAP->NumberFromDouble(1.000123)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000110 CHECK(value->IsHeapNumber());
111 CHECK(value->IsNumber());
112 CHECK_EQ(1.000123, value->Number());
113
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000114 value = HEAP->NumberFromDouble(1.0)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000115 CHECK(value->IsSmi());
116 CHECK(value->IsNumber());
117 CHECK_EQ(1.0, value->Number());
118
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000119 value = HEAP->NumberFromInt32(1024)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000120 CHECK(value->IsSmi());
121 CHECK(value->IsNumber());
122 CHECK_EQ(1024.0, value->Number());
123
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000124 value = HEAP->NumberFromInt32(Smi::kMinValue)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000125 CHECK(value->IsSmi());
126 CHECK(value->IsNumber());
127 CHECK_EQ(Smi::kMinValue, Smi::cast(value)->value());
128
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000129 value = HEAP->NumberFromInt32(Smi::kMaxValue)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000130 CHECK(value->IsSmi());
131 CHECK(value->IsNumber());
132 CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value());
133
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000134#ifndef V8_TARGET_ARCH_X64
135 // TODO(lrn): We need a NumberFromIntptr function in order to test this.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000136 value = HEAP->NumberFromInt32(Smi::kMinValue - 1)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000137 CHECK(value->IsHeapNumber());
138 CHECK(value->IsNumber());
139 CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000140#endif
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000141
lrn@chromium.org303ada72010-10-27 09:33:13 +0000142 MaybeObject* maybe_value =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000143 HEAP->NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000144 value = maybe_value->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000145 CHECK(value->IsHeapNumber());
146 CHECK(value->IsNumber());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000147 CHECK_EQ(static_cast<double>(static_cast<uint32_t>(Smi::kMaxValue) + 1),
148 value->Number());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000149
150 // nan oddball checks
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000151 CHECK(HEAP->nan_value()->IsNumber());
152 CHECK(isnan(HEAP->nan_value()->Number()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000153
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000154 Handle<String> s = FACTORY->NewStringFromAscii(CStrVector("fisk hest "));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000155 CHECK(s->IsString());
156 CHECK_EQ(10, s->length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000157
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000158 String* object_symbol = String::cast(HEAP->Object_symbol());
159 CHECK(
160 Isolate::Current()->context()->global()->HasLocalProperty(object_symbol));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000161
162 // Check ToString for oddballs
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000163 CheckOddball(HEAP->true_value(), "true");
164 CheckOddball(HEAP->false_value(), "false");
165 CheckOddball(HEAP->null_value(), "null");
166 CheckOddball(HEAP->undefined_value(), "undefined");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000167
168 // Check ToString for Smis
169 CheckSmi(0, "0");
170 CheckSmi(42, "42");
171 CheckSmi(-42, "-42");
172
173 // Check ToString for Numbers
174 CheckNumber(1.1, "1.1");
175
176 CheckFindCodeObject();
177}
178
179
180TEST(Tagging) {
181 InitializeVM();
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000182 int request = 24;
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000183 CHECK_EQ(request, static_cast<int>(OBJECT_POINTER_ALIGN(request)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000184 CHECK(Smi::FromInt(42)->IsSmi());
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000185 CHECK(Failure::RetryAfterGC(NEW_SPACE)->IsFailure());
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000186 CHECK_EQ(NEW_SPACE,
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000187 Failure::RetryAfterGC(NEW_SPACE)->allocation_space());
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000188 CHECK_EQ(OLD_POINTER_SPACE,
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000189 Failure::RetryAfterGC(OLD_POINTER_SPACE)->allocation_space());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000190 CHECK(Failure::Exception()->IsFailure());
191 CHECK(Smi::FromInt(Smi::kMinValue)->IsSmi());
192 CHECK(Smi::FromInt(Smi::kMaxValue)->IsSmi());
193}
194
195
196TEST(GarbageCollection) {
197 InitializeVM();
198
199 v8::HandleScope sc;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000200 // Check GC.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000201 HEAP->CollectGarbage(NEW_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000202
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000203 Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction");
204 Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot");
205 Handle<String> prop_namex = FACTORY->LookupAsciiSymbol("theSlotx");
206 Handle<String> obj_name = FACTORY->LookupAsciiSymbol("theObject");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000207
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000208 {
209 v8::HandleScope inner_scope;
210 // Allocate a function and keep it in global object's property.
211 Handle<JSFunction> function =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000212 FACTORY->NewFunction(name, FACTORY->undefined_value());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000213 Handle<Map> initial_map =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000214 FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000215 function->set_initial_map(*initial_map);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000216 Isolate::Current()->context()->global()->SetProperty(
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000217 *name, *function, NONE, kNonStrictMode)->ToObjectChecked();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000218 // Allocate an object. Unrooted after leaving the scope.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000219 Handle<JSObject> obj = FACTORY->NewJSObject(function);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000220 obj->SetProperty(
221 *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
222 obj->SetProperty(
223 *prop_namex, Smi::FromInt(24), NONE, kNonStrictMode)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000224
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000225 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
226 CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex));
227 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000228
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000229 HEAP->CollectGarbage(NEW_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000230
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000231 // Function should be alive.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000232 CHECK(Isolate::Current()->context()->global()->HasLocalProperty(*name));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000233 // Check function is retained.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000234 Object* func_value = Isolate::Current()->context()->global()->
235 GetProperty(*name)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000236 CHECK(func_value->IsJSFunction());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000237 Handle<JSFunction> function(JSFunction::cast(func_value));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000238
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000239 {
240 HandleScope inner_scope;
241 // Allocate another object, make it reachable from global.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000242 Handle<JSObject> obj = FACTORY->NewJSObject(function);
243 Isolate::Current()->context()->global()->SetProperty(
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000244 *obj_name, *obj, NONE, kNonStrictMode)->ToObjectChecked();
245 obj->SetProperty(
246 *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000247 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000248
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000249 // After gc, it should survive.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000250 HEAP->CollectGarbage(NEW_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000251
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000252 CHECK(Isolate::Current()->context()->global()->HasLocalProperty(*obj_name));
253 CHECK(Isolate::Current()->context()->global()->
254 GetProperty(*obj_name)->ToObjectChecked()->IsJSObject());
255 Object* obj = Isolate::Current()->context()->global()->
256 GetProperty(*obj_name)->ToObjectChecked();
lrn@chromium.org303ada72010-10-27 09:33:13 +0000257 JSObject* js_obj = JSObject::cast(obj);
258 CHECK_EQ(Smi::FromInt(23), js_obj->GetProperty(*prop_name));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000259}
260
261
262static void VerifyStringAllocation(const char* string) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000263 v8::HandleScope scope;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000264 Handle<String> s = FACTORY->NewStringFromUtf8(CStrVector(string));
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000265 CHECK_EQ(StrLength(string), s->length());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000266 for (int index = 0; index < s->length(); index++) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000267 CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(index));
268 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000269}
270
271
272TEST(String) {
273 InitializeVM();
274
275 VerifyStringAllocation("a");
276 VerifyStringAllocation("ab");
277 VerifyStringAllocation("abc");
278 VerifyStringAllocation("abcd");
279 VerifyStringAllocation("fiskerdrengen er paa havet");
280}
281
282
283TEST(LocalHandles) {
284 InitializeVM();
285
286 v8::HandleScope scope;
287 const char* name = "Kasper the spunky";
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000288 Handle<String> string = FACTORY->NewStringFromAscii(CStrVector(name));
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000289 CHECK_EQ(StrLength(name), string->length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000290}
291
292
293TEST(GlobalHandles) {
294 InitializeVM();
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000295 GlobalHandles* global_handles = Isolate::Current()->global_handles();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000296
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000297 Handle<Object> h1;
298 Handle<Object> h2;
299 Handle<Object> h3;
300 Handle<Object> h4;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000301
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000302 {
303 HandleScope scope;
304
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000305 Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk"));
306 Handle<Object> u = FACTORY->NewNumber(1.12344);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000307
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000308 h1 = global_handles->Create(*i);
309 h2 = global_handles->Create(*u);
310 h3 = global_handles->Create(*i);
311 h4 = global_handles->Create(*u);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000312 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000313
314 // after gc, it should survive
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000315 HEAP->CollectGarbage(NEW_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000316
317 CHECK((*h1)->IsString());
318 CHECK((*h2)->IsHeapNumber());
319 CHECK((*h3)->IsString());
320 CHECK((*h4)->IsHeapNumber());
321
322 CHECK_EQ(*h3, *h1);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000323 global_handles->Destroy(h1.location());
324 global_handles->Destroy(h3.location());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000325
326 CHECK_EQ(*h4, *h2);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000327 global_handles->Destroy(h2.location());
328 global_handles->Destroy(h4.location());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000329}
330
331
332static bool WeakPointerCleared = false;
333
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000334static void TestWeakGlobalHandleCallback(v8::Persistent<v8::Value> handle,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000335 void* id) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000336 if (1234 == reinterpret_cast<intptr_t>(id)) WeakPointerCleared = true;
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000337 handle.Dispose();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000338}
339
340
341TEST(WeakGlobalHandlesScavenge) {
342 InitializeVM();
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000343 GlobalHandles* global_handles = Isolate::Current()->global_handles();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000344
345 WeakPointerCleared = false;
346
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000347 Handle<Object> h1;
348 Handle<Object> h2;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000349
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000350 {
351 HandleScope scope;
352
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000353 Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk"));
354 Handle<Object> u = FACTORY->NewNumber(1.12344);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000355
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000356 h1 = global_handles->Create(*i);
357 h2 = global_handles->Create(*u);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000358 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000359
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000360 global_handles->MakeWeak(h2.location(),
361 reinterpret_cast<void*>(1234),
362 &TestWeakGlobalHandleCallback);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000363
364 // Scavenge treats weak pointers as normal roots.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000365 HEAP->PerformScavenge();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000366
367 CHECK((*h1)->IsString());
368 CHECK((*h2)->IsHeapNumber());
369
370 CHECK(!WeakPointerCleared);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000371 CHECK(!global_handles->IsNearDeath(h2.location()));
372 CHECK(!global_handles->IsNearDeath(h1.location()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000373
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000374 global_handles->Destroy(h1.location());
375 global_handles->Destroy(h2.location());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000376}
377
378
379TEST(WeakGlobalHandlesMark) {
380 InitializeVM();
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000381 GlobalHandles* global_handles = Isolate::Current()->global_handles();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000382
383 WeakPointerCleared = false;
384
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000385 Handle<Object> h1;
386 Handle<Object> h2;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000387
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000388 {
389 HandleScope scope;
390
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000391 Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk"));
392 Handle<Object> u = FACTORY->NewNumber(1.12344);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000393
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000394 h1 = global_handles->Create(*i);
395 h2 = global_handles->Create(*u);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000396 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000397
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000398 HEAP->CollectGarbage(OLD_POINTER_SPACE);
399 HEAP->CollectGarbage(NEW_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000400 // Make sure the object is promoted.
401
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000402 global_handles->MakeWeak(h2.location(),
403 reinterpret_cast<void*>(1234),
404 &TestWeakGlobalHandleCallback);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000405 CHECK(!GlobalHandles::IsNearDeath(h1.location()));
406 CHECK(!GlobalHandles::IsNearDeath(h2.location()));
407
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000408 HEAP->CollectGarbage(OLD_POINTER_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000409
410 CHECK((*h1)->IsString());
411
412 CHECK(WeakPointerCleared);
413 CHECK(!GlobalHandles::IsNearDeath(h1.location()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000414
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000415 global_handles->Destroy(h1.location());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000416}
417
418TEST(DeleteWeakGlobalHandle) {
419 InitializeVM();
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000420 GlobalHandles* global_handles = Isolate::Current()->global_handles();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000421
422 WeakPointerCleared = false;
423
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000424 Handle<Object> h;
425
426 {
427 HandleScope scope;
428
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000429 Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk"));
430 h = global_handles->Create(*i);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000431 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000432
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000433 global_handles->MakeWeak(h.location(),
434 reinterpret_cast<void*>(1234),
435 &TestWeakGlobalHandleCallback);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000436
437 // Scanvenge does not recognize weak reference.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000438 HEAP->PerformScavenge();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000439
440 CHECK(!WeakPointerCleared);
441
442 // Mark-compact treats weak reference properly.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000443 HEAP->CollectGarbage(OLD_POINTER_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000444
445 CHECK(WeakPointerCleared);
446}
447
448static const char* not_so_random_string_table[] = {
449 "abstract",
450 "boolean",
451 "break",
452 "byte",
453 "case",
454 "catch",
455 "char",
456 "class",
457 "const",
458 "continue",
459 "debugger",
460 "default",
461 "delete",
462 "do",
463 "double",
464 "else",
465 "enum",
466 "export",
467 "extends",
468 "false",
469 "final",
470 "finally",
471 "float",
472 "for",
473 "function",
474 "goto",
475 "if",
476 "implements",
477 "import",
478 "in",
479 "instanceof",
480 "int",
481 "interface",
482 "long",
483 "native",
484 "new",
485 "null",
486 "package",
487 "private",
488 "protected",
489 "public",
490 "return",
491 "short",
492 "static",
493 "super",
494 "switch",
495 "synchronized",
496 "this",
497 "throw",
498 "throws",
499 "transient",
500 "true",
501 "try",
502 "typeof",
503 "var",
504 "void",
505 "volatile",
506 "while",
507 "with",
508 0
509};
510
511
512static void CheckSymbols(const char** strings) {
513 for (const char* string = *strings; *strings != 0; string = *strings++) {
lrn@chromium.org303ada72010-10-27 09:33:13 +0000514 Object* a;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000515 MaybeObject* maybe_a = HEAP->LookupAsciiSymbol(string);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000516 // LookupAsciiSymbol may return a failure if a GC is needed.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000517 if (!maybe_a->ToObject(&a)) continue;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000518 CHECK(a->IsSymbol());
lrn@chromium.org303ada72010-10-27 09:33:13 +0000519 Object* b;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000520 MaybeObject* maybe_b = HEAP->LookupAsciiSymbol(string);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000521 if (!maybe_b->ToObject(&b)) continue;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000522 CHECK_EQ(b, a);
523 CHECK(String::cast(b)->IsEqualTo(CStrVector(string)));
524 }
525}
526
527
528TEST(SymbolTable) {
529 InitializeVM();
530
531 CheckSymbols(not_so_random_string_table);
532 CheckSymbols(not_so_random_string_table);
533}
534
535
536TEST(FunctionAllocation) {
537 InitializeVM();
538
539 v8::HandleScope sc;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000540 Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction");
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000541 Handle<JSFunction> function =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000542 FACTORY->NewFunction(name, FACTORY->undefined_value());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000543 Handle<Map> initial_map =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000544 FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000545 function->set_initial_map(*initial_map);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000546
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000547 Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot");
548 Handle<JSObject> obj = FACTORY->NewJSObject(function);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000549 obj->SetProperty(
550 *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000551 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000552 // Check that we can add properties to function objects.
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000553 function->SetProperty(
554 *prop_name, Smi::FromInt(24), NONE, kNonStrictMode)->ToObjectChecked();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000555 CHECK_EQ(Smi::FromInt(24), function->GetProperty(*prop_name));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000556}
557
558
559TEST(ObjectProperties) {
560 InitializeVM();
561
562 v8::HandleScope sc;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000563 String* object_symbol = String::cast(HEAP->Object_symbol());
564 Object* raw_object = Isolate::Current()->context()->global()->
565 GetProperty(object_symbol)->ToObjectChecked();
lrn@chromium.org303ada72010-10-27 09:33:13 +0000566 JSFunction* object_function = JSFunction::cast(raw_object);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000567 Handle<JSFunction> constructor(object_function);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000568 Handle<JSObject> obj = FACTORY->NewJSObject(constructor);
569 Handle<String> first = FACTORY->LookupAsciiSymbol("first");
570 Handle<String> second = FACTORY->LookupAsciiSymbol("second");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000571
572 // check for empty
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000573 CHECK(!obj->HasLocalProperty(*first));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000574
575 // add first
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000576 obj->SetProperty(
577 *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000578 CHECK(obj->HasLocalProperty(*first));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000579
580 // delete first
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000581 CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION));
582 CHECK(!obj->HasLocalProperty(*first));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000583
584 // add first and then second
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000585 obj->SetProperty(
586 *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
587 obj->SetProperty(
588 *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000589 CHECK(obj->HasLocalProperty(*first));
590 CHECK(obj->HasLocalProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000591
592 // delete first and then second
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000593 CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION));
594 CHECK(obj->HasLocalProperty(*second));
595 CHECK(obj->DeleteProperty(*second, JSObject::NORMAL_DELETION));
596 CHECK(!obj->HasLocalProperty(*first));
597 CHECK(!obj->HasLocalProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000598
599 // add first and then second
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000600 obj->SetProperty(
601 *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
602 obj->SetProperty(
603 *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000604 CHECK(obj->HasLocalProperty(*first));
605 CHECK(obj->HasLocalProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000606
607 // delete second and then first
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000608 CHECK(obj->DeleteProperty(*second, JSObject::NORMAL_DELETION));
609 CHECK(obj->HasLocalProperty(*first));
610 CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION));
611 CHECK(!obj->HasLocalProperty(*first));
612 CHECK(!obj->HasLocalProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000613
614 // check string and symbol match
615 static const char* string1 = "fisk";
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000616 Handle<String> s1 = FACTORY->NewStringFromAscii(CStrVector(string1));
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000617 obj->SetProperty(
618 *s1, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000619 Handle<String> s1_symbol = FACTORY->LookupAsciiSymbol(string1);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000620 CHECK(obj->HasLocalProperty(*s1_symbol));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000621
622 // check symbol and string match
623 static const char* string2 = "fugl";
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000624 Handle<String> s2_symbol = FACTORY->LookupAsciiSymbol(string2);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000625 obj->SetProperty(
626 *s2_symbol, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000627 Handle<String> s2 = FACTORY->NewStringFromAscii(CStrVector(string2));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000628 CHECK(obj->HasLocalProperty(*s2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000629}
630
631
632TEST(JSObjectMaps) {
633 InitializeVM();
634
635 v8::HandleScope sc;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000636 Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction");
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000637 Handle<JSFunction> function =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000638 FACTORY->NewFunction(name, FACTORY->undefined_value());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000639 Handle<Map> initial_map =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000640 FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000641 function->set_initial_map(*initial_map);
642
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000643 Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot");
644 Handle<JSObject> obj = FACTORY->NewJSObject(function);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000645
646 // Set a propery
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000647 obj->SetProperty(
648 *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000649 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000650
651 // Check the map has changed
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000652 CHECK(*initial_map != obj->map());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000653}
654
655
656TEST(JSArray) {
657 InitializeVM();
658
659 v8::HandleScope sc;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000660 Handle<String> name = FACTORY->LookupAsciiSymbol("Array");
661 Object* raw_object = Isolate::Current()->context()->global()->
662 GetProperty(*name)->ToObjectChecked();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000663 Handle<JSFunction> function = Handle<JSFunction>(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000664 JSFunction::cast(raw_object));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000665
666 // Allocate the object.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000667 Handle<JSObject> object = FACTORY->NewJSObject(function);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000668 Handle<JSArray> array = Handle<JSArray>::cast(object);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000669 // We just initialized the VM, no heap allocation failure yet.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000670 Object* ok = array->Initialize(0)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000671
672 // Set array length to 0.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000673 ok = array->SetElementsLength(Smi::FromInt(0))->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000674 CHECK_EQ(Smi::FromInt(0), array->length());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000675 // Must be in fast mode.
676 CHECK(array->HasFastTypeElements());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000677
678 // array[length] = name.
whesse@chromium.org7b260152011-06-20 15:33:18 +0000679 ok = array->SetElement(0, *name, kNonStrictMode, true)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000680 CHECK_EQ(Smi::FromInt(1), array->length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000681 CHECK_EQ(array->GetElement(0), *name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000682
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000683 // Set array length with larger than smi value.
684 Handle<Object> length =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000685 FACTORY->NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000686 ok = array->SetElementsLength(*length)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000687
688 uint32_t int_length = 0;
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000689 CHECK(length->ToArrayIndex(&int_length));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000690 CHECK_EQ(*length, array->length());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000691 CHECK(array->HasDictionaryElements()); // Must be in slow mode.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000692
693 // array[length] = name.
whesse@chromium.org7b260152011-06-20 15:33:18 +0000694 ok = array->SetElement(
695 int_length, *name, kNonStrictMode, true)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000696 uint32_t new_int_length = 0;
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000697 CHECK(array->length()->ToArrayIndex(&new_int_length));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000698 CHECK_EQ(static_cast<double>(int_length), new_int_length - 1);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000699 CHECK_EQ(array->GetElement(int_length), *name);
700 CHECK_EQ(array->GetElement(0), *name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000701}
702
703
704TEST(JSObjectCopy) {
705 InitializeVM();
706
707 v8::HandleScope sc;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000708 String* object_symbol = String::cast(HEAP->Object_symbol());
709 Object* raw_object = Isolate::Current()->context()->global()->
710 GetProperty(object_symbol)->ToObjectChecked();
lrn@chromium.org303ada72010-10-27 09:33:13 +0000711 JSFunction* object_function = JSFunction::cast(raw_object);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000712 Handle<JSFunction> constructor(object_function);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000713 Handle<JSObject> obj = FACTORY->NewJSObject(constructor);
714 Handle<String> first = FACTORY->LookupAsciiSymbol("first");
715 Handle<String> second = FACTORY->LookupAsciiSymbol("second");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000716
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000717 obj->SetProperty(
718 *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
719 obj->SetProperty(
720 *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000721
whesse@chromium.org7b260152011-06-20 15:33:18 +0000722 Object* ok =
723 obj->SetElement(0, *first, kNonStrictMode, true)->ToObjectChecked();
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000724
whesse@chromium.org7b260152011-06-20 15:33:18 +0000725 ok = obj->SetElement(1, *second, kNonStrictMode, true)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000726
727 // Make the clone.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000728 Handle<JSObject> clone = Copy(obj);
729 CHECK(!clone.is_identical_to(obj));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000730
731 CHECK_EQ(obj->GetElement(0), clone->GetElement(0));
732 CHECK_EQ(obj->GetElement(1), clone->GetElement(1));
733
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000734 CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*first));
735 CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000736
737 // Flip the values.
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000738 clone->SetProperty(
739 *first, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
740 clone->SetProperty(
741 *second, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000742
whesse@chromium.org7b260152011-06-20 15:33:18 +0000743 ok = clone->SetElement(0, *second, kNonStrictMode, true)->ToObjectChecked();
744 ok = clone->SetElement(1, *first, kNonStrictMode, true)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000745
746 CHECK_EQ(obj->GetElement(1), clone->GetElement(0));
747 CHECK_EQ(obj->GetElement(0), clone->GetElement(1));
748
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000749 CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*first));
750 CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000751}
752
753
754TEST(StringAllocation) {
755 InitializeVM();
756
757
758 const unsigned char chars[] = { 0xe5, 0xa4, 0xa7 };
759 for (int length = 0; length < 100; length++) {
760 v8::HandleScope scope;
761 char* non_ascii = NewArray<char>(3 * length + 1);
762 char* ascii = NewArray<char>(length + 1);
763 non_ascii[3 * length] = 0;
764 ascii[length] = 0;
765 for (int i = 0; i < length; i++) {
766 ascii[i] = 'a';
767 non_ascii[3 * i] = chars[0];
768 non_ascii[3 * i + 1] = chars[1];
769 non_ascii[3 * i + 2] = chars[2];
770 }
771 Handle<String> non_ascii_sym =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000772 FACTORY->LookupSymbol(Vector<const char>(non_ascii, 3 * length));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000773 CHECK_EQ(length, non_ascii_sym->length());
774 Handle<String> ascii_sym =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000775 FACTORY->LookupSymbol(Vector<const char>(ascii, length));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000776 CHECK_EQ(length, ascii_sym->length());
777 Handle<String> non_ascii_str =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000778 FACTORY->NewStringFromUtf8(Vector<const char>(non_ascii, 3 * length));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000779 non_ascii_str->Hash();
780 CHECK_EQ(length, non_ascii_str->length());
781 Handle<String> ascii_str =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000782 FACTORY->NewStringFromUtf8(Vector<const char>(ascii, length));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000783 ascii_str->Hash();
784 CHECK_EQ(length, ascii_str->length());
785 DeleteArray(non_ascii);
786 DeleteArray(ascii);
787 }
788}
789
790
791static int ObjectsFoundInHeap(Handle<Object> objs[], int size) {
792 // Count the number of objects found in the heap.
793 int found_count = 0;
794 HeapIterator iterator;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000795 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000796 for (int i = 0; i < size; i++) {
797 if (*objs[i] == obj) {
798 found_count++;
799 }
800 }
801 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000802 return found_count;
803}
804
805
806TEST(Iteration) {
807 InitializeVM();
808 v8::HandleScope scope;
809
810 // Array of objects to scan haep for.
811 const int objs_count = 6;
812 Handle<Object> objs[objs_count];
813 int next_objs_index = 0;
814
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000815 // Allocate a JS array to OLD_POINTER_SPACE and NEW_SPACE
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000816 objs[next_objs_index++] = FACTORY->NewJSArray(10);
817 objs[next_objs_index++] = FACTORY->NewJSArray(10, TENURED);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000818
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000819 // Allocate a small string to OLD_DATA_SPACE and NEW_SPACE
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000820 objs[next_objs_index++] =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000821 FACTORY->NewStringFromAscii(CStrVector("abcdefghij"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000822 objs[next_objs_index++] =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000823 FACTORY->NewStringFromAscii(CStrVector("abcdefghij"), TENURED);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000824
825 // Allocate a large string (for large object space).
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000826 int large_size = HEAP->MaxObjectSizeInPagedSpace() + 1;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000827 char* str = new char[large_size];
828 for (int i = 0; i < large_size - 1; ++i) str[i] = 'a';
829 str[large_size - 1] = '\0';
830 objs[next_objs_index++] =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000831 FACTORY->NewStringFromAscii(CStrVector(str), TENURED);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000832 delete[] str;
833
834 // Add a Map object to look for.
835 objs[next_objs_index++] = Handle<Map>(HeapObject::cast(*objs[0])->map());
836
837 CHECK_EQ(objs_count, next_objs_index);
838 CHECK_EQ(objs_count, ObjectsFoundInHeap(objs, objs_count));
839}
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000840
841
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000842TEST(EmptyHandleEscapeFrom) {
843 InitializeVM();
844
845 v8::HandleScope scope;
846 Handle<JSObject> runaway;
847
848 {
849 v8::HandleScope nested;
850 Handle<JSObject> empty;
851 runaway = empty.EscapeFrom(&nested);
852 }
853
854 CHECK(runaway.is_null());
855}
856
857
858static int LenFromSize(int size) {
859 return (size - FixedArray::kHeaderSize) / kPointerSize;
860}
861
862
863TEST(Regression39128) {
864 // Test case for crbug.com/39128.
865 InitializeVM();
866
867 // Increase the chance of 'bump-the-pointer' allocation in old space.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000868 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000869
870 v8::HandleScope scope;
871
872 // The plan: create JSObject which references objects in new space.
873 // Then clone this object (forcing it to go into old space) and check
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000874 // that region dirty marks are updated correctly.
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000875
876 // Step 1: prepare a map for the object. We add 1 inobject property to it.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000877 Handle<JSFunction> object_ctor(
878 Isolate::Current()->global_context()->object_function());
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000879 CHECK(object_ctor->has_initial_map());
880 Handle<Map> object_map(object_ctor->initial_map());
881 // Create a map with single inobject property.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000882 Handle<Map> my_map = FACTORY->CopyMap(object_map, 1);
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000883 int n_properties = my_map->inobject_properties();
884 CHECK_GT(n_properties, 0);
885
886 int object_size = my_map->instance_size();
887
888 // Step 2: allocate a lot of objects so to almost fill new space: we need
889 // just enough room to allocate JSObject and thus fill the newspace.
890
891 int allocation_amount = Min(FixedArray::kMaxSize,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000892 HEAP->MaxObjectSizeInNewSpace());
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000893 int allocation_len = LenFromSize(allocation_amount);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000894 NewSpace* new_space = HEAP->new_space();
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000895 Address* top_addr = new_space->allocation_top_address();
896 Address* limit_addr = new_space->allocation_limit_address();
897 while ((*limit_addr - *top_addr) > allocation_amount) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000898 CHECK(!HEAP->always_allocate());
899 Object* array = HEAP->AllocateFixedArray(allocation_len)->ToObjectChecked();
900 CHECK(!array->IsFailure());
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000901 CHECK(new_space->Contains(array));
902 }
903
904 // Step 3: now allocate fixed array and JSObject to fill the whole new space.
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000905 int to_fill = static_cast<int>(*limit_addr - *top_addr - object_size);
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000906 int fixed_array_len = LenFromSize(to_fill);
907 CHECK(fixed_array_len < FixedArray::kMaxLength);
908
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000909 CHECK(!HEAP->always_allocate());
910 Object* array = HEAP->AllocateFixedArray(fixed_array_len)->ToObjectChecked();
911 CHECK(!array->IsFailure());
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000912 CHECK(new_space->Contains(array));
913
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000914 Object* object = HEAP->AllocateJSObjectFromMap(*my_map)->ToObjectChecked();
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000915 CHECK(new_space->Contains(object));
916 JSObject* jsobject = JSObject::cast(object);
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000917 CHECK_EQ(0, FixedArray::cast(jsobject->elements())->length());
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000918 CHECK_EQ(0, jsobject->properties()->length());
919 // Create a reference to object in new space in jsobject.
920 jsobject->FastPropertyAtPut(-1, array);
921
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000922 CHECK_EQ(0, static_cast<int>(*limit_addr - *top_addr));
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000923
924 // Step 4: clone jsobject, but force always allocate first to create a clone
925 // in old pointer space.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000926 Address old_pointer_space_top = HEAP->old_pointer_space()->top();
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000927 AlwaysAllocateScope aa_scope;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000928 Object* clone_obj = HEAP->CopyJSObject(jsobject)->ToObjectChecked();
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000929 JSObject* clone = JSObject::cast(clone_obj);
930 if (clone->address() != old_pointer_space_top) {
931 // Alas, got allocated from free list, we cannot do checks.
932 return;
933 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000934 CHECK(HEAP->old_pointer_space()->Contains(clone->address()));
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000935}
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000936
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000937
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000938TEST(TestCodeFlushing) {
939 i::FLAG_allow_natives_syntax = true;
ricow@chromium.orgfd0930e2010-06-11 10:37:34 +0000940 // If we do not flush code this test is invalid.
941 if (!FLAG_flush_code) return;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000942 InitializeVM();
943 v8::HandleScope scope;
944 const char* source = "function foo() {"
945 " var x = 42;"
946 " var y = 42;"
947 " var z = x + y;"
948 "};"
949 "foo()";
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000950 Handle<String> foo_name = FACTORY->LookupAsciiSymbol("foo");
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000951
952 // This compile will add the code to the compilation cache.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000953 { v8::HandleScope scope;
954 CompileRun(source);
955 }
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000956
957 // Check function is compiled.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000958 Object* func_value = Isolate::Current()->context()->global()->
959 GetProperty(*foo_name)->ToObjectChecked();
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000960 CHECK(func_value->IsJSFunction());
961 Handle<JSFunction> function(JSFunction::cast(func_value));
962 CHECK(function->shared()->is_compiled());
963
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000964 // TODO(1609) Currently incremental marker does not support code flushing.
965 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask);
966 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask);
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000967
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000968 CHECK(function->shared()->is_compiled());
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000969
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000970 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask);
971 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask);
972 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask);
973 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask);
974 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask);
975 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask);
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000976
977 // foo should no longer be in the compilation cache
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000978 CHECK(!function->shared()->is_compiled() || function->IsOptimized());
979 CHECK(!function->is_compiled() || function->IsOptimized());
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000980 // Call foo to get it recompiled.
981 CompileRun("foo()");
982 CHECK(function->shared()->is_compiled());
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000983 CHECK(function->is_compiled());
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000984}
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000985
986
987// Count the number of global contexts in the weak list of global contexts.
988static int CountGlobalContexts() {
989 int count = 0;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000990 Object* object = HEAP->global_contexts_list();
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000991 while (!object->IsUndefined()) {
992 count++;
993 object = Context::cast(object)->get(Context::NEXT_CONTEXT_LINK);
994 }
995 return count;
996}
997
998
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000999// Count the number of user functions in the weak list of optimized
1000// functions attached to a global context.
1001static int CountOptimizedUserFunctions(v8::Handle<v8::Context> context) {
1002 int count = 0;
1003 Handle<Context> icontext = v8::Utils::OpenHandle(*context);
1004 Object* object = icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST);
1005 while (object->IsJSFunction() && !JSFunction::cast(object)->IsBuiltin()) {
1006 count++;
1007 object = JSFunction::cast(object)->next_function_link();
1008 }
1009 return count;
1010}
1011
1012
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001013TEST(TestInternalWeakLists) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001014 v8::V8::Initialize();
1015
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001016 static const int kNumTestContexts = 10;
1017
1018 v8::HandleScope scope;
1019 v8::Persistent<v8::Context> ctx[kNumTestContexts];
1020
1021 CHECK_EQ(0, CountGlobalContexts());
1022
1023 // Create a number of global contests which gets linked together.
1024 for (int i = 0; i < kNumTestContexts; i++) {
1025 ctx[i] = v8::Context::New();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001026
1027 bool opt = (FLAG_always_opt && i::V8::UseCrankshaft());
1028
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001029 CHECK_EQ(i + 1, CountGlobalContexts());
1030
1031 ctx[i]->Enter();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001032
1033 // Create a handle scope so no function objects get stuch in the outer
1034 // handle scope
1035 v8::HandleScope scope;
1036 const char* source = "function f1() { };"
1037 "function f2() { };"
1038 "function f3() { };"
1039 "function f4() { };"
1040 "function f5() { };";
1041 CompileRun(source);
1042 CHECK_EQ(0, CountOptimizedUserFunctions(ctx[i]));
1043 CompileRun("f1()");
1044 CHECK_EQ(opt ? 1 : 0, CountOptimizedUserFunctions(ctx[i]));
1045 CompileRun("f2()");
1046 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i]));
1047 CompileRun("f3()");
1048 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i]));
1049 CompileRun("f4()");
1050 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i]));
1051 CompileRun("f5()");
1052 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i]));
1053
1054 // Remove function f1, and
1055 CompileRun("f1=null");
1056
1057 // Scavenge treats these references as strong.
1058 for (int j = 0; j < 10; j++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001059 HEAP->PerformScavenge();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001060 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i]));
1061 }
1062
1063 // Mark compact handles the weak references.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001064 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001065 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i]));
1066
1067 // Get rid of f3 and f5 in the same way.
1068 CompileRun("f3=null");
1069 for (int j = 0; j < 10; j++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001070 HEAP->PerformScavenge();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001071 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i]));
1072 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001073 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001074 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i]));
1075 CompileRun("f5=null");
1076 for (int j = 0; j < 10; j++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001077 HEAP->PerformScavenge();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001078 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i]));
1079 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001080 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001081 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i]));
1082
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001083 ctx[i]->Exit();
1084 }
1085
1086 // Force compilation cache cleanup.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001087 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001088
1089 // Dispose the global contexts one by one.
1090 for (int i = 0; i < kNumTestContexts; i++) {
1091 ctx[i].Dispose();
1092 ctx[i].Clear();
1093
1094 // Scavenge treats these references as strong.
1095 for (int j = 0; j < 10; j++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001096 HEAP->PerformScavenge();
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001097 CHECK_EQ(kNumTestContexts - i, CountGlobalContexts());
1098 }
1099
1100 // Mark compact handles the weak references.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001101 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001102 CHECK_EQ(kNumTestContexts - i - 1, CountGlobalContexts());
1103 }
1104
1105 CHECK_EQ(0, CountGlobalContexts());
1106}
1107
1108
1109// Count the number of global contexts in the weak list of global contexts
1110// causing a GC after the specified number of elements.
1111static int CountGlobalContextsWithGC(int n) {
1112 int count = 0;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001113 Handle<Object> object(HEAP->global_contexts_list());
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001114 while (!object->IsUndefined()) {
1115 count++;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001116 if (count == n) HEAP->CollectAllGarbage(Heap::kNoGCFlags);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001117 object =
1118 Handle<Object>(Context::cast(*object)->get(Context::NEXT_CONTEXT_LINK));
1119 }
1120 return count;
1121}
1122
1123
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001124// Count the number of user functions in the weak list of optimized
1125// functions attached to a global context causing a GC after the
1126// specified number of elements.
1127static int CountOptimizedUserFunctionsWithGC(v8::Handle<v8::Context> context,
1128 int n) {
1129 int count = 0;
1130 Handle<Context> icontext = v8::Utils::OpenHandle(*context);
1131 Handle<Object> object(icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST));
1132 while (object->IsJSFunction() &&
1133 !Handle<JSFunction>::cast(object)->IsBuiltin()) {
1134 count++;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001135 if (count == n) HEAP->CollectAllGarbage(Heap::kNoGCFlags);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001136 object = Handle<Object>(
1137 Object::cast(JSFunction::cast(*object)->next_function_link()));
1138 }
1139 return count;
1140}
1141
1142
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001143TEST(TestInternalWeakListsTraverseWithGC) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001144 v8::V8::Initialize();
1145
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001146 static const int kNumTestContexts = 10;
1147
1148 v8::HandleScope scope;
1149 v8::Persistent<v8::Context> ctx[kNumTestContexts];
1150
1151 CHECK_EQ(0, CountGlobalContexts());
1152
1153 // Create an number of contexts and check the length of the weak list both
1154 // with and without GCs while iterating the list.
1155 for (int i = 0; i < kNumTestContexts; i++) {
1156 ctx[i] = v8::Context::New();
1157 CHECK_EQ(i + 1, CountGlobalContexts());
1158 CHECK_EQ(i + 1, CountGlobalContextsWithGC(i / 2 + 1));
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001159 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001160
1161 bool opt = (FLAG_always_opt && i::V8::UseCrankshaft());
1162
1163 // Compile a number of functions the length of the weak list of optimized
1164 // functions both with and without GCs while iterating the list.
1165 ctx[0]->Enter();
1166 const char* source = "function f1() { };"
1167 "function f2() { };"
1168 "function f3() { };"
1169 "function f4() { };"
1170 "function f5() { };";
1171 CompileRun(source);
1172 CHECK_EQ(0, CountOptimizedUserFunctions(ctx[0]));
1173 CompileRun("f1()");
1174 CHECK_EQ(opt ? 1 : 0, CountOptimizedUserFunctions(ctx[0]));
1175 CHECK_EQ(opt ? 1 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 1));
1176 CompileRun("f2()");
1177 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[0]));
1178 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 1));
1179 CompileRun("f3()");
1180 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[0]));
1181 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 1));
1182 CompileRun("f4()");
1183 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[0]));
1184 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 2));
1185 CompileRun("f5()");
1186 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[0]));
1187 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 4));
1188
1189 ctx[0]->Exit();
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001190}
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +00001191
1192
1193TEST(TestSizeOfObjectsVsHeapIteratorPrecision) {
1194 InitializeVM();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001195 HEAP->EnsureHeapIsIterable();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001196 intptr_t size_of_objects_1 = HEAP->SizeOfObjects();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001197 HeapIterator iterator;
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +00001198 intptr_t size_of_objects_2 = 0;
1199 for (HeapObject* obj = iterator.next();
1200 obj != NULL;
1201 obj = iterator.next()) {
1202 size_of_objects_2 += obj->Size();
1203 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001204 // Delta must be within 5% of the larger result.
1205 // TODO(gc): Tighten this up by distinguishing between byte
1206 // arrays that are real and those that merely mark free space
1207 // on the heap.
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +00001208 if (size_of_objects_1 > size_of_objects_2) {
1209 intptr_t delta = size_of_objects_1 - size_of_objects_2;
1210 PrintF("Heap::SizeOfObjects: %" V8_PTR_PREFIX "d, "
1211 "Iterator: %" V8_PTR_PREFIX "d, "
1212 "delta: %" V8_PTR_PREFIX "d\n",
1213 size_of_objects_1, size_of_objects_2, delta);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001214 CHECK_GT(size_of_objects_1 / 20, delta);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +00001215 } else {
1216 intptr_t delta = size_of_objects_2 - size_of_objects_1;
1217 PrintF("Heap::SizeOfObjects: %" V8_PTR_PREFIX "d, "
1218 "Iterator: %" V8_PTR_PREFIX "d, "
1219 "delta: %" V8_PTR_PREFIX "d\n",
1220 size_of_objects_1, size_of_objects_2, delta);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001221 CHECK_GT(size_of_objects_2 / 20, delta);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +00001222 }
1223}
whesse@chromium.org023421e2010-12-21 12:19:12 +00001224
1225
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001226TEST(GrowAndShrinkNewSpace) {
1227 InitializeVM();
1228 NewSpace* new_space = HEAP->new_space();
1229
1230 // Explicitly growing should double the space capacity.
1231 intptr_t old_capacity, new_capacity;
1232 old_capacity = new_space->Capacity();
1233 new_space->Grow();
1234 new_capacity = new_space->Capacity();
1235 CHECK(2 * old_capacity == new_capacity);
1236
1237 // Fill up new space to the point that it is completely full. Make sure
1238 // that the scavenger does not undo the filling.
1239 old_capacity = new_space->Capacity();
1240 {
1241 v8::HandleScope scope;
1242 AlwaysAllocateScope always_allocate;
1243 intptr_t available = new_space->EffectiveCapacity() - new_space->Size();
1244 intptr_t number_of_fillers = (available / FixedArray::SizeFor(1000)) - 10;
1245 for (intptr_t i = 0; i < number_of_fillers; i++) {
1246 CHECK(HEAP->InNewSpace(*FACTORY->NewFixedArray(1000, NOT_TENURED)));
whesse@chromium.org023421e2010-12-21 12:19:12 +00001247 }
1248 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001249 new_capacity = new_space->Capacity();
1250 CHECK(old_capacity == new_capacity);
whesse@chromium.org023421e2010-12-21 12:19:12 +00001251
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001252 // Explicitly shrinking should not affect space capacity.
1253 old_capacity = new_space->Capacity();
1254 new_space->Shrink();
1255 new_capacity = new_space->Capacity();
1256 CHECK(old_capacity == new_capacity);
1257
1258 // Let the scavenger empty the new space.
1259 HEAP->CollectGarbage(NEW_SPACE);
1260 CHECK_LE(new_space->Size(), old_capacity);
1261
1262 // Explicitly shrinking should halve the space capacity.
1263 old_capacity = new_space->Capacity();
1264 new_space->Shrink();
1265 new_capacity = new_space->Capacity();
1266 CHECK(old_capacity == 2 * new_capacity);
1267
1268 // Consecutive shrinking should not affect space capacity.
1269 old_capacity = new_space->Capacity();
1270 new_space->Shrink();
1271 new_space->Shrink();
1272 new_space->Shrink();
1273 new_capacity = new_space->Capacity();
1274 CHECK(old_capacity == new_capacity);
whesse@chromium.org023421e2010-12-21 12:19:12 +00001275}