blob: 2bb3af624dbedf8909c38ca247d0150683fe7174 [file] [log] [blame]
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001// Copyright 2012 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
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00007#include "compilation-cache.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008#include "execution.h"
9#include "factory.h"
10#include "macro-assembler.h"
11#include "global-handles.h"
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000012#include "stub-cache.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013#include "cctest.h"
14
15using namespace v8::internal;
16
17static v8::Persistent<v8::Context> env;
18
19static void InitializeVM() {
20 if (env.IsEmpty()) env = v8::Context::New();
21 v8::HandleScope scope;
22 env->Enter();
23}
24
25
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000026// Go through all incremental marking steps in one swoop.
27static void SimulateIncrementalMarking() {
28 IncrementalMarking* marking = HEAP->incremental_marking();
29 CHECK(marking->IsStopped());
30 marking->Start();
31 CHECK(marking->IsMarking());
32 while (!marking->IsComplete()) {
33 marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
34 }
35 CHECK(marking->IsComplete());
36}
37
38
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000039static void CheckMap(Map* map, int type, int instance_size) {
40 CHECK(map->IsHeapObject());
41#ifdef DEBUG
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000042 CHECK(HEAP->Contains(map));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000043#endif
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000044 CHECK_EQ(HEAP->meta_map(), map->map());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000045 CHECK_EQ(type, map->instance_type());
46 CHECK_EQ(instance_size, map->instance_size());
47}
48
49
50TEST(HeapMaps) {
51 InitializeVM();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000052 CheckMap(HEAP->meta_map(), MAP_TYPE, Map::kSize);
53 CheckMap(HEAP->heap_number_map(), HEAP_NUMBER_TYPE, HeapNumber::kSize);
54 CheckMap(HEAP->fixed_array_map(), FIXED_ARRAY_TYPE, kVariableSizeSentinel);
55 CheckMap(HEAP->string_map(), STRING_TYPE, kVariableSizeSentinel);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000056}
57
58
59static void CheckOddball(Object* obj, const char* string) {
60 CHECK(obj->IsOddball());
61 bool exc;
62 Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
63 CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
64}
65
66
67static void CheckSmi(int value, const char* string) {
68 bool exc;
69 Object* print_string =
70 *Execution::ToString(Handle<Object>(Smi::FromInt(value)), &exc);
71 CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
72}
73
74
75static void CheckNumber(double value, const char* string) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000076 Object* obj = HEAP->NumberFromDouble(value)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000077 CHECK(obj->IsNumber());
78 bool exc;
79 Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
80 CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
81}
82
83
84static void CheckFindCodeObject() {
85 // Test FindCodeObject
86#define __ assm.
87
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000088 Assembler assm(Isolate::Current(), NULL, 0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000089
90 __ nop(); // supported on all architectures
91
92 CodeDesc desc;
93 assm.GetCode(&desc);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000094 Object* code = HEAP->CreateCode(
lrn@chromium.org303ada72010-10-27 09:33:13 +000095 desc,
96 Code::ComputeFlags(Code::STUB),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000097 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000098 CHECK(code->IsCode());
99
100 HeapObject* obj = HeapObject::cast(code);
101 Address obj_addr = obj->address();
102
103 for (int i = 0; i < obj->Size(); i += kPointerSize) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000104 Object* found = HEAP->FindCodeObject(obj_addr + i);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000105 CHECK_EQ(code, found);
106 }
107
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000108 Object* copy = HEAP->CreateCode(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000109 desc,
110 Code::ComputeFlags(Code::STUB),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000111 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000112 CHECK(copy->IsCode());
113 HeapObject* obj_copy = HeapObject::cast(copy);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000114 Object* not_right = HEAP->FindCodeObject(obj_copy->address() +
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000115 obj_copy->Size() / 2);
116 CHECK(not_right != code);
117}
118
119
120TEST(HeapObjects) {
121 InitializeVM();
122
123 v8::HandleScope sc;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000124 Object* value = HEAP->NumberFromDouble(1.000123)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000125 CHECK(value->IsHeapNumber());
126 CHECK(value->IsNumber());
127 CHECK_EQ(1.000123, value->Number());
128
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000129 value = HEAP->NumberFromDouble(1.0)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000130 CHECK(value->IsSmi());
131 CHECK(value->IsNumber());
132 CHECK_EQ(1.0, value->Number());
133
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000134 value = HEAP->NumberFromInt32(1024)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000135 CHECK(value->IsSmi());
136 CHECK(value->IsNumber());
137 CHECK_EQ(1024.0, value->Number());
138
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000139 value = HEAP->NumberFromInt32(Smi::kMinValue)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000140 CHECK(value->IsSmi());
141 CHECK(value->IsNumber());
142 CHECK_EQ(Smi::kMinValue, Smi::cast(value)->value());
143
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000144 value = HEAP->NumberFromInt32(Smi::kMaxValue)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000145 CHECK(value->IsSmi());
146 CHECK(value->IsNumber());
147 CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value());
148
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000149#ifndef V8_TARGET_ARCH_X64
150 // TODO(lrn): We need a NumberFromIntptr function in order to test this.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000151 value = HEAP->NumberFromInt32(Smi::kMinValue - 1)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000152 CHECK(value->IsHeapNumber());
153 CHECK(value->IsNumber());
154 CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000155#endif
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000156
lrn@chromium.org303ada72010-10-27 09:33:13 +0000157 MaybeObject* maybe_value =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000158 HEAP->NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000159 value = maybe_value->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000160 CHECK(value->IsHeapNumber());
161 CHECK(value->IsNumber());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000162 CHECK_EQ(static_cast<double>(static_cast<uint32_t>(Smi::kMaxValue) + 1),
163 value->Number());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000164
165 // nan oddball checks
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000166 CHECK(HEAP->nan_value()->IsNumber());
167 CHECK(isnan(HEAP->nan_value()->Number()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000168
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000169 Handle<String> s = FACTORY->NewStringFromAscii(CStrVector("fisk hest "));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000170 CHECK(s->IsString());
171 CHECK_EQ(10, s->length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000172
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000173 String* object_symbol = String::cast(HEAP->Object_symbol());
174 CHECK(
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000175 Isolate::Current()->context()->global_object()->HasLocalProperty(
176 object_symbol));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000177
178 // Check ToString for oddballs
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000179 CheckOddball(HEAP->true_value(), "true");
180 CheckOddball(HEAP->false_value(), "false");
181 CheckOddball(HEAP->null_value(), "null");
182 CheckOddball(HEAP->undefined_value(), "undefined");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000183
184 // Check ToString for Smis
185 CheckSmi(0, "0");
186 CheckSmi(42, "42");
187 CheckSmi(-42, "-42");
188
189 // Check ToString for Numbers
190 CheckNumber(1.1, "1.1");
191
192 CheckFindCodeObject();
193}
194
195
196TEST(Tagging) {
197 InitializeVM();
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000198 int request = 24;
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000199 CHECK_EQ(request, static_cast<int>(OBJECT_POINTER_ALIGN(request)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000200 CHECK(Smi::FromInt(42)->IsSmi());
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000201 CHECK(Failure::RetryAfterGC(NEW_SPACE)->IsFailure());
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000202 CHECK_EQ(NEW_SPACE,
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000203 Failure::RetryAfterGC(NEW_SPACE)->allocation_space());
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000204 CHECK_EQ(OLD_POINTER_SPACE,
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000205 Failure::RetryAfterGC(OLD_POINTER_SPACE)->allocation_space());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000206 CHECK(Failure::Exception()->IsFailure());
207 CHECK(Smi::FromInt(Smi::kMinValue)->IsSmi());
208 CHECK(Smi::FromInt(Smi::kMaxValue)->IsSmi());
209}
210
211
212TEST(GarbageCollection) {
213 InitializeVM();
214
215 v8::HandleScope sc;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000216 // Check GC.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000217 HEAP->CollectGarbage(NEW_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000218
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000219 Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction");
220 Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot");
221 Handle<String> prop_namex = FACTORY->LookupAsciiSymbol("theSlotx");
222 Handle<String> obj_name = FACTORY->LookupAsciiSymbol("theObject");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000223
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000224 {
225 v8::HandleScope inner_scope;
226 // Allocate a function and keep it in global object's property.
227 Handle<JSFunction> function =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000228 FACTORY->NewFunction(name, FACTORY->undefined_value());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000229 Handle<Map> initial_map =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000230 FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000231 function->set_initial_map(*initial_map);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000232 Isolate::Current()->context()->global_object()->SetProperty(
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000233 *name, *function, NONE, kNonStrictMode)->ToObjectChecked();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000234 // Allocate an object. Unrooted after leaving the scope.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000235 Handle<JSObject> obj = FACTORY->NewJSObject(function);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000236 obj->SetProperty(
237 *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
238 obj->SetProperty(
239 *prop_namex, Smi::FromInt(24), NONE, kNonStrictMode)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000240
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000241 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
242 CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex));
243 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000244
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000245 HEAP->CollectGarbage(NEW_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000246
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000247 // Function should be alive.
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000248 CHECK(Isolate::Current()->context()->global_object()->
249 HasLocalProperty(*name));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000250 // Check function is retained.
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000251 Object* func_value = Isolate::Current()->context()->global_object()->
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000252 GetProperty(*name)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000253 CHECK(func_value->IsJSFunction());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000254 Handle<JSFunction> function(JSFunction::cast(func_value));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000255
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000256 {
257 HandleScope inner_scope;
258 // Allocate another object, make it reachable from global.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000259 Handle<JSObject> obj = FACTORY->NewJSObject(function);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000260 Isolate::Current()->context()->global_object()->SetProperty(
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000261 *obj_name, *obj, NONE, kNonStrictMode)->ToObjectChecked();
262 obj->SetProperty(
263 *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000264 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000265
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000266 // After gc, it should survive.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000267 HEAP->CollectGarbage(NEW_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000268
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000269 CHECK(Isolate::Current()->context()->global_object()->
270 HasLocalProperty(*obj_name));
271 CHECK(Isolate::Current()->context()->global_object()->
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000272 GetProperty(*obj_name)->ToObjectChecked()->IsJSObject());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000273 Object* obj = Isolate::Current()->context()->global_object()->
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000274 GetProperty(*obj_name)->ToObjectChecked();
lrn@chromium.org303ada72010-10-27 09:33:13 +0000275 JSObject* js_obj = JSObject::cast(obj);
276 CHECK_EQ(Smi::FromInt(23), js_obj->GetProperty(*prop_name));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000277}
278
279
280static void VerifyStringAllocation(const char* string) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000281 v8::HandleScope scope;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000282 Handle<String> s = FACTORY->NewStringFromUtf8(CStrVector(string));
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000283 CHECK_EQ(StrLength(string), s->length());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000284 for (int index = 0; index < s->length(); index++) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000285 CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(index));
286 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000287}
288
289
290TEST(String) {
291 InitializeVM();
292
293 VerifyStringAllocation("a");
294 VerifyStringAllocation("ab");
295 VerifyStringAllocation("abc");
296 VerifyStringAllocation("abcd");
297 VerifyStringAllocation("fiskerdrengen er paa havet");
298}
299
300
301TEST(LocalHandles) {
302 InitializeVM();
303
304 v8::HandleScope scope;
305 const char* name = "Kasper the spunky";
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000306 Handle<String> string = FACTORY->NewStringFromAscii(CStrVector(name));
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000307 CHECK_EQ(StrLength(name), string->length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000308}
309
310
311TEST(GlobalHandles) {
312 InitializeVM();
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000313 GlobalHandles* global_handles = Isolate::Current()->global_handles();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000314
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000315 Handle<Object> h1;
316 Handle<Object> h2;
317 Handle<Object> h3;
318 Handle<Object> h4;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000319
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000320 {
321 HandleScope scope;
322
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000323 Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk"));
324 Handle<Object> u = FACTORY->NewNumber(1.12344);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000325
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000326 h1 = global_handles->Create(*i);
327 h2 = global_handles->Create(*u);
328 h3 = global_handles->Create(*i);
329 h4 = global_handles->Create(*u);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000330 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000331
332 // after gc, it should survive
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000333 HEAP->CollectGarbage(NEW_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000334
335 CHECK((*h1)->IsString());
336 CHECK((*h2)->IsHeapNumber());
337 CHECK((*h3)->IsString());
338 CHECK((*h4)->IsHeapNumber());
339
340 CHECK_EQ(*h3, *h1);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000341 global_handles->Destroy(h1.location());
342 global_handles->Destroy(h3.location());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000343
344 CHECK_EQ(*h4, *h2);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000345 global_handles->Destroy(h2.location());
346 global_handles->Destroy(h4.location());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000347}
348
349
350static bool WeakPointerCleared = false;
351
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000352static void TestWeakGlobalHandleCallback(v8::Persistent<v8::Value> handle,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000353 void* id) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000354 if (1234 == reinterpret_cast<intptr_t>(id)) WeakPointerCleared = true;
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000355 handle.Dispose();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000356}
357
358
359TEST(WeakGlobalHandlesScavenge) {
360 InitializeVM();
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000361 GlobalHandles* global_handles = Isolate::Current()->global_handles();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000362
363 WeakPointerCleared = false;
364
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000365 Handle<Object> h1;
366 Handle<Object> h2;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000367
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000368 {
369 HandleScope scope;
370
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000371 Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk"));
372 Handle<Object> u = FACTORY->NewNumber(1.12344);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000373
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000374 h1 = global_handles->Create(*i);
375 h2 = global_handles->Create(*u);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000376 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000377
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000378 global_handles->MakeWeak(h2.location(),
379 reinterpret_cast<void*>(1234),
380 &TestWeakGlobalHandleCallback);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000381
382 // Scavenge treats weak pointers as normal roots.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000383 HEAP->PerformScavenge();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000384
385 CHECK((*h1)->IsString());
386 CHECK((*h2)->IsHeapNumber());
387
388 CHECK(!WeakPointerCleared);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000389 CHECK(!global_handles->IsNearDeath(h2.location()));
390 CHECK(!global_handles->IsNearDeath(h1.location()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000391
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000392 global_handles->Destroy(h1.location());
393 global_handles->Destroy(h2.location());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000394}
395
396
397TEST(WeakGlobalHandlesMark) {
398 InitializeVM();
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000399 GlobalHandles* global_handles = Isolate::Current()->global_handles();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000400
401 WeakPointerCleared = false;
402
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000403 Handle<Object> h1;
404 Handle<Object> h2;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000405
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000406 {
407 HandleScope scope;
408
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000409 Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk"));
410 Handle<Object> u = FACTORY->NewNumber(1.12344);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000411
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000412 h1 = global_handles->Create(*i);
413 h2 = global_handles->Create(*u);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000414 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000415
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000416 HEAP->CollectGarbage(OLD_POINTER_SPACE);
417 HEAP->CollectGarbage(NEW_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000418 // Make sure the object is promoted.
419
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000420 global_handles->MakeWeak(h2.location(),
421 reinterpret_cast<void*>(1234),
422 &TestWeakGlobalHandleCallback);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000423 CHECK(!GlobalHandles::IsNearDeath(h1.location()));
424 CHECK(!GlobalHandles::IsNearDeath(h2.location()));
425
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000426 HEAP->CollectGarbage(OLD_POINTER_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000427
428 CHECK((*h1)->IsString());
429
430 CHECK(WeakPointerCleared);
431 CHECK(!GlobalHandles::IsNearDeath(h1.location()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000432
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000433 global_handles->Destroy(h1.location());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000434}
435
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000436
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000437TEST(DeleteWeakGlobalHandle) {
438 InitializeVM();
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000439 GlobalHandles* global_handles = Isolate::Current()->global_handles();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000440
441 WeakPointerCleared = false;
442
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000443 Handle<Object> h;
444
445 {
446 HandleScope scope;
447
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000448 Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk"));
449 h = global_handles->Create(*i);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000450 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000451
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000452 global_handles->MakeWeak(h.location(),
453 reinterpret_cast<void*>(1234),
454 &TestWeakGlobalHandleCallback);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000455
456 // Scanvenge does not recognize weak reference.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000457 HEAP->PerformScavenge();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000458
459 CHECK(!WeakPointerCleared);
460
461 // Mark-compact treats weak reference properly.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000462 HEAP->CollectGarbage(OLD_POINTER_SPACE);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000463
464 CHECK(WeakPointerCleared);
465}
466
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000467
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000468static const char* not_so_random_string_table[] = {
469 "abstract",
470 "boolean",
471 "break",
472 "byte",
473 "case",
474 "catch",
475 "char",
476 "class",
477 "const",
478 "continue",
479 "debugger",
480 "default",
481 "delete",
482 "do",
483 "double",
484 "else",
485 "enum",
486 "export",
487 "extends",
488 "false",
489 "final",
490 "finally",
491 "float",
492 "for",
493 "function",
494 "goto",
495 "if",
496 "implements",
497 "import",
498 "in",
499 "instanceof",
500 "int",
501 "interface",
502 "long",
503 "native",
504 "new",
505 "null",
506 "package",
507 "private",
508 "protected",
509 "public",
510 "return",
511 "short",
512 "static",
513 "super",
514 "switch",
515 "synchronized",
516 "this",
517 "throw",
518 "throws",
519 "transient",
520 "true",
521 "try",
522 "typeof",
523 "var",
524 "void",
525 "volatile",
526 "while",
527 "with",
528 0
529};
530
531
532static void CheckSymbols(const char** strings) {
533 for (const char* string = *strings; *strings != 0; string = *strings++) {
lrn@chromium.org303ada72010-10-27 09:33:13 +0000534 Object* a;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000535 MaybeObject* maybe_a = HEAP->LookupAsciiSymbol(string);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000536 // LookupAsciiSymbol may return a failure if a GC is needed.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000537 if (!maybe_a->ToObject(&a)) continue;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000538 CHECK(a->IsSymbol());
lrn@chromium.org303ada72010-10-27 09:33:13 +0000539 Object* b;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000540 MaybeObject* maybe_b = HEAP->LookupAsciiSymbol(string);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000541 if (!maybe_b->ToObject(&b)) continue;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000542 CHECK_EQ(b, a);
543 CHECK(String::cast(b)->IsEqualTo(CStrVector(string)));
544 }
545}
546
547
548TEST(SymbolTable) {
549 InitializeVM();
550
551 CheckSymbols(not_so_random_string_table);
552 CheckSymbols(not_so_random_string_table);
553}
554
555
556TEST(FunctionAllocation) {
557 InitializeVM();
558
559 v8::HandleScope sc;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000560 Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction");
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000561 Handle<JSFunction> function =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000562 FACTORY->NewFunction(name, FACTORY->undefined_value());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000563 Handle<Map> initial_map =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000564 FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000565 function->set_initial_map(*initial_map);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000566
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000567 Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot");
568 Handle<JSObject> obj = FACTORY->NewJSObject(function);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000569 obj->SetProperty(
570 *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000571 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000572 // Check that we can add properties to function objects.
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000573 function->SetProperty(
574 *prop_name, Smi::FromInt(24), NONE, kNonStrictMode)->ToObjectChecked();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000575 CHECK_EQ(Smi::FromInt(24), function->GetProperty(*prop_name));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000576}
577
578
579TEST(ObjectProperties) {
580 InitializeVM();
581
582 v8::HandleScope sc;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000583 String* object_symbol = String::cast(HEAP->Object_symbol());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000584 Object* raw_object = Isolate::Current()->context()->global_object()->
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000585 GetProperty(object_symbol)->ToObjectChecked();
lrn@chromium.org303ada72010-10-27 09:33:13 +0000586 JSFunction* object_function = JSFunction::cast(raw_object);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000587 Handle<JSFunction> constructor(object_function);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000588 Handle<JSObject> obj = FACTORY->NewJSObject(constructor);
589 Handle<String> first = FACTORY->LookupAsciiSymbol("first");
590 Handle<String> second = FACTORY->LookupAsciiSymbol("second");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000591
592 // check for empty
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000593 CHECK(!obj->HasLocalProperty(*first));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000594
595 // add first
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000596 obj->SetProperty(
597 *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000598 CHECK(obj->HasLocalProperty(*first));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000599
600 // delete first
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000601 CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION));
602 CHECK(!obj->HasLocalProperty(*first));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000603
604 // add first and then second
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000605 obj->SetProperty(
606 *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
607 obj->SetProperty(
608 *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000609 CHECK(obj->HasLocalProperty(*first));
610 CHECK(obj->HasLocalProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000611
612 // delete first and then second
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000613 CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION));
614 CHECK(obj->HasLocalProperty(*second));
615 CHECK(obj->DeleteProperty(*second, JSObject::NORMAL_DELETION));
616 CHECK(!obj->HasLocalProperty(*first));
617 CHECK(!obj->HasLocalProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000618
619 // add first and then second
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000620 obj->SetProperty(
621 *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
622 obj->SetProperty(
623 *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000624 CHECK(obj->HasLocalProperty(*first));
625 CHECK(obj->HasLocalProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000626
627 // delete second and then first
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000628 CHECK(obj->DeleteProperty(*second, JSObject::NORMAL_DELETION));
629 CHECK(obj->HasLocalProperty(*first));
630 CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION));
631 CHECK(!obj->HasLocalProperty(*first));
632 CHECK(!obj->HasLocalProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000633
634 // check string and symbol match
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000635 const char* string1 = "fisk";
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000636 Handle<String> s1 = FACTORY->NewStringFromAscii(CStrVector(string1));
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000637 obj->SetProperty(
638 *s1, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000639 Handle<String> s1_symbol = FACTORY->LookupAsciiSymbol(string1);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000640 CHECK(obj->HasLocalProperty(*s1_symbol));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000641
642 // check symbol and string match
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000643 const char* string2 = "fugl";
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000644 Handle<String> s2_symbol = FACTORY->LookupAsciiSymbol(string2);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000645 obj->SetProperty(
646 *s2_symbol, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000647 Handle<String> s2 = FACTORY->NewStringFromAscii(CStrVector(string2));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000648 CHECK(obj->HasLocalProperty(*s2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000649}
650
651
652TEST(JSObjectMaps) {
653 InitializeVM();
654
655 v8::HandleScope sc;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000656 Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction");
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000657 Handle<JSFunction> function =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000658 FACTORY->NewFunction(name, FACTORY->undefined_value());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000659 Handle<Map> initial_map =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000660 FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000661 function->set_initial_map(*initial_map);
662
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000663 Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot");
664 Handle<JSObject> obj = FACTORY->NewJSObject(function);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000665
666 // Set a propery
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000667 obj->SetProperty(
668 *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000669 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000670
671 // Check the map has changed
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000672 CHECK(*initial_map != obj->map());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000673}
674
675
676TEST(JSArray) {
677 InitializeVM();
678
679 v8::HandleScope sc;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000680 Handle<String> name = FACTORY->LookupAsciiSymbol("Array");
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000681 Object* raw_object = Isolate::Current()->context()->global_object()->
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000682 GetProperty(*name)->ToObjectChecked();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000683 Handle<JSFunction> function = Handle<JSFunction>(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000684 JSFunction::cast(raw_object));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000685
686 // Allocate the object.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000687 Handle<JSObject> object = FACTORY->NewJSObject(function);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000688 Handle<JSArray> array = Handle<JSArray>::cast(object);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000689 // We just initialized the VM, no heap allocation failure yet.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000690 array->Initialize(0)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000691
692 // Set array length to 0.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000693 array->SetElementsLength(Smi::FromInt(0))->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000694 CHECK_EQ(Smi::FromInt(0), array->length());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000695 // Must be in fast mode.
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +0000696 CHECK(array->HasFastSmiOrObjectElements());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000697
698 // array[length] = name.
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +0000699 array->SetElement(0, *name, NONE, kNonStrictMode)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000700 CHECK_EQ(Smi::FromInt(1), array->length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000701 CHECK_EQ(array->GetElement(0), *name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000702
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000703 // Set array length with larger than smi value.
704 Handle<Object> length =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000705 FACTORY->NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000706 array->SetElementsLength(*length)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000707
708 uint32_t int_length = 0;
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000709 CHECK(length->ToArrayIndex(&int_length));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000710 CHECK_EQ(*length, array->length());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000711 CHECK(array->HasDictionaryElements()); // Must be in slow mode.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000712
713 // array[length] = name.
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +0000714 array->SetElement(int_length, *name, NONE, kNonStrictMode)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000715 uint32_t new_int_length = 0;
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000716 CHECK(array->length()->ToArrayIndex(&new_int_length));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000717 CHECK_EQ(static_cast<double>(int_length), new_int_length - 1);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000718 CHECK_EQ(array->GetElement(int_length), *name);
719 CHECK_EQ(array->GetElement(0), *name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000720}
721
722
723TEST(JSObjectCopy) {
724 InitializeVM();
725
726 v8::HandleScope sc;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000727 String* object_symbol = String::cast(HEAP->Object_symbol());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000728 Object* raw_object = Isolate::Current()->context()->global_object()->
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000729 GetProperty(object_symbol)->ToObjectChecked();
lrn@chromium.org303ada72010-10-27 09:33:13 +0000730 JSFunction* object_function = JSFunction::cast(raw_object);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000731 Handle<JSFunction> constructor(object_function);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000732 Handle<JSObject> obj = FACTORY->NewJSObject(constructor);
733 Handle<String> first = FACTORY->LookupAsciiSymbol("first");
734 Handle<String> second = FACTORY->LookupAsciiSymbol("second");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000735
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000736 obj->SetProperty(
737 *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
738 obj->SetProperty(
739 *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000740
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +0000741 obj->SetElement(0, *first, NONE, kNonStrictMode)->ToObjectChecked();
742 obj->SetElement(1, *second, NONE, kNonStrictMode)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000743
744 // Make the clone.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000745 Handle<JSObject> clone = Copy(obj);
746 CHECK(!clone.is_identical_to(obj));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000747
748 CHECK_EQ(obj->GetElement(0), clone->GetElement(0));
749 CHECK_EQ(obj->GetElement(1), clone->GetElement(1));
750
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000751 CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*first));
752 CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000753
754 // Flip the values.
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000755 clone->SetProperty(
756 *first, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
757 clone->SetProperty(
758 *second, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000759
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +0000760 clone->SetElement(0, *second, NONE, kNonStrictMode)->ToObjectChecked();
761 clone->SetElement(1, *first, NONE, kNonStrictMode)->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000762
763 CHECK_EQ(obj->GetElement(1), clone->GetElement(0));
764 CHECK_EQ(obj->GetElement(0), clone->GetElement(1));
765
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000766 CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*first));
767 CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*second));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000768}
769
770
771TEST(StringAllocation) {
772 InitializeVM();
773
774
775 const unsigned char chars[] = { 0xe5, 0xa4, 0xa7 };
776 for (int length = 0; length < 100; length++) {
777 v8::HandleScope scope;
778 char* non_ascii = NewArray<char>(3 * length + 1);
779 char* ascii = NewArray<char>(length + 1);
780 non_ascii[3 * length] = 0;
781 ascii[length] = 0;
782 for (int i = 0; i < length; i++) {
783 ascii[i] = 'a';
784 non_ascii[3 * i] = chars[0];
785 non_ascii[3 * i + 1] = chars[1];
786 non_ascii[3 * i + 2] = chars[2];
787 }
788 Handle<String> non_ascii_sym =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000789 FACTORY->LookupSymbol(Vector<const char>(non_ascii, 3 * length));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000790 CHECK_EQ(length, non_ascii_sym->length());
791 Handle<String> ascii_sym =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000792 FACTORY->LookupSymbol(Vector<const char>(ascii, length));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000793 CHECK_EQ(length, ascii_sym->length());
794 Handle<String> non_ascii_str =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000795 FACTORY->NewStringFromUtf8(Vector<const char>(non_ascii, 3 * length));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000796 non_ascii_str->Hash();
797 CHECK_EQ(length, non_ascii_str->length());
798 Handle<String> ascii_str =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000799 FACTORY->NewStringFromUtf8(Vector<const char>(ascii, length));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000800 ascii_str->Hash();
801 CHECK_EQ(length, ascii_str->length());
802 DeleteArray(non_ascii);
803 DeleteArray(ascii);
804 }
805}
806
807
808static int ObjectsFoundInHeap(Handle<Object> objs[], int size) {
809 // Count the number of objects found in the heap.
810 int found_count = 0;
811 HeapIterator iterator;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000812 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000813 for (int i = 0; i < size; i++) {
814 if (*objs[i] == obj) {
815 found_count++;
816 }
817 }
818 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000819 return found_count;
820}
821
822
823TEST(Iteration) {
824 InitializeVM();
825 v8::HandleScope scope;
826
827 // Array of objects to scan haep for.
828 const int objs_count = 6;
829 Handle<Object> objs[objs_count];
830 int next_objs_index = 0;
831
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000832 // Allocate a JS array to OLD_POINTER_SPACE and NEW_SPACE
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000833 objs[next_objs_index++] = FACTORY->NewJSArray(10);
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +0000834 objs[next_objs_index++] = FACTORY->NewJSArray(10,
835 FAST_HOLEY_ELEMENTS,
836 TENURED);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000837
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000838 // Allocate a small string to OLD_DATA_SPACE and NEW_SPACE
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000839 objs[next_objs_index++] =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000840 FACTORY->NewStringFromAscii(CStrVector("abcdefghij"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000841 objs[next_objs_index++] =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000842 FACTORY->NewStringFromAscii(CStrVector("abcdefghij"), TENURED);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000843
844 // Allocate a large string (for large object space).
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +0000845 int large_size = Page::kMaxNonCodeHeapObjectSize + 1;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000846 char* str = new char[large_size];
847 for (int i = 0; i < large_size - 1; ++i) str[i] = 'a';
848 str[large_size - 1] = '\0';
849 objs[next_objs_index++] =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000850 FACTORY->NewStringFromAscii(CStrVector(str), TENURED);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000851 delete[] str;
852
853 // Add a Map object to look for.
854 objs[next_objs_index++] = Handle<Map>(HeapObject::cast(*objs[0])->map());
855
856 CHECK_EQ(objs_count, next_objs_index);
857 CHECK_EQ(objs_count, ObjectsFoundInHeap(objs, objs_count));
858}
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000859
860
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000861TEST(EmptyHandleEscapeFrom) {
862 InitializeVM();
863
864 v8::HandleScope scope;
865 Handle<JSObject> runaway;
866
867 {
868 v8::HandleScope nested;
869 Handle<JSObject> empty;
870 runaway = empty.EscapeFrom(&nested);
871 }
872
873 CHECK(runaway.is_null());
874}
875
876
877static int LenFromSize(int size) {
878 return (size - FixedArray::kHeaderSize) / kPointerSize;
879}
880
881
882TEST(Regression39128) {
883 // Test case for crbug.com/39128.
884 InitializeVM();
885
886 // Increase the chance of 'bump-the-pointer' allocation in old space.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000887 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000888
889 v8::HandleScope scope;
890
891 // The plan: create JSObject which references objects in new space.
892 // Then clone this object (forcing it to go into old space) and check
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000893 // that region dirty marks are updated correctly.
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000894
895 // Step 1: prepare a map for the object. We add 1 inobject property to it.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000896 Handle<JSFunction> object_ctor(
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000897 Isolate::Current()->native_context()->object_function());
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000898 CHECK(object_ctor->has_initial_map());
899 Handle<Map> object_map(object_ctor->initial_map());
900 // Create a map with single inobject property.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000901 Handle<Map> my_map = FACTORY->CopyMap(object_map, 1);
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000902 int n_properties = my_map->inobject_properties();
903 CHECK_GT(n_properties, 0);
904
905 int object_size = my_map->instance_size();
906
907 // Step 2: allocate a lot of objects so to almost fill new space: we need
908 // just enough room to allocate JSObject and thus fill the newspace.
909
910 int allocation_amount = Min(FixedArray::kMaxSize,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000911 HEAP->MaxObjectSizeInNewSpace());
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000912 int allocation_len = LenFromSize(allocation_amount);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000913 NewSpace* new_space = HEAP->new_space();
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000914 Address* top_addr = new_space->allocation_top_address();
915 Address* limit_addr = new_space->allocation_limit_address();
916 while ((*limit_addr - *top_addr) > allocation_amount) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000917 CHECK(!HEAP->always_allocate());
918 Object* array = HEAP->AllocateFixedArray(allocation_len)->ToObjectChecked();
919 CHECK(!array->IsFailure());
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000920 CHECK(new_space->Contains(array));
921 }
922
923 // Step 3: now allocate fixed array and JSObject to fill the whole new space.
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000924 int to_fill = static_cast<int>(*limit_addr - *top_addr - object_size);
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000925 int fixed_array_len = LenFromSize(to_fill);
926 CHECK(fixed_array_len < FixedArray::kMaxLength);
927
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000928 CHECK(!HEAP->always_allocate());
929 Object* array = HEAP->AllocateFixedArray(fixed_array_len)->ToObjectChecked();
930 CHECK(!array->IsFailure());
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000931 CHECK(new_space->Contains(array));
932
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000933 Object* object = HEAP->AllocateJSObjectFromMap(*my_map)->ToObjectChecked();
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000934 CHECK(new_space->Contains(object));
935 JSObject* jsobject = JSObject::cast(object);
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000936 CHECK_EQ(0, FixedArray::cast(jsobject->elements())->length());
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000937 CHECK_EQ(0, jsobject->properties()->length());
938 // Create a reference to object in new space in jsobject.
939 jsobject->FastPropertyAtPut(-1, array);
940
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000941 CHECK_EQ(0, static_cast<int>(*limit_addr - *top_addr));
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000942
943 // Step 4: clone jsobject, but force always allocate first to create a clone
944 // in old pointer space.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000945 Address old_pointer_space_top = HEAP->old_pointer_space()->top();
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000946 AlwaysAllocateScope aa_scope;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000947 Object* clone_obj = HEAP->CopyJSObject(jsobject)->ToObjectChecked();
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000948 JSObject* clone = JSObject::cast(clone_obj);
949 if (clone->address() != old_pointer_space_top) {
950 // Alas, got allocated from free list, we cannot do checks.
951 return;
952 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000953 CHECK(HEAP->old_pointer_space()->Contains(clone->address()));
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000954}
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000955
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000956
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000957TEST(TestCodeFlushing) {
ricow@chromium.orgfd0930e2010-06-11 10:37:34 +0000958 // If we do not flush code this test is invalid.
959 if (!FLAG_flush_code) return;
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +0000960 i::FLAG_allow_natives_syntax = true;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000961 InitializeVM();
962 v8::HandleScope scope;
963 const char* source = "function foo() {"
964 " var x = 42;"
965 " var y = 42;"
966 " var z = x + y;"
967 "};"
968 "foo()";
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000969 Handle<String> foo_name = FACTORY->LookupAsciiSymbol("foo");
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000970
971 // This compile will add the code to the compilation cache.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000972 { v8::HandleScope scope;
973 CompileRun(source);
974 }
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000975
976 // Check function is compiled.
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000977 Object* func_value = Isolate::Current()->context()->global_object()->
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000978 GetProperty(*foo_name)->ToObjectChecked();
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000979 CHECK(func_value->IsJSFunction());
980 Handle<JSFunction> function(JSFunction::cast(func_value));
981 CHECK(function->shared()->is_compiled());
982
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +0000983 // The code will survive at least two GCs.
984 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
985 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000986 CHECK(function->shared()->is_compiled());
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000987
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +0000988 // Simulate several GCs that use full marking.
989 const int kAgingThreshold = 6;
990 for (int i = 0; i < kAgingThreshold; i++) {
991 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
992 }
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000993
994 // foo should no longer be in the compilation cache
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000995 CHECK(!function->shared()->is_compiled() || function->IsOptimized());
996 CHECK(!function->is_compiled() || function->IsOptimized());
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000997 // Call foo to get it recompiled.
998 CompileRun("foo()");
999 CHECK(function->shared()->is_compiled());
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001000 CHECK(function->is_compiled());
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00001001}
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001002
1003
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00001004TEST(TestCodeFlushingIncremental) {
1005 // If we do not flush code this test is invalid.
1006 if (!FLAG_flush_code || !FLAG_flush_code_incrementally) return;
1007 i::FLAG_allow_natives_syntax = true;
1008 InitializeVM();
1009 v8::HandleScope scope;
1010 const char* source = "function foo() {"
1011 " var x = 42;"
1012 " var y = 42;"
1013 " var z = x + y;"
1014 "};"
1015 "foo()";
1016 Handle<String> foo_name = FACTORY->LookupAsciiSymbol("foo");
1017
1018 // This compile will add the code to the compilation cache.
1019 { v8::HandleScope scope;
1020 CompileRun(source);
1021 }
1022
1023 // Check function is compiled.
1024 Object* func_value = Isolate::Current()->context()->global_object()->
1025 GetProperty(*foo_name)->ToObjectChecked();
1026 CHECK(func_value->IsJSFunction());
1027 Handle<JSFunction> function(JSFunction::cast(func_value));
1028 CHECK(function->shared()->is_compiled());
1029
1030 // The code will survive at least two GCs.
1031 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1032 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1033 CHECK(function->shared()->is_compiled());
1034
1035 // Simulate several GCs that use incremental marking.
1036 const int kAgingThreshold = 6;
1037 for (int i = 0; i < kAgingThreshold; i++) {
1038 HEAP->incremental_marking()->Abort();
1039 SimulateIncrementalMarking();
1040 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1041 }
1042 CHECK(!function->shared()->is_compiled() || function->IsOptimized());
1043 CHECK(!function->is_compiled() || function->IsOptimized());
1044
1045 // This compile will compile the function again.
1046 { v8::HandleScope scope;
1047 CompileRun("foo();");
1048 }
1049
1050 // Simulate several GCs that use incremental marking but make sure
1051 // the loop breaks once the function is enqueued as a candidate.
1052 for (int i = 0; i < kAgingThreshold; i++) {
1053 HEAP->incremental_marking()->Abort();
1054 SimulateIncrementalMarking();
1055 if (!function->next_function_link()->IsUndefined()) break;
1056 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1057 }
1058
1059 // Force optimization while incremental marking is active and while
1060 // the function is enqueued as a candidate.
1061 { v8::HandleScope scope;
1062 CompileRun("%OptimizeFunctionOnNextCall(foo); foo();");
1063 }
1064
1065 // Simulate one final GC to make sure the candidate queue is sane.
1066 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1067 CHECK(function->shared()->is_compiled() || !function->IsOptimized());
1068 CHECK(function->is_compiled() || !function->IsOptimized());
1069}
1070
1071
1072TEST(TestCodeFlushingIncrementalScavenge) {
1073 // If we do not flush code this test is invalid.
1074 if (!FLAG_flush_code || !FLAG_flush_code_incrementally) return;
1075 i::FLAG_allow_natives_syntax = true;
1076 InitializeVM();
1077 v8::HandleScope scope;
1078 const char* source = "var foo = function() {"
1079 " var x = 42;"
1080 " var y = 42;"
1081 " var z = x + y;"
1082 "};"
1083 "foo();"
1084 "var bar = function() {"
1085 " var x = 23;"
1086 "};"
1087 "bar();";
1088 Handle<String> foo_name = FACTORY->LookupAsciiSymbol("foo");
1089 Handle<String> bar_name = FACTORY->LookupAsciiSymbol("bar");
1090
1091 // Perfrom one initial GC to enable code flushing.
1092 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1093
1094 // This compile will add the code to the compilation cache.
1095 { v8::HandleScope scope;
1096 CompileRun(source);
1097 }
1098
1099 // Check functions are compiled.
1100 Object* func_value = Isolate::Current()->context()->global_object()->
1101 GetProperty(*foo_name)->ToObjectChecked();
1102 CHECK(func_value->IsJSFunction());
1103 Handle<JSFunction> function(JSFunction::cast(func_value));
1104 CHECK(function->shared()->is_compiled());
1105 Object* func_value2 = Isolate::Current()->context()->global_object()->
1106 GetProperty(*bar_name)->ToObjectChecked();
1107 CHECK(func_value2->IsJSFunction());
1108 Handle<JSFunction> function2(JSFunction::cast(func_value2));
1109 CHECK(function2->shared()->is_compiled());
1110
1111 // Clear references to functions so that one of them can die.
1112 { v8::HandleScope scope;
1113 CompileRun("foo = 0; bar = 0;");
1114 }
1115
1116 // Bump the code age so that flushing is triggered while the function
1117 // object is still located in new-space.
1118 const int kAgingThreshold = 6;
1119 function->shared()->set_code_age(kAgingThreshold);
1120 function2->shared()->set_code_age(kAgingThreshold);
1121
1122 // Simulate incremental marking so that the functions are enqueued as
1123 // code flushing candidates. Then kill one of the functions. Finally
1124 // perform a scavenge while incremental marking is still running.
1125 SimulateIncrementalMarking();
1126 *function2.location() = NULL;
1127 HEAP->CollectGarbage(NEW_SPACE, "test scavenge while marking");
1128
1129 // Simulate one final GC to make sure the candidate queue is sane.
1130 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1131 CHECK(!function->shared()->is_compiled() || function->IsOptimized());
1132 CHECK(!function->is_compiled() || function->IsOptimized());
1133}
1134
1135
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00001136TEST(TestCodeFlushingIncrementalAbort) {
1137 // If we do not flush code this test is invalid.
1138 if (!FLAG_flush_code || !FLAG_flush_code_incrementally) return;
1139 i::FLAG_allow_natives_syntax = true;
1140 InitializeVM();
1141 v8::HandleScope scope;
1142 const char* source = "function foo() {"
1143 " var x = 42;"
1144 " var y = 42;"
1145 " var z = x + y;"
1146 "};"
1147 "foo()";
1148 Handle<String> foo_name = FACTORY->LookupAsciiSymbol("foo");
1149
1150 // This compile will add the code to the compilation cache.
1151 { v8::HandleScope scope;
1152 CompileRun(source);
1153 }
1154
1155 // Check function is compiled.
1156 Object* func_value = Isolate::Current()->context()->global_object()->
1157 GetProperty(*foo_name)->ToObjectChecked();
1158 CHECK(func_value->IsJSFunction());
1159 Handle<JSFunction> function(JSFunction::cast(func_value));
1160 CHECK(function->shared()->is_compiled());
1161
1162 // The code will survive at least two GCs.
1163 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1164 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1165 CHECK(function->shared()->is_compiled());
1166
1167 // Bump the code age so that flushing is triggered.
1168 const int kAgingThreshold = 6;
1169 function->shared()->set_code_age(kAgingThreshold);
1170
1171 // Simulate incremental marking so that the function is enqueued as
1172 // code flushing candidate.
1173 SimulateIncrementalMarking();
1174
1175 // Enable the debugger and add a breakpoint while incremental marking
1176 // is running so that incremental marking aborts and code flushing is
1177 // disabled.
1178 int position = 0;
1179 Handle<Object> breakpoint_object(Smi::FromInt(0));
1180 ISOLATE->debug()->SetBreakPoint(function, breakpoint_object, &position);
1181 ISOLATE->debug()->ClearAllBreakPoints();
1182
1183 // Force optimization now that code flushing is disabled.
1184 { v8::HandleScope scope;
1185 CompileRun("%OptimizeFunctionOnNextCall(foo); foo();");
1186 }
1187
1188 // Simulate one final GC to make sure the candidate queue is sane.
1189 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1190 CHECK(function->shared()->is_compiled() || !function->IsOptimized());
1191 CHECK(function->is_compiled() || !function->IsOptimized());
1192}
1193
1194
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001195// Count the number of native contexts in the weak list of native contexts.
1196int CountNativeContexts() {
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001197 int count = 0;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001198 Object* object = HEAP->native_contexts_list();
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001199 while (!object->IsUndefined()) {
1200 count++;
1201 object = Context::cast(object)->get(Context::NEXT_CONTEXT_LINK);
1202 }
1203 return count;
1204}
1205
1206
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001207// Count the number of user functions in the weak list of optimized
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001208// functions attached to a native context.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001209static int CountOptimizedUserFunctions(v8::Handle<v8::Context> context) {
1210 int count = 0;
1211 Handle<Context> icontext = v8::Utils::OpenHandle(*context);
1212 Object* object = icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST);
1213 while (object->IsJSFunction() && !JSFunction::cast(object)->IsBuiltin()) {
1214 count++;
1215 object = JSFunction::cast(object)->next_function_link();
1216 }
1217 return count;
1218}
1219
1220
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001221TEST(TestInternalWeakLists) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001222 v8::V8::Initialize();
1223
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001224 static const int kNumTestContexts = 10;
1225
1226 v8::HandleScope scope;
1227 v8::Persistent<v8::Context> ctx[kNumTestContexts];
1228
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001229 CHECK_EQ(0, CountNativeContexts());
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001230
1231 // Create a number of global contests which gets linked together.
1232 for (int i = 0; i < kNumTestContexts; i++) {
1233 ctx[i] = v8::Context::New();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001234
1235 bool opt = (FLAG_always_opt && i::V8::UseCrankshaft());
1236
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001237 CHECK_EQ(i + 1, CountNativeContexts());
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001238
1239 ctx[i]->Enter();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001240
1241 // Create a handle scope so no function objects get stuch in the outer
1242 // handle scope
1243 v8::HandleScope scope;
1244 const char* source = "function f1() { };"
1245 "function f2() { };"
1246 "function f3() { };"
1247 "function f4() { };"
1248 "function f5() { };";
1249 CompileRun(source);
1250 CHECK_EQ(0, CountOptimizedUserFunctions(ctx[i]));
1251 CompileRun("f1()");
1252 CHECK_EQ(opt ? 1 : 0, CountOptimizedUserFunctions(ctx[i]));
1253 CompileRun("f2()");
1254 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i]));
1255 CompileRun("f3()");
1256 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i]));
1257 CompileRun("f4()");
1258 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i]));
1259 CompileRun("f5()");
1260 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i]));
1261
1262 // Remove function f1, and
1263 CompileRun("f1=null");
1264
1265 // Scavenge treats these references as strong.
1266 for (int j = 0; j < 10; j++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001267 HEAP->PerformScavenge();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001268 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i]));
1269 }
1270
1271 // Mark compact handles the weak references.
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00001272 ISOLATE->compilation_cache()->Clear();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001273 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001274 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i]));
1275
1276 // Get rid of f3 and f5 in the same way.
1277 CompileRun("f3=null");
1278 for (int j = 0; j < 10; j++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001279 HEAP->PerformScavenge();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001280 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i]));
1281 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001282 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001283 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i]));
1284 CompileRun("f5=null");
1285 for (int j = 0; j < 10; j++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001286 HEAP->PerformScavenge();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001287 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i]));
1288 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001289 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001290 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i]));
1291
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001292 ctx[i]->Exit();
1293 }
1294
1295 // Force compilation cache cleanup.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001296 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001297
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001298 // Dispose the native contexts one by one.
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001299 for (int i = 0; i < kNumTestContexts; i++) {
1300 ctx[i].Dispose();
1301 ctx[i].Clear();
1302
1303 // Scavenge treats these references as strong.
1304 for (int j = 0; j < 10; j++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001305 HEAP->PerformScavenge();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001306 CHECK_EQ(kNumTestContexts - i, CountNativeContexts());
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001307 }
1308
1309 // Mark compact handles the weak references.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001310 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001311 CHECK_EQ(kNumTestContexts - i - 1, CountNativeContexts());
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001312 }
1313
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001314 CHECK_EQ(0, CountNativeContexts());
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001315}
1316
1317
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001318// Count the number of native contexts in the weak list of native contexts
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001319// causing a GC after the specified number of elements.
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001320static int CountNativeContextsWithGC(int n) {
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001321 int count = 0;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001322 Handle<Object> object(HEAP->native_contexts_list());
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001323 while (!object->IsUndefined()) {
1324 count++;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001325 if (count == n) HEAP->CollectAllGarbage(Heap::kNoGCFlags);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001326 object =
1327 Handle<Object>(Context::cast(*object)->get(Context::NEXT_CONTEXT_LINK));
1328 }
1329 return count;
1330}
1331
1332
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001333// Count the number of user functions in the weak list of optimized
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001334// functions attached to a native context causing a GC after the
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001335// specified number of elements.
1336static int CountOptimizedUserFunctionsWithGC(v8::Handle<v8::Context> context,
1337 int n) {
1338 int count = 0;
1339 Handle<Context> icontext = v8::Utils::OpenHandle(*context);
1340 Handle<Object> object(icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST));
1341 while (object->IsJSFunction() &&
1342 !Handle<JSFunction>::cast(object)->IsBuiltin()) {
1343 count++;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001344 if (count == n) HEAP->CollectAllGarbage(Heap::kNoGCFlags);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001345 object = Handle<Object>(
1346 Object::cast(JSFunction::cast(*object)->next_function_link()));
1347 }
1348 return count;
1349}
1350
1351
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001352TEST(TestInternalWeakListsTraverseWithGC) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001353 v8::V8::Initialize();
1354
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001355 static const int kNumTestContexts = 10;
1356
1357 v8::HandleScope scope;
1358 v8::Persistent<v8::Context> ctx[kNumTestContexts];
1359
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001360 CHECK_EQ(0, CountNativeContexts());
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001361
1362 // Create an number of contexts and check the length of the weak list both
1363 // with and without GCs while iterating the list.
1364 for (int i = 0; i < kNumTestContexts; i++) {
1365 ctx[i] = v8::Context::New();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001366 CHECK_EQ(i + 1, CountNativeContexts());
1367 CHECK_EQ(i + 1, CountNativeContextsWithGC(i / 2 + 1));
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001368 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001369
1370 bool opt = (FLAG_always_opt && i::V8::UseCrankshaft());
1371
1372 // Compile a number of functions the length of the weak list of optimized
1373 // functions both with and without GCs while iterating the list.
1374 ctx[0]->Enter();
1375 const char* source = "function f1() { };"
1376 "function f2() { };"
1377 "function f3() { };"
1378 "function f4() { };"
1379 "function f5() { };";
1380 CompileRun(source);
1381 CHECK_EQ(0, CountOptimizedUserFunctions(ctx[0]));
1382 CompileRun("f1()");
1383 CHECK_EQ(opt ? 1 : 0, CountOptimizedUserFunctions(ctx[0]));
1384 CHECK_EQ(opt ? 1 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 1));
1385 CompileRun("f2()");
1386 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[0]));
1387 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 1));
1388 CompileRun("f3()");
1389 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[0]));
1390 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 1));
1391 CompileRun("f4()");
1392 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[0]));
1393 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 2));
1394 CompileRun("f5()");
1395 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[0]));
1396 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 4));
1397
1398 ctx[0]->Exit();
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001399}
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +00001400
1401
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001402TEST(TestSizeOfObjects) {
1403 v8::V8::Initialize();
1404
1405 // Get initial heap size after several full GCs, which will stabilize
1406 // the heap size and return with sweeping finished completely.
1407 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1408 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1409 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1410 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001411 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001412 CHECK(HEAP->old_pointer_space()->IsSweepingComplete());
1413 int initial_size = static_cast<int>(HEAP->SizeOfObjects());
1414
1415 {
1416 // Allocate objects on several different old-space pages so that
1417 // lazy sweeping kicks in for subsequent GC runs.
1418 AlwaysAllocateScope always_allocate;
1419 int filler_size = static_cast<int>(FixedArray::SizeFor(8192));
1420 for (int i = 1; i <= 100; i++) {
1421 HEAP->AllocateFixedArray(8192, TENURED)->ToObjectChecked();
1422 CHECK_EQ(initial_size + i * filler_size,
1423 static_cast<int>(HEAP->SizeOfObjects()));
1424 }
1425 }
1426
1427 // The heap size should go back to initial size after a full GC, even
1428 // though sweeping didn't finish yet.
1429 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
danno@chromium.org2c26cb12012-05-03 09:06:43 +00001430
1431 // Normally sweeping would not be complete here, but no guarantees.
1432
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001433 CHECK_EQ(initial_size, static_cast<int>(HEAP->SizeOfObjects()));
1434
1435 // Advancing the sweeper step-wise should not change the heap size.
1436 while (!HEAP->old_pointer_space()->IsSweepingComplete()) {
1437 HEAP->old_pointer_space()->AdvanceSweeper(KB);
1438 CHECK_EQ(initial_size, static_cast<int>(HEAP->SizeOfObjects()));
1439 }
1440}
1441
1442
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +00001443TEST(TestSizeOfObjectsVsHeapIteratorPrecision) {
1444 InitializeVM();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001445 HEAP->EnsureHeapIsIterable();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001446 intptr_t size_of_objects_1 = HEAP->SizeOfObjects();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001447 HeapIterator iterator;
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +00001448 intptr_t size_of_objects_2 = 0;
1449 for (HeapObject* obj = iterator.next();
1450 obj != NULL;
1451 obj = iterator.next()) {
ulan@chromium.org56c14af2012-09-20 12:51:09 +00001452 if (!obj->IsFreeSpace()) {
1453 size_of_objects_2 += obj->Size();
1454 }
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +00001455 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001456 // Delta must be within 5% of the larger result.
1457 // TODO(gc): Tighten this up by distinguishing between byte
1458 // arrays that are real and those that merely mark free space
1459 // on the heap.
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +00001460 if (size_of_objects_1 > size_of_objects_2) {
1461 intptr_t delta = size_of_objects_1 - size_of_objects_2;
1462 PrintF("Heap::SizeOfObjects: %" V8_PTR_PREFIX "d, "
1463 "Iterator: %" V8_PTR_PREFIX "d, "
1464 "delta: %" V8_PTR_PREFIX "d\n",
1465 size_of_objects_1, size_of_objects_2, delta);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001466 CHECK_GT(size_of_objects_1 / 20, delta);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +00001467 } else {
1468 intptr_t delta = size_of_objects_2 - size_of_objects_1;
1469 PrintF("Heap::SizeOfObjects: %" V8_PTR_PREFIX "d, "
1470 "Iterator: %" V8_PTR_PREFIX "d, "
1471 "delta: %" V8_PTR_PREFIX "d\n",
1472 size_of_objects_1, size_of_objects_2, delta);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001473 CHECK_GT(size_of_objects_2 / 20, delta);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +00001474 }
1475}
whesse@chromium.org023421e2010-12-21 12:19:12 +00001476
1477
danno@chromium.orgc612e022011-11-10 11:38:15 +00001478static void FillUpNewSpace(NewSpace* new_space) {
1479 // Fill up new space to the point that it is completely full. Make sure
1480 // that the scavenger does not undo the filling.
1481 v8::HandleScope scope;
1482 AlwaysAllocateScope always_allocate;
1483 intptr_t available = new_space->EffectiveCapacity() - new_space->Size();
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001484 intptr_t number_of_fillers = (available / FixedArray::SizeFor(32)) - 1;
danno@chromium.orgc612e022011-11-10 11:38:15 +00001485 for (intptr_t i = 0; i < number_of_fillers; i++) {
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001486 CHECK(HEAP->InNewSpace(*FACTORY->NewFixedArray(32, NOT_TENURED)));
danno@chromium.orgc612e022011-11-10 11:38:15 +00001487 }
1488}
1489
1490
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001491TEST(GrowAndShrinkNewSpace) {
1492 InitializeVM();
1493 NewSpace* new_space = HEAP->new_space();
1494
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001495 if (HEAP->ReservedSemiSpaceSize() == HEAP->InitialSemiSpaceSize() ||
1496 HEAP->MaxSemiSpaceSize() == HEAP->InitialSemiSpaceSize()) {
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001497 // The max size cannot exceed the reserved size, since semispaces must be
1498 // always within the reserved space. We can't test new space growing and
1499 // shrinking if the reserved size is the same as the minimum (initial) size.
1500 return;
1501 }
1502
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001503 // Explicitly growing should double the space capacity.
1504 intptr_t old_capacity, new_capacity;
1505 old_capacity = new_space->Capacity();
1506 new_space->Grow();
1507 new_capacity = new_space->Capacity();
1508 CHECK(2 * old_capacity == new_capacity);
1509
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001510 old_capacity = new_space->Capacity();
danno@chromium.orgc612e022011-11-10 11:38:15 +00001511 FillUpNewSpace(new_space);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001512 new_capacity = new_space->Capacity();
1513 CHECK(old_capacity == new_capacity);
whesse@chromium.org023421e2010-12-21 12:19:12 +00001514
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001515 // Explicitly shrinking should not affect space capacity.
1516 old_capacity = new_space->Capacity();
1517 new_space->Shrink();
1518 new_capacity = new_space->Capacity();
1519 CHECK(old_capacity == new_capacity);
1520
1521 // Let the scavenger empty the new space.
1522 HEAP->CollectGarbage(NEW_SPACE);
1523 CHECK_LE(new_space->Size(), old_capacity);
1524
1525 // Explicitly shrinking should halve the space capacity.
1526 old_capacity = new_space->Capacity();
1527 new_space->Shrink();
1528 new_capacity = new_space->Capacity();
1529 CHECK(old_capacity == 2 * new_capacity);
1530
1531 // Consecutive shrinking should not affect space capacity.
1532 old_capacity = new_space->Capacity();
1533 new_space->Shrink();
1534 new_space->Shrink();
1535 new_space->Shrink();
1536 new_capacity = new_space->Capacity();
1537 CHECK(old_capacity == new_capacity);
whesse@chromium.org023421e2010-12-21 12:19:12 +00001538}
danno@chromium.orgc612e022011-11-10 11:38:15 +00001539
1540
1541TEST(CollectingAllAvailableGarbageShrinksNewSpace) {
1542 InitializeVM();
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001543
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001544 if (HEAP->ReservedSemiSpaceSize() == HEAP->InitialSemiSpaceSize() ||
1545 HEAP->MaxSemiSpaceSize() == HEAP->InitialSemiSpaceSize()) {
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001546 // The max size cannot exceed the reserved size, since semispaces must be
1547 // always within the reserved space. We can't test new space growing and
1548 // shrinking if the reserved size is the same as the minimum (initial) size.
1549 return;
1550 }
1551
danno@chromium.orgc612e022011-11-10 11:38:15 +00001552 v8::HandleScope scope;
1553 NewSpace* new_space = HEAP->new_space();
1554 intptr_t old_capacity, new_capacity;
1555 old_capacity = new_space->Capacity();
1556 new_space->Grow();
1557 new_capacity = new_space->Capacity();
1558 CHECK(2 * old_capacity == new_capacity);
1559 FillUpNewSpace(new_space);
1560 HEAP->CollectAllAvailableGarbage();
1561 new_capacity = new_space->Capacity();
1562 CHECK(old_capacity == new_capacity);
1563}
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +00001564
ricow@chromium.org7ad65222011-12-19 12:13:11 +00001565
1566static int NumberOfGlobalObjects() {
1567 int count = 0;
1568 HeapIterator iterator;
1569 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
1570 if (obj->IsGlobalObject()) count++;
1571 }
1572 return count;
1573}
1574
1575
1576// Test that we don't embed maps from foreign contexts into
1577// optimized code.
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001578TEST(LeakNativeContextViaMap) {
danno@chromium.orge78f9fc2011-12-21 08:29:34 +00001579 i::FLAG_allow_natives_syntax = true;
ricow@chromium.org7ad65222011-12-19 12:13:11 +00001580 v8::HandleScope outer_scope;
1581 v8::Persistent<v8::Context> ctx1 = v8::Context::New();
1582 v8::Persistent<v8::Context> ctx2 = v8::Context::New();
1583 ctx1->Enter();
1584
1585 HEAP->CollectAllAvailableGarbage();
1586 CHECK_EQ(4, NumberOfGlobalObjects());
1587
1588 {
1589 v8::HandleScope inner_scope;
1590 CompileRun("var v = {x: 42}");
1591 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v"));
1592 ctx2->Enter();
1593 ctx2->Global()->Set(v8_str("o"), v);
1594 v8::Local<v8::Value> res = CompileRun(
1595 "function f() { return o.x; }"
danno@chromium.orge78f9fc2011-12-21 08:29:34 +00001596 "for (var i = 0; i < 10; ++i) f();"
1597 "%OptimizeFunctionOnNextCall(f);"
ricow@chromium.org7ad65222011-12-19 12:13:11 +00001598 "f();");
1599 CHECK_EQ(42, res->Int32Value());
1600 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0));
1601 ctx2->Exit();
1602 ctx1->Exit();
1603 ctx1.Dispose();
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00001604 v8::V8::ContextDisposedNotification();
ricow@chromium.org7ad65222011-12-19 12:13:11 +00001605 }
1606 HEAP->CollectAllAvailableGarbage();
1607 CHECK_EQ(2, NumberOfGlobalObjects());
1608 ctx2.Dispose();
1609 HEAP->CollectAllAvailableGarbage();
1610 CHECK_EQ(0, NumberOfGlobalObjects());
1611}
1612
1613
1614// Test that we don't embed functions from foreign contexts into
1615// optimized code.
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001616TEST(LeakNativeContextViaFunction) {
danno@chromium.orge78f9fc2011-12-21 08:29:34 +00001617 i::FLAG_allow_natives_syntax = true;
ricow@chromium.org7ad65222011-12-19 12:13:11 +00001618 v8::HandleScope outer_scope;
1619 v8::Persistent<v8::Context> ctx1 = v8::Context::New();
1620 v8::Persistent<v8::Context> ctx2 = v8::Context::New();
1621 ctx1->Enter();
1622
1623 HEAP->CollectAllAvailableGarbage();
1624 CHECK_EQ(4, NumberOfGlobalObjects());
1625
1626 {
1627 v8::HandleScope inner_scope;
1628 CompileRun("var v = function() { return 42; }");
1629 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v"));
1630 ctx2->Enter();
1631 ctx2->Global()->Set(v8_str("o"), v);
1632 v8::Local<v8::Value> res = CompileRun(
1633 "function f(x) { return x(); }"
danno@chromium.orge78f9fc2011-12-21 08:29:34 +00001634 "for (var i = 0; i < 10; ++i) f(o);"
1635 "%OptimizeFunctionOnNextCall(f);"
ricow@chromium.org7ad65222011-12-19 12:13:11 +00001636 "f(o);");
1637 CHECK_EQ(42, res->Int32Value());
1638 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0));
1639 ctx2->Exit();
1640 ctx1->Exit();
1641 ctx1.Dispose();
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00001642 v8::V8::ContextDisposedNotification();
ricow@chromium.org7ad65222011-12-19 12:13:11 +00001643 }
1644 HEAP->CollectAllAvailableGarbage();
1645 CHECK_EQ(2, NumberOfGlobalObjects());
1646 ctx2.Dispose();
1647 HEAP->CollectAllAvailableGarbage();
1648 CHECK_EQ(0, NumberOfGlobalObjects());
1649}
danno@chromium.orge78f9fc2011-12-21 08:29:34 +00001650
1651
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001652TEST(LeakNativeContextViaMapKeyed) {
danno@chromium.orge78f9fc2011-12-21 08:29:34 +00001653 i::FLAG_allow_natives_syntax = true;
1654 v8::HandleScope outer_scope;
1655 v8::Persistent<v8::Context> ctx1 = v8::Context::New();
1656 v8::Persistent<v8::Context> ctx2 = v8::Context::New();
1657 ctx1->Enter();
1658
1659 HEAP->CollectAllAvailableGarbage();
1660 CHECK_EQ(4, NumberOfGlobalObjects());
1661
1662 {
1663 v8::HandleScope inner_scope;
1664 CompileRun("var v = [42, 43]");
1665 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v"));
1666 ctx2->Enter();
1667 ctx2->Global()->Set(v8_str("o"), v);
1668 v8::Local<v8::Value> res = CompileRun(
1669 "function f() { return o[0]; }"
1670 "for (var i = 0; i < 10; ++i) f();"
1671 "%OptimizeFunctionOnNextCall(f);"
1672 "f();");
1673 CHECK_EQ(42, res->Int32Value());
1674 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0));
1675 ctx2->Exit();
1676 ctx1->Exit();
1677 ctx1.Dispose();
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00001678 v8::V8::ContextDisposedNotification();
danno@chromium.orge78f9fc2011-12-21 08:29:34 +00001679 }
1680 HEAP->CollectAllAvailableGarbage();
1681 CHECK_EQ(2, NumberOfGlobalObjects());
1682 ctx2.Dispose();
1683 HEAP->CollectAllAvailableGarbage();
1684 CHECK_EQ(0, NumberOfGlobalObjects());
1685}
1686
1687
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001688TEST(LeakNativeContextViaMapProto) {
danno@chromium.orge78f9fc2011-12-21 08:29:34 +00001689 i::FLAG_allow_natives_syntax = true;
1690 v8::HandleScope outer_scope;
1691 v8::Persistent<v8::Context> ctx1 = v8::Context::New();
1692 v8::Persistent<v8::Context> ctx2 = v8::Context::New();
1693 ctx1->Enter();
1694
1695 HEAP->CollectAllAvailableGarbage();
1696 CHECK_EQ(4, NumberOfGlobalObjects());
1697
1698 {
1699 v8::HandleScope inner_scope;
1700 CompileRun("var v = { y: 42}");
1701 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v"));
1702 ctx2->Enter();
1703 ctx2->Global()->Set(v8_str("o"), v);
1704 v8::Local<v8::Value> res = CompileRun(
1705 "function f() {"
1706 " var p = {x: 42};"
1707 " p.__proto__ = o;"
1708 " return p.x;"
1709 "}"
1710 "for (var i = 0; i < 10; ++i) f();"
1711 "%OptimizeFunctionOnNextCall(f);"
1712 "f();");
1713 CHECK_EQ(42, res->Int32Value());
1714 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0));
1715 ctx2->Exit();
1716 ctx1->Exit();
1717 ctx1.Dispose();
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00001718 v8::V8::ContextDisposedNotification();
danno@chromium.orge78f9fc2011-12-21 08:29:34 +00001719 }
1720 HEAP->CollectAllAvailableGarbage();
1721 CHECK_EQ(2, NumberOfGlobalObjects());
1722 ctx2.Dispose();
1723 HEAP->CollectAllAvailableGarbage();
1724 CHECK_EQ(0, NumberOfGlobalObjects());
1725}
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001726
1727
1728TEST(InstanceOfStubWriteBarrier) {
1729 i::FLAG_allow_natives_syntax = true;
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00001730#ifdef VERIFY_HEAP
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001731 i::FLAG_verify_heap = true;
1732#endif
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00001733
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001734 InitializeVM();
1735 if (!i::V8::UseCrankshaft()) return;
1736 v8::HandleScope outer_scope;
1737
1738 {
1739 v8::HandleScope scope;
1740 CompileRun(
1741 "function foo () { }"
1742 "function mkbar () { return new (new Function(\"\")) (); }"
1743 "function f (x) { return (x instanceof foo); }"
1744 "function g () { f(mkbar()); }"
1745 "f(new foo()); f(new foo());"
1746 "%OptimizeFunctionOnNextCall(f);"
1747 "f(new foo()); g();");
1748 }
1749
1750 IncrementalMarking* marking = HEAP->incremental_marking();
1751 marking->Abort();
1752 marking->Start();
1753
1754 Handle<JSFunction> f =
1755 v8::Utils::OpenHandle(
1756 *v8::Handle<v8::Function>::Cast(
1757 v8::Context::GetCurrent()->Global()->Get(v8_str("f"))));
1758
1759 CHECK(f->IsOptimized());
1760
1761 while (!Marking::IsBlack(Marking::MarkBitFrom(f->code())) &&
1762 !marking->IsStopped()) {
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001763 // Discard any pending GC requests otherwise we will get GC when we enter
1764 // code below.
1765 marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001766 }
1767
1768 CHECK(marking->IsMarking());
1769
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001770 {
1771 v8::HandleScope scope;
1772 v8::Handle<v8::Object> global = v8::Context::GetCurrent()->Global();
1773 v8::Handle<v8::Function> g =
1774 v8::Handle<v8::Function>::Cast(global->Get(v8_str("g")));
1775 g->Call(global, 0, NULL);
1776 }
1777
1778 HEAP->incremental_marking()->set_should_hurry(true);
1779 HEAP->CollectGarbage(OLD_POINTER_SPACE);
1780}
ulan@chromium.org2efb9002012-01-19 15:36:35 +00001781
1782
1783TEST(PrototypeTransitionClearing) {
1784 InitializeVM();
1785 v8::HandleScope scope;
1786
1787 CompileRun(
1788 "var base = {};"
1789 "var live = [];"
1790 "for (var i = 0; i < 10; i++) {"
1791 " var object = {};"
1792 " var prototype = {};"
1793 " object.__proto__ = prototype;"
1794 " if (i >= 3) live.push(object, prototype);"
1795 "}");
1796
1797 Handle<JSObject> baseObject =
1798 v8::Utils::OpenHandle(
1799 *v8::Handle<v8::Object>::Cast(
1800 v8::Context::GetCurrent()->Global()->Get(v8_str("base"))));
1801
ulan@chromium.orgf6a0c412012-06-15 12:31:06 +00001802 // Verify that only dead prototype transitions are cleared.
1803 CHECK_EQ(10, baseObject->map()->NumberOfProtoTransitions());
ulan@chromium.org2efb9002012-01-19 15:36:35 +00001804 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
ulan@chromium.orgf6a0c412012-06-15 12:31:06 +00001805 const int transitions = 10 - 3;
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001806 CHECK_EQ(transitions, baseObject->map()->NumberOfProtoTransitions());
ulan@chromium.org2efb9002012-01-19 15:36:35 +00001807
1808 // Verify that prototype transitions array was compacted.
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001809 FixedArray* trans = baseObject->map()->GetPrototypeTransitions();
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001810 for (int i = 0; i < transitions; i++) {
ulan@chromium.org2efb9002012-01-19 15:36:35 +00001811 int j = Map::kProtoTransitionHeaderSize +
1812 i * Map::kProtoTransitionElementsPerEntry;
1813 CHECK(trans->get(j + Map::kProtoTransitionMapOffset)->IsMap());
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001814 Object* proto = trans->get(j + Map::kProtoTransitionPrototypeOffset);
1815 CHECK(proto->IsTheHole() || proto->IsJSObject());
ulan@chromium.org2efb9002012-01-19 15:36:35 +00001816 }
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001817
1818 // Make sure next prototype is placed on an old-space evacuation candidate.
1819 Handle<JSObject> prototype;
1820 PagedSpace* space = HEAP->old_pointer_space();
1821 do {
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00001822 prototype = FACTORY->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, TENURED);
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001823 } while (space->FirstPage() == space->LastPage() ||
1824 !space->LastPage()->Contains(prototype->address()));
1825
1826 // Add a prototype on an evacuation candidate and verify that transition
1827 // clearing correctly records slots in prototype transition array.
1828 i::FLAG_always_compact = true;
1829 Handle<Map> map(baseObject->map());
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001830 CHECK(!space->LastPage()->Contains(
1831 map->GetPrototypeTransitions()->address()));
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001832 CHECK(space->LastPage()->Contains(prototype->address()));
1833 baseObject->SetPrototype(*prototype, false)->ToObjectChecked();
1834 CHECK(map->GetPrototypeTransition(*prototype)->IsMap());
1835 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
1836 CHECK(map->GetPrototypeTransition(*prototype)->IsMap());
ulan@chromium.org2efb9002012-01-19 15:36:35 +00001837}
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001838
1839
1840TEST(ResetSharedFunctionInfoCountersDuringIncrementalMarking) {
1841 i::FLAG_allow_natives_syntax = true;
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00001842#ifdef VERIFY_HEAP
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001843 i::FLAG_verify_heap = true;
1844#endif
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00001845
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001846 InitializeVM();
1847 if (!i::V8::UseCrankshaft()) return;
1848 v8::HandleScope outer_scope;
1849
1850 {
1851 v8::HandleScope scope;
1852 CompileRun(
1853 "function f () {"
1854 " var s = 0;"
1855 " for (var i = 0; i < 100; i++) s += i;"
1856 " return s;"
1857 "}"
1858 "f(); f();"
1859 "%OptimizeFunctionOnNextCall(f);"
1860 "f();");
1861 }
1862 Handle<JSFunction> f =
1863 v8::Utils::OpenHandle(
1864 *v8::Handle<v8::Function>::Cast(
1865 v8::Context::GetCurrent()->Global()->Get(v8_str("f"))));
1866 CHECK(f->IsOptimized());
1867
1868 IncrementalMarking* marking = HEAP->incremental_marking();
1869 marking->Abort();
1870 marking->Start();
1871
1872 // The following two calls will increment HEAP->global_ic_age().
1873 const int kLongIdlePauseInMs = 1000;
1874 v8::V8::ContextDisposedNotification();
1875 v8::V8::IdleNotification(kLongIdlePauseInMs);
1876
1877 while (!marking->IsStopped() && !marking->IsComplete()) {
1878 marking->Step(1 * MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
1879 }
danno@chromium.org2c26cb12012-05-03 09:06:43 +00001880 if (!marking->IsStopped() || marking->should_hurry()) {
1881 // We don't normally finish a GC via Step(), we normally finish by
1882 // setting the stack guard and then do the final steps in the stack
1883 // guard interrupt. But here we didn't ask for that, and there is no
1884 // JS code running to trigger the interrupt, so we explicitly finalize
1885 // here.
1886 HEAP->CollectAllGarbage(Heap::kNoGCFlags,
1887 "Test finalizing incremental mark-sweep");
1888 }
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001889
1890 CHECK_EQ(HEAP->global_ic_age(), f->shared()->ic_age());
1891 CHECK_EQ(0, f->shared()->opt_count());
1892 CHECK_EQ(0, f->shared()->code()->profiler_ticks());
1893}
1894
1895
1896TEST(ResetSharedFunctionInfoCountersDuringMarkSweep) {
1897 i::FLAG_allow_natives_syntax = true;
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00001898#ifdef VERIFY_HEAP
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001899 i::FLAG_verify_heap = true;
1900#endif
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00001901
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001902 InitializeVM();
1903 if (!i::V8::UseCrankshaft()) return;
1904 v8::HandleScope outer_scope;
1905
1906 {
1907 v8::HandleScope scope;
1908 CompileRun(
1909 "function f () {"
1910 " var s = 0;"
1911 " for (var i = 0; i < 100; i++) s += i;"
1912 " return s;"
1913 "}"
1914 "f(); f();"
1915 "%OptimizeFunctionOnNextCall(f);"
1916 "f();");
1917 }
1918 Handle<JSFunction> f =
1919 v8::Utils::OpenHandle(
1920 *v8::Handle<v8::Function>::Cast(
1921 v8::Context::GetCurrent()->Global()->Get(v8_str("f"))));
1922 CHECK(f->IsOptimized());
1923
1924 HEAP->incremental_marking()->Abort();
1925
1926 // The following two calls will increment HEAP->global_ic_age().
1927 // Since incremental marking is off, IdleNotification will do full GC.
1928 const int kLongIdlePauseInMs = 1000;
1929 v8::V8::ContextDisposedNotification();
1930 v8::V8::IdleNotification(kLongIdlePauseInMs);
1931
1932 CHECK_EQ(HEAP->global_ic_age(), f->shared()->ic_age());
1933 CHECK_EQ(0, f->shared()->opt_count());
1934 CHECK_EQ(0, f->shared()->code()->profiler_ticks());
1935}
1936
1937
1938// Test that HAllocateObject will always return an object in new-space.
1939TEST(OptimizedAllocationAlwaysInNewSpace) {
1940 i::FLAG_allow_natives_syntax = true;
1941 InitializeVM();
1942 if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return;
1943 v8::HandleScope scope;
1944
1945 FillUpNewSpace(HEAP->new_space());
1946 AlwaysAllocateScope always_allocate;
1947 v8::Local<v8::Value> res = CompileRun(
1948 "function c(x) {"
1949 " this.x = x;"
1950 " for (var i = 0; i < 32; i++) {"
1951 " this['x' + i] = x;"
1952 " }"
1953 "}"
1954 "function f(x) { return new c(x); };"
1955 "f(1); f(2); f(3);"
1956 "%OptimizeFunctionOnNextCall(f);"
1957 "f(4);");
1958 CHECK_EQ(4, res->ToObject()->GetRealNamedProperty(v8_str("x"))->Int32Value());
1959
1960 Handle<JSObject> o =
1961 v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
1962
1963 CHECK(HEAP->InNewSpace(*o));
1964}
yangguo@chromium.org5f0b8ea2012-05-16 12:37:04 +00001965
1966
1967static int CountMapTransitions(Map* map) {
yangguo@chromium.org99aa4902012-07-06 16:21:55 +00001968 return map->transitions()->number_of_transitions();
yangguo@chromium.org5f0b8ea2012-05-16 12:37:04 +00001969}
1970
1971
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001972// Test that map transitions are cleared and maps are collected with
1973// incremental marking as well.
1974TEST(Regress1465) {
1975 i::FLAG_allow_natives_syntax = true;
1976 i::FLAG_trace_incremental_marking = true;
1977 InitializeVM();
1978 v8::HandleScope scope;
1979 static const int transitions_count = 256;
1980
1981 {
1982 AlwaysAllocateScope always_allocate;
1983 for (int i = 0; i < transitions_count; i++) {
1984 EmbeddedVector<char, 64> buffer;
1985 OS::SNPrintF(buffer, "var o = new Object; o.prop%d = %d;", i, i);
1986 CompileRun(buffer.start());
1987 }
1988 CompileRun("var root = new Object;");
1989 }
1990
1991 Handle<JSObject> root =
1992 v8::Utils::OpenHandle(
1993 *v8::Handle<v8::Object>::Cast(
1994 v8::Context::GetCurrent()->Global()->Get(v8_str("root"))));
1995
1996 // Count number of live transitions before marking.
1997 int transitions_before = CountMapTransitions(root->map());
1998 CompileRun("%DebugPrint(root);");
1999 CHECK_EQ(transitions_count, transitions_before);
2000
2001 SimulateIncrementalMarking();
yangguo@chromium.org5f0b8ea2012-05-16 12:37:04 +00002002 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
yangguo@chromium.org5f0b8ea2012-05-16 12:37:04 +00002003
2004 // Count number of live transitions after marking. Note that one transition
2005 // is left, because 'o' still holds an instance of one transition target.
2006 int transitions_after = CountMapTransitions(root->map());
2007 CompileRun("%DebugPrint(root);");
2008 CHECK_EQ(1, transitions_after);
2009}
verwaest@chromium.org37141392012-05-31 13:27:02 +00002010
2011
2012TEST(Regress2143a) {
2013 i::FLAG_collect_maps = true;
2014 i::FLAG_incremental_marking = true;
2015 InitializeVM();
2016 v8::HandleScope scope;
2017
2018 // Prepare a map transition from the root object together with a yet
2019 // untransitioned root object.
2020 CompileRun("var root = new Object;"
2021 "root.foo = 0;"
2022 "root = new Object;");
2023
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002024 SimulateIncrementalMarking();
verwaest@chromium.org37141392012-05-31 13:27:02 +00002025
2026 // Compile a StoreIC that performs the prepared map transition. This
2027 // will restart incremental marking and should make sure the root is
2028 // marked grey again.
2029 CompileRun("function f(o) {"
2030 " o.foo = 0;"
2031 "}"
2032 "f(new Object);"
2033 "f(root);");
2034
2035 // This bug only triggers with aggressive IC clearing.
2036 HEAP->AgeInlineCaches();
2037
2038 // Explicitly request GC to perform final marking step and sweeping.
2039 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
verwaest@chromium.org37141392012-05-31 13:27:02 +00002040
2041 Handle<JSObject> root =
2042 v8::Utils::OpenHandle(
2043 *v8::Handle<v8::Object>::Cast(
2044 v8::Context::GetCurrent()->Global()->Get(v8_str("root"))));
2045
2046 // The root object should be in a sane state.
2047 CHECK(root->IsJSObject());
2048 CHECK(root->map()->IsMap());
2049}
2050
2051
2052TEST(Regress2143b) {
2053 i::FLAG_collect_maps = true;
2054 i::FLAG_incremental_marking = true;
2055 i::FLAG_allow_natives_syntax = true;
2056 InitializeVM();
2057 v8::HandleScope scope;
2058
2059 // Prepare a map transition from the root object together with a yet
2060 // untransitioned root object.
2061 CompileRun("var root = new Object;"
2062 "root.foo = 0;"
2063 "root = new Object;");
2064
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002065 SimulateIncrementalMarking();
verwaest@chromium.org37141392012-05-31 13:27:02 +00002066
2067 // Compile an optimized LStoreNamedField that performs the prepared
2068 // map transition. This will restart incremental marking and should
2069 // make sure the root is marked grey again.
2070 CompileRun("function f(o) {"
2071 " o.foo = 0;"
2072 "}"
2073 "f(new Object);"
2074 "f(new Object);"
2075 "%OptimizeFunctionOnNextCall(f);"
2076 "f(root);"
2077 "%DeoptimizeFunction(f);");
2078
2079 // This bug only triggers with aggressive IC clearing.
2080 HEAP->AgeInlineCaches();
2081
2082 // Explicitly request GC to perform final marking step and sweeping.
2083 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
verwaest@chromium.org37141392012-05-31 13:27:02 +00002084
2085 Handle<JSObject> root =
2086 v8::Utils::OpenHandle(
2087 *v8::Handle<v8::Object>::Cast(
2088 v8::Context::GetCurrent()->Global()->Get(v8_str("root"))));
2089
2090 // The root object should be in a sane state.
2091 CHECK(root->IsJSObject());
2092 CHECK(root->map()->IsMap());
2093}
yangguo@chromium.orgde0db002012-06-22 13:44:28 +00002094
2095
2096// Implemented in the test-alloc.cc test suite.
2097void SimulateFullSpace(PagedSpace* space);
2098
2099
2100TEST(ReleaseOverReservedPages) {
2101 i::FLAG_trace_gc = true;
jkummerow@chromium.org000f7fb2012-08-01 11:14:42 +00002102 // The optimizer can allocate stuff, messing up the test.
2103 i::FLAG_crankshaft = false;
2104 i::FLAG_always_opt = false;
yangguo@chromium.orgde0db002012-06-22 13:44:28 +00002105 InitializeVM();
2106 v8::HandleScope scope;
2107 static const int number_of_test_pages = 20;
2108
2109 // Prepare many pages with low live-bytes count.
2110 PagedSpace* old_pointer_space = HEAP->old_pointer_space();
2111 CHECK_EQ(1, old_pointer_space->CountTotalPages());
2112 for (int i = 0; i < number_of_test_pages; i++) {
2113 AlwaysAllocateScope always_allocate;
2114 SimulateFullSpace(old_pointer_space);
2115 FACTORY->NewFixedArray(1, TENURED);
2116 }
2117 CHECK_EQ(number_of_test_pages + 1, old_pointer_space->CountTotalPages());
2118
2119 // Triggering one GC will cause a lot of garbage to be discovered but
2120 // even spread across all allocated pages.
2121 HEAP->CollectAllGarbage(Heap::kNoGCFlags, "triggered for preparation");
2122 CHECK_EQ(number_of_test_pages + 1, old_pointer_space->CountTotalPages());
2123
2124 // Triggering subsequent GCs should cause at least half of the pages
2125 // to be released to the OS after at most two cycles.
2126 HEAP->CollectAllGarbage(Heap::kNoGCFlags, "triggered by test 1");
2127 CHECK_GE(number_of_test_pages + 1, old_pointer_space->CountTotalPages());
2128 HEAP->CollectAllGarbage(Heap::kNoGCFlags, "triggered by test 2");
2129 CHECK_GE(number_of_test_pages + 1, old_pointer_space->CountTotalPages() * 2);
2130
ulan@chromium.org56c14af2012-09-20 12:51:09 +00002131 // Triggering a last-resort GC should cause all pages to be released to the
2132 // OS so that other processes can seize the memory. If we get a failure here
2133 // where there are 2 pages left instead of 1, then we should increase the
2134 // size of the first page a little in SizeOfFirstPage in spaces.cc. The
2135 // first page should be small in order to reduce memory used when the VM
2136 // boots, but if the 20 small arrays don't fit on the first page then that's
2137 // an indication that it is too small.
yangguo@chromium.orgde0db002012-06-22 13:44:28 +00002138 HEAP->CollectAllAvailableGarbage("triggered really hard");
2139 CHECK_EQ(1, old_pointer_space->CountTotalPages());
2140}
yangguo@chromium.org304cc332012-07-24 07:59:48 +00002141
2142
2143TEST(Regress2237) {
2144 InitializeVM();
2145 v8::HandleScope scope;
2146 Handle<String> slice(HEAP->empty_string());
2147
2148 {
2149 // Generate a parent that lives in new-space.
2150 v8::HandleScope inner_scope;
2151 const char* c = "This text is long enough to trigger sliced strings.";
2152 Handle<String> s = FACTORY->NewStringFromAscii(CStrVector(c));
2153 CHECK(s->IsSeqAsciiString());
2154 CHECK(HEAP->InNewSpace(*s));
2155
2156 // Generate a sliced string that is based on the above parent and
2157 // lives in old-space.
2158 FillUpNewSpace(HEAP->new_space());
2159 AlwaysAllocateScope always_allocate;
2160 Handle<String> t;
2161 // TODO(mstarzinger): Unfortunately FillUpNewSpace() still leaves
2162 // some slack, so we need to allocate a few sliced strings.
2163 for (int i = 0; i < 16; i++) {
2164 t = FACTORY->NewProperSubString(s, 5, 35);
2165 }
2166 CHECK(t->IsSlicedString());
2167 CHECK(!HEAP->InNewSpace(*t));
2168 *slice.location() = *t.location();
2169 }
2170
2171 CHECK(SlicedString::cast(*slice)->parent()->IsSeqAsciiString());
2172 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
2173 CHECK(SlicedString::cast(*slice)->parent()->IsSeqAsciiString());
2174}
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +00002175
2176
2177#ifdef OBJECT_PRINT
2178TEST(PrintSharedFunctionInfo) {
2179 InitializeVM();
2180 v8::HandleScope scope;
2181 const char* source = "f = function() { return 987654321; }\n"
2182 "g = function() { return 123456789; }\n";
2183 CompileRun(source);
2184 Handle<JSFunction> g =
2185 v8::Utils::OpenHandle(
2186 *v8::Handle<v8::Function>::Cast(
2187 v8::Context::GetCurrent()->Global()->Get(v8_str("g"))));
2188
2189 AssertNoAllocation no_alloc;
2190 g->shared()->PrintLn();
2191}
2192#endif // OBJECT_PRINT
jkummerow@chromium.org000f7fb2012-08-01 11:14:42 +00002193
2194
2195TEST(Regress2211) {
2196 InitializeVM();
2197 v8::HandleScope scope;
2198
2199 v8::Handle<v8::String> value = v8_str("val string");
2200 Smi* hash = Smi::FromInt(321);
2201 Heap* heap = Isolate::Current()->heap();
2202
2203 for (int i = 0; i < 2; i++) {
2204 // Store identity hash first and common hidden property second.
2205 v8::Handle<v8::Object> obj = v8::Object::New();
2206 Handle<JSObject> internal_obj = v8::Utils::OpenHandle(*obj);
2207 CHECK(internal_obj->HasFastProperties());
2208
2209 // In the first iteration, set hidden value first and identity hash second.
2210 // In the second iteration, reverse the order.
2211 if (i == 0) obj->SetHiddenValue(v8_str("key string"), value);
2212 MaybeObject* maybe_obj = internal_obj->SetIdentityHash(hash,
2213 ALLOW_CREATION);
2214 CHECK(!maybe_obj->IsFailure());
2215 if (i == 1) obj->SetHiddenValue(v8_str("key string"), value);
2216
2217 // Check values.
2218 CHECK_EQ(hash,
2219 internal_obj->GetHiddenProperty(heap->identity_hash_symbol()));
2220 CHECK(value->Equals(obj->GetHiddenValue(v8_str("key string"))));
2221
2222 // Check size.
2223 DescriptorArray* descriptors = internal_obj->map()->instance_descriptors();
2224 ObjectHashTable* hashtable = ObjectHashTable::cast(
2225 internal_obj->FastPropertyAt(descriptors->GetFieldIndex(0)));
2226 // HashTable header (5) and 4 initial entries (8).
2227 CHECK_LE(hashtable->SizeFor(hashtable->length()), 13 * kPointerSize);
2228 }
2229}
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002230
2231
2232TEST(IncrementalMarkingClearsTypeFeedbackCells) {
2233 if (i::FLAG_always_opt) return;
2234 InitializeVM();
2235 v8::HandleScope scope;
2236 v8::Local<v8::Value> fun1, fun2;
2237
2238 {
2239 LocalContext env;
2240 CompileRun("function fun() {};");
2241 fun1 = env->Global()->Get(v8_str("fun"));
2242 }
2243
2244 {
2245 LocalContext env;
2246 CompileRun("function fun() {};");
2247 fun2 = env->Global()->Get(v8_str("fun"));
2248 }
2249
2250 // Prepare function f that contains type feedback for closures
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00002251 // originating from two different native contexts.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002252 v8::Context::GetCurrent()->Global()->Set(v8_str("fun1"), fun1);
2253 v8::Context::GetCurrent()->Global()->Set(v8_str("fun2"), fun2);
2254 CompileRun("function f(a, b) { a(); b(); } f(fun1, fun2);");
2255 Handle<JSFunction> f =
2256 v8::Utils::OpenHandle(
2257 *v8::Handle<v8::Function>::Cast(
2258 v8::Context::GetCurrent()->Global()->Get(v8_str("f"))));
2259 Handle<TypeFeedbackCells> cells(TypeFeedbackInfo::cast(
2260 f->shared()->code()->type_feedback_info())->type_feedback_cells());
2261
2262 CHECK_EQ(2, cells->CellCount());
2263 CHECK(cells->Cell(0)->value()->IsJSFunction());
2264 CHECK(cells->Cell(1)->value()->IsJSFunction());
2265
2266 SimulateIncrementalMarking();
2267 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
2268
2269 CHECK_EQ(2, cells->CellCount());
2270 CHECK(cells->Cell(0)->value()->IsTheHole());
2271 CHECK(cells->Cell(1)->value()->IsTheHole());
2272}
2273
2274
2275static Code* FindFirstIC(Code* code, Code::Kind kind) {
2276 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
2277 RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
2278 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) |
2279 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT);
2280 for (RelocIterator it(code, mask); !it.done(); it.next()) {
2281 RelocInfo* info = it.rinfo();
2282 Code* target = Code::GetCodeFromTargetAddress(info->target_address());
2283 if (target->is_inline_cache_stub() && target->kind() == kind) {
2284 return target;
2285 }
2286 }
2287 return NULL;
2288}
2289
2290
2291TEST(IncrementalMarkingPreservesMonomorhpicIC) {
2292 if (i::FLAG_always_opt) return;
2293 InitializeVM();
2294 v8::HandleScope scope;
2295
2296 // Prepare function f that contains a monomorphic IC for object
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00002297 // originating from the same native context.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002298 CompileRun("function fun() { this.x = 1; }; var obj = new fun();"
2299 "function f(o) { return o.x; } f(obj); f(obj);");
2300 Handle<JSFunction> f =
2301 v8::Utils::OpenHandle(
2302 *v8::Handle<v8::Function>::Cast(
2303 v8::Context::GetCurrent()->Global()->Get(v8_str("f"))));
2304
2305 Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
2306 CHECK(ic_before->ic_state() == MONOMORPHIC);
2307
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002308 SimulateIncrementalMarking();
2309 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
2310
2311 Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
2312 CHECK(ic_after->ic_state() == MONOMORPHIC);
2313}
2314
2315
2316TEST(IncrementalMarkingClearsMonomorhpicIC) {
2317 if (i::FLAG_always_opt) return;
2318 InitializeVM();
2319 v8::HandleScope scope;
2320 v8::Local<v8::Value> obj1;
2321
2322 {
2323 LocalContext env;
2324 CompileRun("function fun() { this.x = 1; }; var obj = new fun();");
2325 obj1 = env->Global()->Get(v8_str("obj"));
2326 }
2327
2328 // Prepare function f that contains a monomorphic IC for object
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00002329 // originating from a different native context.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002330 v8::Context::GetCurrent()->Global()->Set(v8_str("obj1"), obj1);
2331 CompileRun("function f(o) { return o.x; } f(obj1); f(obj1);");
2332 Handle<JSFunction> f =
2333 v8::Utils::OpenHandle(
2334 *v8::Handle<v8::Function>::Cast(
2335 v8::Context::GetCurrent()->Global()->Get(v8_str("f"))));
2336
2337 Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
2338 CHECK(ic_before->ic_state() == MONOMORPHIC);
2339
2340 // Fire context dispose notification.
2341 v8::V8::ContextDisposedNotification();
2342 SimulateIncrementalMarking();
2343 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
2344
2345 Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
2346 CHECK(ic_after->ic_state() == UNINITIALIZED);
2347}
2348
2349
2350TEST(IncrementalMarkingClearsPolymorhpicIC) {
2351 if (i::FLAG_always_opt) return;
2352 InitializeVM();
2353 v8::HandleScope scope;
2354 v8::Local<v8::Value> obj1, obj2;
2355
2356 {
2357 LocalContext env;
2358 CompileRun("function fun() { this.x = 1; }; var obj = new fun();");
2359 obj1 = env->Global()->Get(v8_str("obj"));
2360 }
2361
2362 {
2363 LocalContext env;
2364 CompileRun("function fun() { this.x = 2; }; var obj = new fun();");
2365 obj2 = env->Global()->Get(v8_str("obj"));
2366 }
2367
2368 // Prepare function f that contains a polymorphic IC for objects
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00002369 // originating from two different native contexts.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002370 v8::Context::GetCurrent()->Global()->Set(v8_str("obj1"), obj1);
2371 v8::Context::GetCurrent()->Global()->Set(v8_str("obj2"), obj2);
2372 CompileRun("function f(o) { return o.x; } f(obj1); f(obj1); f(obj2);");
2373 Handle<JSFunction> f =
2374 v8::Utils::OpenHandle(
2375 *v8::Handle<v8::Function>::Cast(
2376 v8::Context::GetCurrent()->Global()->Get(v8_str("f"))));
2377
2378 Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
2379 CHECK(ic_before->ic_state() == MEGAMORPHIC);
2380
2381 // Fire context dispose notification.
2382 v8::V8::ContextDisposedNotification();
2383 SimulateIncrementalMarking();
2384 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
2385
2386 Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
2387 CHECK(ic_after->ic_state() == UNINITIALIZED);
2388}
yangguo@chromium.org355cfd12012-08-29 15:32:24 +00002389
2390
2391class SourceResource: public v8::String::ExternalAsciiStringResource {
2392 public:
2393 explicit SourceResource(const char* data)
2394 : data_(data), length_(strlen(data)) { }
2395
2396 virtual void Dispose() {
2397 i::DeleteArray(data_);
2398 data_ = NULL;
2399 }
2400
2401 const char* data() const { return data_; }
2402
2403 size_t length() const { return length_; }
2404
2405 bool IsDisposed() { return data_ == NULL; }
2406
2407 private:
2408 const char* data_;
2409 size_t length_;
2410};
2411
2412
2413TEST(ReleaseStackTraceData) {
2414 // Test that the data retained by the Error.stack accessor is released
2415 // after the first time the accessor is fired. We use external string
2416 // to check whether the data is being released since the external string
2417 // resource's callback is fired when the external string is GC'ed.
2418 InitializeVM();
2419 v8::HandleScope scope;
2420 static const char* source = "var error = 1; "
2421 "try { "
2422 " throw new Error(); "
2423 "} catch (e) { "
2424 " error = e; "
2425 "} ";
2426 SourceResource* resource = new SourceResource(i::StrDup(source));
2427 {
2428 v8::HandleScope scope;
2429 v8::Handle<v8::String> source_string = v8::String::NewExternal(resource);
2430 v8::Script::Compile(source_string)->Run();
2431 CHECK(!resource->IsDisposed());
2432 }
2433 HEAP->CollectAllAvailableGarbage();
2434 // External source is being retained by the stack trace.
2435 CHECK(!resource->IsDisposed());
2436
2437 CompileRun("error.stack; error.stack;");
2438 HEAP->CollectAllAvailableGarbage();
2439 // External source has been released.
2440 CHECK(resource->IsDisposed());
2441
2442 delete resource;
2443}
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002444
2445
2446TEST(Regression144230) {
2447 InitializeVM();
2448 v8::HandleScope scope;
2449
2450 // First make sure that the uninitialized CallIC stub is on a single page
2451 // that will later be selected as an evacuation candidate.
2452 {
2453 v8::HandleScope inner_scope;
2454 AlwaysAllocateScope always_allocate;
2455 SimulateFullSpace(HEAP->code_space());
2456 ISOLATE->stub_cache()->ComputeCallInitialize(9, RelocInfo::CODE_TARGET);
2457 }
2458
2459 // Second compile a CallIC and execute it once so that it gets patched to
2460 // the pre-monomorphic stub. These code objects are on yet another page.
2461 {
2462 v8::HandleScope inner_scope;
2463 AlwaysAllocateScope always_allocate;
2464 SimulateFullSpace(HEAP->code_space());
2465 CompileRun("var o = { f:function(a,b,c,d,e,f,g,h,i) {}};"
2466 "function call() { o.f(1,2,3,4,5,6,7,8,9); };"
2467 "call();");
2468 }
2469
2470 // Third we fill up the last page of the code space so that it does not get
2471 // chosen as an evacuation candidate.
2472 {
2473 v8::HandleScope inner_scope;
2474 AlwaysAllocateScope always_allocate;
2475 CompileRun("for (var i = 0; i < 2000; i++) {"
2476 " eval('function f' + i + '() { return ' + i +'; };' +"
2477 " 'f' + i + '();');"
2478 "}");
2479 }
2480 HEAP->CollectAllGarbage(Heap::kNoGCFlags);
2481
2482 // Fourth is the tricky part. Make sure the code containing the CallIC is
2483 // visited first without clearing the IC. The shared function info is then
2484 // visited later, causing the CallIC to be cleared.
2485 Handle<String> name = FACTORY->LookupAsciiSymbol("call");
2486 Handle<GlobalObject> global(ISOLATE->context()->global_object());
2487 MaybeObject* maybe_call = global->GetProperty(*name);
2488 JSFunction* call = JSFunction::cast(maybe_call->ToObjectChecked());
2489 USE(global->SetProperty(*name, Smi::FromInt(0), NONE, kNonStrictMode));
2490 ISOLATE->compilation_cache()->Clear();
2491 call->shared()->set_ic_age(HEAP->global_ic_age() + 1);
2492 Handle<Object> call_code(call->code());
2493 Handle<Object> call_function(call);
2494
2495 // Now we are ready to mess up the heap.
2496 HEAP->CollectAllGarbage(Heap::kReduceMemoryFootprintMask);
2497
2498 // Either heap verification caught the problem already or we go kaboom once
2499 // the CallIC is executed the next time.
2500 USE(global->SetProperty(*name, *call_function, NONE, kNonStrictMode));
2501 CompileRun("call();");
2502}