v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-heap.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include <stdlib.h>
29 #include <utility>
30 
31 #include "v8.h"
32 
33 #include "compilation-cache.h"
34 #include "execution.h"
35 #include "factory.h"
36 #include "macro-assembler.h"
37 #include "global-handles.h"
38 #include "stub-cache.h"
39 #include "cctest.h"
40 
41 using namespace v8::internal;
42 
43 
44 // Go through all incremental marking steps in one swoop.
45 static void SimulateIncrementalMarking() {
48  if (collector->IsConcurrentSweepingInProgress()) {
49  collector->WaitUntilSweepingCompleted();
50  }
51  CHECK(marking->IsMarking() || marking->IsStopped());
52  if (marking->IsStopped()) {
53  marking->Start();
54  }
55  CHECK(marking->IsMarking());
56  while (!marking->IsComplete()) {
58  }
59  CHECK(marking->IsComplete());
60 }
61 
62 
63 static void CheckMap(Map* map, int type, int instance_size) {
64  CHECK(map->IsHeapObject());
65 #ifdef DEBUG
66  CHECK(CcTest::heap()->Contains(map));
67 #endif
68  CHECK_EQ(CcTest::heap()->meta_map(), map->map());
69  CHECK_EQ(type, map->instance_type());
70  CHECK_EQ(instance_size, map->instance_size());
71 }
72 
73 
74 TEST(HeapMaps) {
76  Heap* heap = CcTest::heap();
77  CheckMap(heap->meta_map(), MAP_TYPE, Map::kSize);
78  CheckMap(heap->heap_number_map(), HEAP_NUMBER_TYPE, HeapNumber::kSize);
79  CheckMap(heap->fixed_array_map(), FIXED_ARRAY_TYPE, kVariableSizeSentinel);
80  CheckMap(heap->string_map(), STRING_TYPE, kVariableSizeSentinel);
81 }
82 
83 
84 static void CheckOddball(Isolate* isolate, Object* obj, const char* string) {
85  CHECK(obj->IsOddball());
86  bool exc;
87  Handle<Object> handle(obj, isolate);
88  Object* print_string =
89  *Execution::ToString(isolate, handle, &exc);
90  CHECK(String::cast(print_string)->IsUtf8EqualTo(CStrVector(string)));
91 }
92 
93 
94 static void CheckSmi(Isolate* isolate, int value, const char* string) {
95  bool exc;
96  Handle<Object> handle(Smi::FromInt(value), isolate);
97  Object* print_string =
98  *Execution::ToString(isolate, handle, &exc);
99  CHECK(String::cast(print_string)->IsUtf8EqualTo(CStrVector(string)));
100 }
101 
102 
103 static void CheckNumber(Isolate* isolate, double value, const char* string) {
104  Object* obj = CcTest::heap()->NumberFromDouble(value)->ToObjectChecked();
105  CHECK(obj->IsNumber());
106  bool exc;
107  Handle<Object> handle(obj, isolate);
108  Object* print_string =
109  *Execution::ToString(isolate, handle, &exc);
110  CHECK(String::cast(print_string)->IsUtf8EqualTo(CStrVector(string)));
111 }
112 
113 
114 static void CheckFindCodeObject(Isolate* isolate) {
115  // Test FindCodeObject
116 #define __ assm.
117 
118  Assembler assm(isolate, NULL, 0);
119 
120  __ nop(); // supported on all architectures
121 
122  CodeDesc desc;
123  assm.GetCode(&desc);
124  Heap* heap = isolate->heap();
125  Object* code = heap->CreateCode(
126  desc,
128  Handle<Code>())->ToObjectChecked();
129  CHECK(code->IsCode());
130 
131  HeapObject* obj = HeapObject::cast(code);
132  Address obj_addr = obj->address();
133 
134  for (int i = 0; i < obj->Size(); i += kPointerSize) {
135  Object* found = isolate->FindCodeObject(obj_addr + i);
136  CHECK_EQ(code, found);
137  }
138 
139  Object* copy = heap->CreateCode(
140  desc,
142  Handle<Code>())->ToObjectChecked();
143  CHECK(copy->IsCode());
144  HeapObject* obj_copy = HeapObject::cast(copy);
145  Object* not_right = isolate->FindCodeObject(obj_copy->address() +
146  obj_copy->Size() / 2);
147  CHECK(not_right != code);
148 }
149 
150 
151 TEST(HandleNull) {
153  Isolate* isolate = CcTest::i_isolate();
154  HandleScope outer_scope(isolate);
155  LocalContext context;
156  Handle<Object> n(reinterpret_cast<Object*>(NULL), isolate);
157  CHECK(!n.is_null());
158 }
159 
160 
161 TEST(HeapObjects) {
163  Isolate* isolate = CcTest::i_isolate();
164  Factory* factory = isolate->factory();
165  Heap* heap = isolate->heap();
166 
167  HandleScope sc(isolate);
168  Object* value = heap->NumberFromDouble(1.000123)->ToObjectChecked();
169  CHECK(value->IsHeapNumber());
170  CHECK(value->IsNumber());
171  CHECK_EQ(1.000123, value->Number());
172 
173  value = heap->NumberFromDouble(1.0)->ToObjectChecked();
174  CHECK(value->IsSmi());
175  CHECK(value->IsNumber());
176  CHECK_EQ(1.0, value->Number());
177 
178  value = heap->NumberFromInt32(1024)->ToObjectChecked();
179  CHECK(value->IsSmi());
180  CHECK(value->IsNumber());
181  CHECK_EQ(1024.0, value->Number());
182 
183  value = heap->NumberFromInt32(Smi::kMinValue)->ToObjectChecked();
184  CHECK(value->IsSmi());
185  CHECK(value->IsNumber());
186  CHECK_EQ(Smi::kMinValue, Smi::cast(value)->value());
187 
188  value = heap->NumberFromInt32(Smi::kMaxValue)->ToObjectChecked();
189  CHECK(value->IsSmi());
190  CHECK(value->IsNumber());
191  CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value());
192 
193 #if !defined(V8_TARGET_ARCH_X64) && !defined(V8_TARGET_ARCH_ARM64)
194  // TODO(lrn): We need a NumberFromIntptr function in order to test this.
195  value = heap->NumberFromInt32(Smi::kMinValue - 1)->ToObjectChecked();
196  CHECK(value->IsHeapNumber());
197  CHECK(value->IsNumber());
198  CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number());
199 #endif
200 
201  MaybeObject* maybe_value =
202  heap->NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1);
203  value = maybe_value->ToObjectChecked();
204  CHECK(value->IsHeapNumber());
205  CHECK(value->IsNumber());
206  CHECK_EQ(static_cast<double>(static_cast<uint32_t>(Smi::kMaxValue) + 1),
207  value->Number());
208 
209  maybe_value = heap->NumberFromUint32(static_cast<uint32_t>(1) << 31);
210  value = maybe_value->ToObjectChecked();
211  CHECK(value->IsHeapNumber());
212  CHECK(value->IsNumber());
213  CHECK_EQ(static_cast<double>(static_cast<uint32_t>(1) << 31),
214  value->Number());
215 
216  // nan oddball checks
217  CHECK(heap->nan_value()->IsNumber());
218  CHECK(std::isnan(heap->nan_value()->Number()));
219 
220  Handle<String> s = factory->NewStringFromAscii(CStrVector("fisk hest "));
221  CHECK(s->IsString());
222  CHECK_EQ(10, s->length());
223 
224  Handle<String> object_string = Handle<String>::cast(factory->Object_string());
225  Handle<GlobalObject> global(CcTest::i_isolate()->context()->global_object());
226  CHECK(JSReceiver::HasLocalProperty(global, object_string));
227 
228  // Check ToString for oddballs
229  CheckOddball(isolate, heap->true_value(), "true");
230  CheckOddball(isolate, heap->false_value(), "false");
231  CheckOddball(isolate, heap->null_value(), "null");
232  CheckOddball(isolate, heap->undefined_value(), "undefined");
233 
234  // Check ToString for Smis
235  CheckSmi(isolate, 0, "0");
236  CheckSmi(isolate, 42, "42");
237  CheckSmi(isolate, -42, "-42");
238 
239  // Check ToString for Numbers
240  CheckNumber(isolate, 1.1, "1.1");
241 
242  CheckFindCodeObject(isolate);
243 }
244 
245 
246 TEST(Tagging) {
248  int request = 24;
249  CHECK_EQ(request, static_cast<int>(OBJECT_POINTER_ALIGN(request)));
250  CHECK(Smi::FromInt(42)->IsSmi());
251  CHECK(Failure::RetryAfterGC(NEW_SPACE)->IsFailure());
253  Failure::RetryAfterGC(NEW_SPACE)->allocation_space());
255  Failure::RetryAfterGC(OLD_POINTER_SPACE)->allocation_space());
256  CHECK(Failure::Exception()->IsFailure());
257  CHECK(Smi::FromInt(Smi::kMinValue)->IsSmi());
258  CHECK(Smi::FromInt(Smi::kMaxValue)->IsSmi());
259 }
260 
261 
262 TEST(GarbageCollection) {
264  Isolate* isolate = CcTest::i_isolate();
265  Heap* heap = isolate->heap();
266  Factory* factory = isolate->factory();
267 
268  HandleScope sc(isolate);
269  // Check GC.
270  heap->CollectGarbage(NEW_SPACE);
271 
272  Handle<GlobalObject> global(CcTest::i_isolate()->context()->global_object());
273  Handle<String> name = factory->InternalizeUtf8String("theFunction");
274  Handle<String> prop_name = factory->InternalizeUtf8String("theSlot");
275  Handle<String> prop_namex = factory->InternalizeUtf8String("theSlotx");
276  Handle<String> obj_name = factory->InternalizeUtf8String("theObject");
277  Handle<Smi> twenty_three(Smi::FromInt(23), isolate);
278  Handle<Smi> twenty_four(Smi::FromInt(24), isolate);
279 
280  {
281  HandleScope inner_scope(isolate);
282  // Allocate a function and keep it in global object's property.
283  Handle<JSFunction> function =
284  factory->NewFunction(name, factory->undefined_value());
285  Handle<Map> initial_map =
287  function->set_initial_map(*initial_map);
288  JSReceiver::SetProperty(global, name, function, NONE, SLOPPY);
289  // Allocate an object. Unrooted after leaving the scope.
290  Handle<JSObject> obj = factory->NewJSObject(function);
291  JSReceiver::SetProperty(obj, prop_name, twenty_three, NONE, SLOPPY);
292  JSReceiver::SetProperty(obj, prop_namex, twenty_four, NONE, SLOPPY);
293 
294  CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
295  CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex));
296  }
297 
298  heap->CollectGarbage(NEW_SPACE);
299 
300  // Function should be alive.
301  CHECK(JSReceiver::HasLocalProperty(global, name));
302  // Check function is retained.
303  Object* func_value = CcTest::i_isolate()->context()->global_object()->
304  GetProperty(*name)->ToObjectChecked();
305  CHECK(func_value->IsJSFunction());
306  Handle<JSFunction> function(JSFunction::cast(func_value));
307 
308  {
309  HandleScope inner_scope(isolate);
310  // Allocate another object, make it reachable from global.
311  Handle<JSObject> obj = factory->NewJSObject(function);
312  JSReceiver::SetProperty(global, obj_name, obj, NONE, SLOPPY);
313  JSReceiver::SetProperty(obj, prop_name, twenty_three, NONE, SLOPPY);
314  }
315 
316  // After gc, it should survive.
317  heap->CollectGarbage(NEW_SPACE);
318 
319  CHECK(JSReceiver::HasLocalProperty(global, obj_name));
320  CHECK(CcTest::i_isolate()->context()->global_object()->
321  GetProperty(*obj_name)->ToObjectChecked()->IsJSObject());
323  GetProperty(*obj_name)->ToObjectChecked();
324  JSObject* js_obj = JSObject::cast(obj);
325  CHECK_EQ(Smi::FromInt(23), js_obj->GetProperty(*prop_name));
326 }
327 
328 
329 static void VerifyStringAllocation(Isolate* isolate, const char* string) {
330  HandleScope scope(isolate);
331  Handle<String> s = isolate->factory()->NewStringFromUtf8(CStrVector(string));
332  CHECK_EQ(StrLength(string), s->length());
333  for (int index = 0; index < s->length(); index++) {
334  CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(index));
335  }
336 }
337 
338 
341  Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
342 
343  VerifyStringAllocation(isolate, "a");
344  VerifyStringAllocation(isolate, "ab");
345  VerifyStringAllocation(isolate, "abc");
346  VerifyStringAllocation(isolate, "abcd");
347  VerifyStringAllocation(isolate, "fiskerdrengen er paa havet");
348 }
349 
350 
351 TEST(LocalHandles) {
353  Isolate* isolate = CcTest::i_isolate();
354  Factory* factory = isolate->factory();
355 
357  const char* name = "Kasper the spunky";
358  Handle<String> string = factory->NewStringFromAscii(CStrVector(name));
359  CHECK_EQ(StrLength(name), string->length());
360 }
361 
362 
365  Isolate* isolate = CcTest::i_isolate();
366  Heap* heap = isolate->heap();
367  Factory* factory = isolate->factory();
368  GlobalHandles* global_handles = isolate->global_handles();
369 
370  Handle<Object> h1;
371  Handle<Object> h2;
372  Handle<Object> h3;
373  Handle<Object> h4;
374 
375  {
376  HandleScope scope(isolate);
377 
378  Handle<Object> i = factory->NewStringFromAscii(CStrVector("fisk"));
379  Handle<Object> u = factory->NewNumber(1.12344);
380 
381  h1 = global_handles->Create(*i);
382  h2 = global_handles->Create(*u);
383  h3 = global_handles->Create(*i);
384  h4 = global_handles->Create(*u);
385  }
386 
387  // after gc, it should survive
388  heap->CollectGarbage(NEW_SPACE);
389 
390  CHECK((*h1)->IsString());
391  CHECK((*h2)->IsHeapNumber());
392  CHECK((*h3)->IsString());
393  CHECK((*h4)->IsHeapNumber());
394 
395  CHECK_EQ(*h3, *h1);
396  GlobalHandles::Destroy(h1.location());
397  GlobalHandles::Destroy(h3.location());
398 
399  CHECK_EQ(*h4, *h2);
400  GlobalHandles::Destroy(h2.location());
401  GlobalHandles::Destroy(h4.location());
402 }
403 
404 
405 static bool WeakPointerCleared = false;
406 
407 static void TestWeakGlobalHandleCallback(
409  std::pair<v8::Persistent<v8::Value>*, int>* p =
410  reinterpret_cast<std::pair<v8::Persistent<v8::Value>*, int>*>(
411  data.GetParameter());
412  if (p->second == 1234) WeakPointerCleared = true;
413  p->first->Reset();
414 }
415 
416 
417 TEST(WeakGlobalHandlesScavenge) {
418  i::FLAG_stress_compaction = false;
420  Isolate* isolate = CcTest::i_isolate();
421  Heap* heap = isolate->heap();
422  Factory* factory = isolate->factory();
423  GlobalHandles* global_handles = isolate->global_handles();
424 
425  WeakPointerCleared = false;
426 
427  Handle<Object> h1;
428  Handle<Object> h2;
429 
430  {
431  HandleScope scope(isolate);
432 
433  Handle<Object> i = factory->NewStringFromAscii(CStrVector("fisk"));
434  Handle<Object> u = factory->NewNumber(1.12344);
435 
436  h1 = global_handles->Create(*i);
437  h2 = global_handles->Create(*u);
438  }
439 
440  std::pair<Handle<Object>*, int> handle_and_id(&h2, 1234);
441  GlobalHandles::MakeWeak(h2.location(),
442  reinterpret_cast<void*>(&handle_and_id),
443  &TestWeakGlobalHandleCallback);
444 
445  // Scavenge treats weak pointers as normal roots.
446  heap->CollectGarbage(NEW_SPACE);
447 
448  CHECK((*h1)->IsString());
449  CHECK((*h2)->IsHeapNumber());
450 
451  CHECK(!WeakPointerCleared);
452  CHECK(!global_handles->IsNearDeath(h2.location()));
453  CHECK(!global_handles->IsNearDeath(h1.location()));
454 
455  GlobalHandles::Destroy(h1.location());
456  GlobalHandles::Destroy(h2.location());
457 }
458 
459 
460 TEST(WeakGlobalHandlesMark) {
462  Isolate* isolate = CcTest::i_isolate();
463  Heap* heap = isolate->heap();
464  Factory* factory = isolate->factory();
465  GlobalHandles* global_handles = isolate->global_handles();
466 
467  WeakPointerCleared = false;
468 
469  Handle<Object> h1;
470  Handle<Object> h2;
471 
472  {
473  HandleScope scope(isolate);
474 
475  Handle<Object> i = factory->NewStringFromAscii(CStrVector("fisk"));
476  Handle<Object> u = factory->NewNumber(1.12344);
477 
478  h1 = global_handles->Create(*i);
479  h2 = global_handles->Create(*u);
480  }
481 
482  // Make sure the objects are promoted.
484  heap->CollectGarbage(NEW_SPACE);
485  CHECK(!heap->InNewSpace(*h1) && !heap->InNewSpace(*h2));
486 
487  std::pair<Handle<Object>*, int> handle_and_id(&h2, 1234);
488  GlobalHandles::MakeWeak(h2.location(),
489  reinterpret_cast<void*>(&handle_and_id),
490  &TestWeakGlobalHandleCallback);
491  CHECK(!GlobalHandles::IsNearDeath(h1.location()));
492  CHECK(!GlobalHandles::IsNearDeath(h2.location()));
493 
494  // Incremental marking potentially marked handles before they turned weak.
496 
497  CHECK((*h1)->IsString());
498 
499  CHECK(WeakPointerCleared);
500  CHECK(!GlobalHandles::IsNearDeath(h1.location()));
501 
502  GlobalHandles::Destroy(h1.location());
503 }
504 
505 
506 TEST(DeleteWeakGlobalHandle) {
507  i::FLAG_stress_compaction = false;
509  Isolate* isolate = CcTest::i_isolate();
510  Heap* heap = isolate->heap();
511  Factory* factory = isolate->factory();
512  GlobalHandles* global_handles = isolate->global_handles();
513 
514  WeakPointerCleared = false;
515 
516  Handle<Object> h;
517 
518  {
519  HandleScope scope(isolate);
520 
521  Handle<Object> i = factory->NewStringFromAscii(CStrVector("fisk"));
522  h = global_handles->Create(*i);
523  }
524 
525  std::pair<Handle<Object>*, int> handle_and_id(&h, 1234);
526  GlobalHandles::MakeWeak(h.location(),
527  reinterpret_cast<void*>(&handle_and_id),
528  &TestWeakGlobalHandleCallback);
529 
530  // Scanvenge does not recognize weak reference.
531  heap->CollectGarbage(NEW_SPACE);
532 
533  CHECK(!WeakPointerCleared);
534 
535  // Mark-compact treats weak reference properly.
537 
538  CHECK(WeakPointerCleared);
539 }
540 
541 
542 static const char* not_so_random_string_table[] = {
543  "abstract",
544  "boolean",
545  "break",
546  "byte",
547  "case",
548  "catch",
549  "char",
550  "class",
551  "const",
552  "continue",
553  "debugger",
554  "default",
555  "delete",
556  "do",
557  "double",
558  "else",
559  "enum",
560  "export",
561  "extends",
562  "false",
563  "final",
564  "finally",
565  "float",
566  "for",
567  "function",
568  "goto",
569  "if",
570  "implements",
571  "import",
572  "in",
573  "instanceof",
574  "int",
575  "interface",
576  "long",
577  "native",
578  "new",
579  "null",
580  "package",
581  "private",
582  "protected",
583  "public",
584  "return",
585  "short",
586  "static",
587  "super",
588  "switch",
589  "synchronized",
590  "this",
591  "throw",
592  "throws",
593  "transient",
594  "true",
595  "try",
596  "typeof",
597  "var",
598  "void",
599  "volatile",
600  "while",
601  "with",
602  0
603 };
604 
605 
606 static void CheckInternalizedStrings(const char** strings) {
607  for (const char* string = *strings; *strings != 0; string = *strings++) {
608  Object* a;
609  MaybeObject* maybe_a = CcTest::heap()->InternalizeUtf8String(string);
610  // InternalizeUtf8String may return a failure if a GC is needed.
611  if (!maybe_a->ToObject(&a)) continue;
612  CHECK(a->IsInternalizedString());
613  Object* b;
614  MaybeObject* maybe_b = CcTest::heap()->InternalizeUtf8String(string);
615  if (!maybe_b->ToObject(&b)) continue;
616  CHECK_EQ(b, a);
617  CHECK(String::cast(b)->IsUtf8EqualTo(CStrVector(string)));
618  }
619 }
620 
621 
624 
625  CheckInternalizedStrings(not_so_random_string_table);
626  CheckInternalizedStrings(not_so_random_string_table);
627 }
628 
629 
630 TEST(FunctionAllocation) {
632  Isolate* isolate = CcTest::i_isolate();
633  Factory* factory = isolate->factory();
634 
636  Handle<String> name = factory->InternalizeUtf8String("theFunction");
637  Handle<JSFunction> function =
638  factory->NewFunction(name, factory->undefined_value());
639  Handle<Map> initial_map =
641  function->set_initial_map(*initial_map);
642 
643  Handle<Smi> twenty_three(Smi::FromInt(23), isolate);
644  Handle<Smi> twenty_four(Smi::FromInt(24), isolate);
645 
646  Handle<String> prop_name = factory->InternalizeUtf8String("theSlot");
647  Handle<JSObject> obj = factory->NewJSObject(function);
648  JSReceiver::SetProperty(obj, prop_name, twenty_three, NONE, SLOPPY);
649  CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
650  // Check that we can add properties to function objects.
651  JSReceiver::SetProperty(function, prop_name, twenty_four, NONE, SLOPPY);
652  CHECK_EQ(Smi::FromInt(24), function->GetProperty(*prop_name));
653 }
654 
655 
656 TEST(ObjectProperties) {
658  Isolate* isolate = CcTest::i_isolate();
659  Factory* factory = isolate->factory();
660 
662  String* object_string = String::cast(CcTest::heap()->Object_string());
663  Object* raw_object = CcTest::i_isolate()->context()->global_object()->
664  GetProperty(object_string)->ToObjectChecked();
665  JSFunction* object_function = JSFunction::cast(raw_object);
666  Handle<JSFunction> constructor(object_function);
667  Handle<JSObject> obj = factory->NewJSObject(constructor);
668  Handle<String> first = factory->InternalizeUtf8String("first");
669  Handle<String> second = factory->InternalizeUtf8String("second");
670 
671  Handle<Smi> one(Smi::FromInt(1), isolate);
672  Handle<Smi> two(Smi::FromInt(2), isolate);
673 
674  // check for empty
675  CHECK(!JSReceiver::HasLocalProperty(obj, first));
676 
677  // add first
678  JSReceiver::SetProperty(obj, first, one, NONE, SLOPPY);
679  CHECK(JSReceiver::HasLocalProperty(obj, first));
680 
681  // delete first
683  CHECK(!JSReceiver::HasLocalProperty(obj, first));
684 
685  // add first and then second
686  JSReceiver::SetProperty(obj, first, one, NONE, SLOPPY);
687  JSReceiver::SetProperty(obj, second, two, NONE, SLOPPY);
688  CHECK(JSReceiver::HasLocalProperty(obj, first));
689  CHECK(JSReceiver::HasLocalProperty(obj, second));
690 
691  // delete first and then second
693  CHECK(JSReceiver::HasLocalProperty(obj, second));
695  CHECK(!JSReceiver::HasLocalProperty(obj, first));
696  CHECK(!JSReceiver::HasLocalProperty(obj, second));
697 
698  // add first and then second
699  JSReceiver::SetProperty(obj, first, one, NONE, SLOPPY);
700  JSReceiver::SetProperty(obj, second, two, NONE, SLOPPY);
701  CHECK(JSReceiver::HasLocalProperty(obj, first));
702  CHECK(JSReceiver::HasLocalProperty(obj, second));
703 
704  // delete second and then first
706  CHECK(JSReceiver::HasLocalProperty(obj, first));
708  CHECK(!JSReceiver::HasLocalProperty(obj, first));
709  CHECK(!JSReceiver::HasLocalProperty(obj, second));
710 
711  // check string and internalized string match
712  const char* string1 = "fisk";
713  Handle<String> s1 = factory->NewStringFromAscii(CStrVector(string1));
714  JSReceiver::SetProperty(obj, s1, one, NONE, SLOPPY);
715  Handle<String> s1_string = factory->InternalizeUtf8String(string1);
716  CHECK(JSReceiver::HasLocalProperty(obj, s1_string));
717 
718  // check internalized string and string match
719  const char* string2 = "fugl";
720  Handle<String> s2_string = factory->InternalizeUtf8String(string2);
721  JSReceiver::SetProperty(obj, s2_string, one, NONE, SLOPPY);
722  Handle<String> s2 = factory->NewStringFromAscii(CStrVector(string2));
724 }
725 
726 
727 TEST(JSObjectMaps) {
729  Isolate* isolate = CcTest::i_isolate();
730  Factory* factory = isolate->factory();
731 
733  Handle<String> name = factory->InternalizeUtf8String("theFunction");
734  Handle<JSFunction> function =
735  factory->NewFunction(name, factory->undefined_value());
736  Handle<Map> initial_map =
738  function->set_initial_map(*initial_map);
739 
740  Handle<String> prop_name = factory->InternalizeUtf8String("theSlot");
741  Handle<JSObject> obj = factory->NewJSObject(function);
742 
743  // Set a propery
744  Handle<Smi> twenty_three(Smi::FromInt(23), isolate);
745  JSReceiver::SetProperty(obj, prop_name, twenty_three, NONE, SLOPPY);
746  CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
747 
748  // Check the map has changed
749  CHECK(*initial_map != obj->map());
750 }
751 
752 
755  Isolate* isolate = CcTest::i_isolate();
756  Factory* factory = isolate->factory();
757 
759  Handle<String> name = factory->InternalizeUtf8String("Array");
760  Object* raw_object = CcTest::i_isolate()->context()->global_object()->
761  GetProperty(*name)->ToObjectChecked();
763  JSFunction::cast(raw_object));
764 
765  // Allocate the object.
766  Handle<JSObject> object = factory->NewJSObject(function);
767  Handle<JSArray> array = Handle<JSArray>::cast(object);
768  // We just initialized the VM, no heap allocation failure yet.
769  JSArray::Initialize(array, 0);
770 
771  // Set array length to 0.
772  *JSArray::SetElementsLength(array, handle(Smi::FromInt(0), isolate));
773  CHECK_EQ(Smi::FromInt(0), array->length());
774  // Must be in fast mode.
775  CHECK(array->HasFastSmiOrObjectElements());
776 
777  // array[length] = name.
778  JSReceiver::SetElement(array, 0, name, NONE, SLOPPY);
779  CHECK_EQ(Smi::FromInt(1), array->length());
780  CHECK_EQ(*i::Object::GetElement(isolate, array, 0), *name);
781 
782  // Set array length with larger than smi value.
783  Handle<Object> length =
784  factory->NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1);
785  *JSArray::SetElementsLength(array, length);
786 
787  uint32_t int_length = 0;
788  CHECK(length->ToArrayIndex(&int_length));
789  CHECK_EQ(*length, array->length());
790  CHECK(array->HasDictionaryElements()); // Must be in slow mode.
791 
792  // array[length] = name.
793  JSReceiver::SetElement(array, int_length, name, NONE, SLOPPY);
794  uint32_t new_int_length = 0;
795  CHECK(array->length()->ToArrayIndex(&new_int_length));
796  CHECK_EQ(static_cast<double>(int_length), new_int_length - 1);
797  CHECK_EQ(*i::Object::GetElement(isolate, array, int_length), *name);
798  CHECK_EQ(*i::Object::GetElement(isolate, array, 0), *name);
799 }
800 
801 
802 TEST(JSObjectCopy) {
804  Isolate* isolate = CcTest::i_isolate();
805  Factory* factory = isolate->factory();
806 
808  String* object_string = String::cast(CcTest::heap()->Object_string());
809  Object* raw_object = CcTest::i_isolate()->context()->global_object()->
810  GetProperty(object_string)->ToObjectChecked();
811  JSFunction* object_function = JSFunction::cast(raw_object);
812  Handle<JSFunction> constructor(object_function);
813  Handle<JSObject> obj = factory->NewJSObject(constructor);
814  Handle<String> first = factory->InternalizeUtf8String("first");
815  Handle<String> second = factory->InternalizeUtf8String("second");
816 
817  Handle<Smi> one(Smi::FromInt(1), isolate);
818  Handle<Smi> two(Smi::FromInt(2), isolate);
819 
820  JSReceiver::SetProperty(obj, first, one, NONE, SLOPPY);
821  JSReceiver::SetProperty(obj, second, two, NONE, SLOPPY);
822 
823  JSReceiver::SetElement(obj, 0, first, NONE, SLOPPY);
824  JSReceiver::SetElement(obj, 1, second, NONE, SLOPPY);
825 
826  // Make the clone.
827  Handle<JSObject> clone = JSObject::Copy(obj);
828  CHECK(!clone.is_identical_to(obj));
829 
830  CHECK_EQ(*i::Object::GetElement(isolate, obj, 0),
831  *i::Object::GetElement(isolate, clone, 0));
832  CHECK_EQ(*i::Object::GetElement(isolate, obj, 1),
833  *i::Object::GetElement(isolate, clone, 1));
834 
835  CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*first));
836  CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*second));
837 
838  // Flip the values.
839  JSReceiver::SetProperty(clone, first, two, NONE, SLOPPY);
840  JSReceiver::SetProperty(clone, second, one, NONE, SLOPPY);
841 
842  JSReceiver::SetElement(clone, 0, second, NONE, SLOPPY);
843  JSReceiver::SetElement(clone, 1, first, NONE, SLOPPY);
844 
845  CHECK_EQ(*i::Object::GetElement(isolate, obj, 1),
846  *i::Object::GetElement(isolate, clone, 0));
847  CHECK_EQ(*i::Object::GetElement(isolate, obj, 0),
848  *i::Object::GetElement(isolate, clone, 1));
849 
850  CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*first));
851  CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*second));
852 }
853 
854 
855 TEST(StringAllocation) {
857  Isolate* isolate = CcTest::i_isolate();
858  Factory* factory = isolate->factory();
859 
860  const unsigned char chars[] = { 0xe5, 0xa4, 0xa7 };
861  for (int length = 0; length < 100; length++) {
863  char* non_ascii = NewArray<char>(3 * length + 1);
864  char* ascii = NewArray<char>(length + 1);
865  non_ascii[3 * length] = 0;
866  ascii[length] = 0;
867  for (int i = 0; i < length; i++) {
868  ascii[i] = 'a';
869  non_ascii[3 * i] = chars[0];
870  non_ascii[3 * i + 1] = chars[1];
871  non_ascii[3 * i + 2] = chars[2];
872  }
873  Handle<String> non_ascii_sym =
874  factory->InternalizeUtf8String(
875  Vector<const char>(non_ascii, 3 * length));
876  CHECK_EQ(length, non_ascii_sym->length());
877  Handle<String> ascii_sym =
878  factory->InternalizeOneByteString(OneByteVector(ascii, length));
879  CHECK_EQ(length, ascii_sym->length());
880  Handle<String> non_ascii_str =
881  factory->NewStringFromUtf8(Vector<const char>(non_ascii, 3 * length));
882  non_ascii_str->Hash();
883  CHECK_EQ(length, non_ascii_str->length());
884  Handle<String> ascii_str =
885  factory->NewStringFromUtf8(Vector<const char>(ascii, length));
886  ascii_str->Hash();
887  CHECK_EQ(length, ascii_str->length());
888  DeleteArray(non_ascii);
889  DeleteArray(ascii);
890  }
891 }
892 
893 
894 static int ObjectsFoundInHeap(Heap* heap, Handle<Object> objs[], int size) {
895  // Count the number of objects found in the heap.
896  int found_count = 0;
897  heap->EnsureHeapIsIterable();
898  HeapIterator iterator(heap);
899  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
900  for (int i = 0; i < size; i++) {
901  if (*objs[i] == obj) {
902  found_count++;
903  }
904  }
905  }
906  return found_count;
907 }
908 
909 
910 TEST(Iteration) {
912  Isolate* isolate = CcTest::i_isolate();
913  Factory* factory = isolate->factory();
915 
916  // Array of objects to scan haep for.
917  const int objs_count = 6;
918  Handle<Object> objs[objs_count];
919  int next_objs_index = 0;
920 
921  // Allocate a JS array to OLD_POINTER_SPACE and NEW_SPACE
922  objs[next_objs_index++] = factory->NewJSArray(10);
923  objs[next_objs_index++] = factory->NewJSArray(10,
925  TENURED);
926 
927  // Allocate a small string to OLD_DATA_SPACE and NEW_SPACE
928  objs[next_objs_index++] =
929  factory->NewStringFromAscii(CStrVector("abcdefghij"));
930  objs[next_objs_index++] =
931  factory->NewStringFromAscii(CStrVector("abcdefghij"), TENURED);
932 
933  // Allocate a large string (for large object space).
934  int large_size = Page::kMaxRegularHeapObjectSize + 1;
935  char* str = new char[large_size];
936  for (int i = 0; i < large_size - 1; ++i) str[i] = 'a';
937  str[large_size - 1] = '\0';
938  objs[next_objs_index++] =
939  factory->NewStringFromAscii(CStrVector(str), TENURED);
940  delete[] str;
941 
942  // Add a Map object to look for.
943  objs[next_objs_index++] = Handle<Map>(HeapObject::cast(*objs[0])->map());
944 
945  CHECK_EQ(objs_count, next_objs_index);
946  CHECK_EQ(objs_count, ObjectsFoundInHeap(CcTest::heap(), objs, objs_count));
947 }
948 
949 
950 TEST(EmptyHandleEscapeFrom) {
952 
954  Handle<JSObject> runaway;
955 
956  {
958  Handle<JSObject> empty;
959  runaway = empty.EscapeFrom(&nested);
960  }
961 
962  CHECK(runaway.is_null());
963 }
964 
965 
966 static int LenFromSize(int size) {
967  return (size - FixedArray::kHeaderSize) / kPointerSize;
968 }
969 
970 
971 TEST(Regression39128) {
972  // Test case for crbug.com/39128.
974  Isolate* isolate = CcTest::i_isolate();
975  Factory* factory = isolate->factory();
976  Heap* heap = isolate->heap();
977 
978  // Increase the chance of 'bump-the-pointer' allocation in old space.
980 
982 
983  // The plan: create JSObject which references objects in new space.
984  // Then clone this object (forcing it to go into old space) and check
985  // that region dirty marks are updated correctly.
986 
987  // Step 1: prepare a map for the object. We add 1 inobject property to it.
988  Handle<JSFunction> object_ctor(
989  CcTest::i_isolate()->native_context()->object_function());
990  CHECK(object_ctor->has_initial_map());
991  Handle<Map> object_map(object_ctor->initial_map());
992  // Create a map with single inobject property.
993  Handle<Map> my_map = factory->CopyMap(object_map, 1);
994  int n_properties = my_map->inobject_properties();
995  CHECK_GT(n_properties, 0);
996 
997  int object_size = my_map->instance_size();
998 
999  // Step 2: allocate a lot of objects so to almost fill new space: we need
1000  // just enough room to allocate JSObject and thus fill the newspace.
1001 
1002  int allocation_amount = Min(FixedArray::kMaxSize,
1004  int allocation_len = LenFromSize(allocation_amount);
1005  NewSpace* new_space = heap->new_space();
1006  Address* top_addr = new_space->allocation_top_address();
1007  Address* limit_addr = new_space->allocation_limit_address();
1008  while ((*limit_addr - *top_addr) > allocation_amount) {
1009  CHECK(!heap->always_allocate());
1010  Object* array = heap->AllocateFixedArray(allocation_len)->ToObjectChecked();
1011  CHECK(!array->IsFailure());
1012  CHECK(new_space->Contains(array));
1013  }
1014 
1015  // Step 3: now allocate fixed array and JSObject to fill the whole new space.
1016  int to_fill = static_cast<int>(*limit_addr - *top_addr - object_size);
1017  int fixed_array_len = LenFromSize(to_fill);
1018  CHECK(fixed_array_len < FixedArray::kMaxLength);
1019 
1020  CHECK(!heap->always_allocate());
1021  Object* array = heap->AllocateFixedArray(fixed_array_len)->ToObjectChecked();
1022  CHECK(!array->IsFailure());
1023  CHECK(new_space->Contains(array));
1024 
1025  Object* object = heap->AllocateJSObjectFromMap(*my_map)->ToObjectChecked();
1026  CHECK(new_space->Contains(object));
1027  JSObject* jsobject = JSObject::cast(object);
1028  CHECK_EQ(0, FixedArray::cast(jsobject->elements())->length());
1029  CHECK_EQ(0, jsobject->properties()->length());
1030  // Create a reference to object in new space in jsobject.
1031  jsobject->FastPropertyAtPut(-1, array);
1032 
1033  CHECK_EQ(0, static_cast<int>(*limit_addr - *top_addr));
1034 
1035  // Step 4: clone jsobject, but force always allocate first to create a clone
1036  // in old pointer space.
1037  Address old_pointer_space_top = heap->old_pointer_space()->top();
1038  AlwaysAllocateScope aa_scope(isolate);
1039  Object* clone_obj = heap->CopyJSObject(jsobject)->ToObjectChecked();
1040  JSObject* clone = JSObject::cast(clone_obj);
1041  if (clone->address() != old_pointer_space_top) {
1042  // Alas, got allocated from free list, we cannot do checks.
1043  return;
1044  }
1045  CHECK(heap->old_pointer_space()->Contains(clone->address()));
1046 }
1047 
1048 
1049 TEST(TestCodeFlushing) {
1050  // If we do not flush code this test is invalid.
1051  if (!FLAG_flush_code) return;
1052  i::FLAG_allow_natives_syntax = true;
1053  i::FLAG_optimize_for_size = false;
1055  Isolate* isolate = CcTest::i_isolate();
1056  Factory* factory = isolate->factory();
1058  const char* source = "function foo() {"
1059  " var x = 42;"
1060  " var y = 42;"
1061  " var z = x + y;"
1062  "};"
1063  "foo()";
1064  Handle<String> foo_name = factory->InternalizeUtf8String("foo");
1065 
1066  // This compile will add the code to the compilation cache.
1067  { v8::HandleScope scope(CcTest::isolate());
1068  CompileRun(source);
1069  }
1070 
1071  // Check function is compiled.
1072  Object* func_value = CcTest::i_isolate()->context()->global_object()->
1073  GetProperty(*foo_name)->ToObjectChecked();
1074  CHECK(func_value->IsJSFunction());
1075  Handle<JSFunction> function(JSFunction::cast(func_value));
1076  CHECK(function->shared()->is_compiled());
1077 
1078  // The code will survive at least two GCs.
1081  CHECK(function->shared()->is_compiled());
1082 
1083  // Simulate several GCs that use full marking.
1084  const int kAgingThreshold = 6;
1085  for (int i = 0; i < kAgingThreshold; i++) {
1087  }
1088 
1089  // foo should no longer be in the compilation cache
1090  CHECK(!function->shared()->is_compiled() || function->IsOptimized());
1091  CHECK(!function->is_compiled() || function->IsOptimized());
1092  // Call foo to get it recompiled.
1093  CompileRun("foo()");
1094  CHECK(function->shared()->is_compiled());
1095  CHECK(function->is_compiled());
1096 }
1097 
1098 
1099 TEST(TestCodeFlushingPreAged) {
1100  // If we do not flush code this test is invalid.
1101  if (!FLAG_flush_code) return;
1102  i::FLAG_allow_natives_syntax = true;
1103  i::FLAG_optimize_for_size = true;
1105  Isolate* isolate = Isolate::Current();
1106  Factory* factory = isolate->factory();
1108  const char* source = "function foo() {"
1109  " var x = 42;"
1110  " var y = 42;"
1111  " var z = x + y;"
1112  "};"
1113  "foo()";
1114  Handle<String> foo_name = factory->InternalizeUtf8String("foo");
1115 
1116  // Compile foo, but don't run it.
1117  { v8::HandleScope scope(CcTest::isolate());
1118  CompileRun(source);
1119  }
1120 
1121  // Check function is compiled.
1122  Object* func_value = Isolate::Current()->context()->global_object()->
1123  GetProperty(*foo_name)->ToObjectChecked();
1124  CHECK(func_value->IsJSFunction());
1125  Handle<JSFunction> function(JSFunction::cast(func_value));
1126  CHECK(function->shared()->is_compiled());
1127 
1128  // The code has been run so will survive at least one GC.
1130  CHECK(function->shared()->is_compiled());
1131 
1132  // The code was only run once, so it should be pre-aged and collected on the
1133  // next GC.
1135  CHECK(!function->shared()->is_compiled() || function->IsOptimized());
1136 
1137  // Execute the function again twice, and ensure it is reset to the young age.
1138  { v8::HandleScope scope(CcTest::isolate());
1139  CompileRun("foo();"
1140  "foo();");
1141  }
1142 
1143  // The code will survive at least two GC now that it is young again.
1146  CHECK(function->shared()->is_compiled());
1147 
1148  // Simulate several GCs that use full marking.
1149  const int kAgingThreshold = 6;
1150  for (int i = 0; i < kAgingThreshold; i++) {
1152  }
1153 
1154  // foo should no longer be in the compilation cache
1155  CHECK(!function->shared()->is_compiled() || function->IsOptimized());
1156  CHECK(!function->is_compiled() || function->IsOptimized());
1157  // Call foo to get it recompiled.
1158  CompileRun("foo()");
1159  CHECK(function->shared()->is_compiled());
1160  CHECK(function->is_compiled());
1161 }
1162 
1163 
1164 TEST(TestCodeFlushingIncremental) {
1165  // If we do not flush code this test is invalid.
1166  if (!FLAG_flush_code || !FLAG_flush_code_incrementally) return;
1167  i::FLAG_allow_natives_syntax = true;
1168  i::FLAG_optimize_for_size = false;
1170  Isolate* isolate = CcTest::i_isolate();
1171  Factory* factory = isolate->factory();
1173  const char* source = "function foo() {"
1174  " var x = 42;"
1175  " var y = 42;"
1176  " var z = x + y;"
1177  "};"
1178  "foo()";
1179  Handle<String> foo_name = factory->InternalizeUtf8String("foo");
1180 
1181  // This compile will add the code to the compilation cache.
1182  { v8::HandleScope scope(CcTest::isolate());
1183  CompileRun(source);
1184  }
1185 
1186  // Check function is compiled.
1187  Object* func_value = CcTest::i_isolate()->context()->global_object()->
1188  GetProperty(*foo_name)->ToObjectChecked();
1189  CHECK(func_value->IsJSFunction());
1190  Handle<JSFunction> function(JSFunction::cast(func_value));
1191  CHECK(function->shared()->is_compiled());
1192 
1193  // The code will survive at least two GCs.
1196  CHECK(function->shared()->is_compiled());
1197 
1198  // Simulate several GCs that use incremental marking.
1199  const int kAgingThreshold = 6;
1200  for (int i = 0; i < kAgingThreshold; i++) {
1201  SimulateIncrementalMarking();
1203  }
1204  CHECK(!function->shared()->is_compiled() || function->IsOptimized());
1205  CHECK(!function->is_compiled() || function->IsOptimized());
1206 
1207  // This compile will compile the function again.
1208  { v8::HandleScope scope(CcTest::isolate());
1209  CompileRun("foo();");
1210  }
1211 
1212  // Simulate several GCs that use incremental marking but make sure
1213  // the loop breaks once the function is enqueued as a candidate.
1214  for (int i = 0; i < kAgingThreshold; i++) {
1215  SimulateIncrementalMarking();
1216  if (!function->next_function_link()->IsUndefined()) break;
1218  }
1219 
1220  // Force optimization while incremental marking is active and while
1221  // the function is enqueued as a candidate.
1222  { v8::HandleScope scope(CcTest::isolate());
1223  CompileRun("%OptimizeFunctionOnNextCall(foo); foo();");
1224  }
1225 
1226  // Simulate one final GC to make sure the candidate queue is sane.
1228  CHECK(function->shared()->is_compiled() || !function->IsOptimized());
1229  CHECK(function->is_compiled() || !function->IsOptimized());
1230 }
1231 
1232 
1233 TEST(TestCodeFlushingIncrementalScavenge) {
1234  // If we do not flush code this test is invalid.
1235  if (!FLAG_flush_code || !FLAG_flush_code_incrementally) return;
1236  i::FLAG_allow_natives_syntax = true;
1237  i::FLAG_optimize_for_size = false;
1239  Isolate* isolate = CcTest::i_isolate();
1240  Factory* factory = isolate->factory();
1242  const char* source = "var foo = function() {"
1243  " var x = 42;"
1244  " var y = 42;"
1245  " var z = x + y;"
1246  "};"
1247  "foo();"
1248  "var bar = function() {"
1249  " var x = 23;"
1250  "};"
1251  "bar();";
1252  Handle<String> foo_name = factory->InternalizeUtf8String("foo");
1253  Handle<String> bar_name = factory->InternalizeUtf8String("bar");
1254 
1255  // Perfrom one initial GC to enable code flushing.
1257 
1258  // This compile will add the code to the compilation cache.
1259  { v8::HandleScope scope(CcTest::isolate());
1260  CompileRun(source);
1261  }
1262 
1263  // Check functions are compiled.
1264  Object* func_value = CcTest::i_isolate()->context()->global_object()->
1265  GetProperty(*foo_name)->ToObjectChecked();
1266  CHECK(func_value->IsJSFunction());
1267  Handle<JSFunction> function(JSFunction::cast(func_value));
1268  CHECK(function->shared()->is_compiled());
1269  Object* func_value2 = CcTest::i_isolate()->context()->global_object()->
1270  GetProperty(*bar_name)->ToObjectChecked();
1271  CHECK(func_value2->IsJSFunction());
1272  Handle<JSFunction> function2(JSFunction::cast(func_value2));
1273  CHECK(function2->shared()->is_compiled());
1274 
1275  // Clear references to functions so that one of them can die.
1276  { v8::HandleScope scope(CcTest::isolate());
1277  CompileRun("foo = 0; bar = 0;");
1278  }
1279 
1280  // Bump the code age so that flushing is triggered while the function
1281  // object is still located in new-space.
1282  const int kAgingThreshold = 6;
1283  for (int i = 0; i < kAgingThreshold; i++) {
1284  function->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
1285  function2->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
1286  }
1287 
1288  // Simulate incremental marking so that the functions are enqueued as
1289  // code flushing candidates. Then kill one of the functions. Finally
1290  // perform a scavenge while incremental marking is still running.
1291  SimulateIncrementalMarking();
1292  *function2.location() = NULL;
1293  CcTest::heap()->CollectGarbage(NEW_SPACE, "test scavenge while marking");
1294 
1295  // Simulate one final GC to make sure the candidate queue is sane.
1297  CHECK(!function->shared()->is_compiled() || function->IsOptimized());
1298  CHECK(!function->is_compiled() || function->IsOptimized());
1299 }
1300 
1301 
1302 TEST(TestCodeFlushingIncrementalAbort) {
1303  // If we do not flush code this test is invalid.
1304  if (!FLAG_flush_code || !FLAG_flush_code_incrementally) return;
1305  i::FLAG_allow_natives_syntax = true;
1306  i::FLAG_optimize_for_size = false;
1308  Isolate* isolate = CcTest::i_isolate();
1309  Factory* factory = isolate->factory();
1310  Heap* heap = isolate->heap();
1312  const char* source = "function foo() {"
1313  " var x = 42;"
1314  " var y = 42;"
1315  " var z = x + y;"
1316  "};"
1317  "foo()";
1318  Handle<String> foo_name = factory->InternalizeUtf8String("foo");
1319 
1320  // This compile will add the code to the compilation cache.
1321  { v8::HandleScope scope(CcTest::isolate());
1322  CompileRun(source);
1323  }
1324 
1325  // Check function is compiled.
1326  Object* func_value = CcTest::i_isolate()->context()->global_object()->
1327  GetProperty(*foo_name)->ToObjectChecked();
1328  CHECK(func_value->IsJSFunction());
1329  Handle<JSFunction> function(JSFunction::cast(func_value));
1330  CHECK(function->shared()->is_compiled());
1331 
1332  // The code will survive at least two GCs.
1335  CHECK(function->shared()->is_compiled());
1336 
1337  // Bump the code age so that flushing is triggered.
1338  const int kAgingThreshold = 6;
1339  for (int i = 0; i < kAgingThreshold; i++) {
1340  function->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
1341  }
1342 
1343  // Simulate incremental marking so that the function is enqueued as
1344  // code flushing candidate.
1345  SimulateIncrementalMarking();
1346 
1347 #ifdef ENABLE_DEBUGGER_SUPPORT
1348  // Enable the debugger and add a breakpoint while incremental marking
1349  // is running so that incremental marking aborts and code flushing is
1350  // disabled.
1351  int position = 0;
1352  Handle<Object> breakpoint_object(Smi::FromInt(0), isolate);
1353  isolate->debug()->SetBreakPoint(function, breakpoint_object, &position);
1354  isolate->debug()->ClearAllBreakPoints();
1355 #endif // ENABLE_DEBUGGER_SUPPORT
1356 
1357  // Force optimization now that code flushing is disabled.
1358  { v8::HandleScope scope(CcTest::isolate());
1359  CompileRun("%OptimizeFunctionOnNextCall(foo); foo();");
1360  }
1361 
1362  // Simulate one final GC to make sure the candidate queue is sane.
1364  CHECK(function->shared()->is_compiled() || !function->IsOptimized());
1365  CHECK(function->is_compiled() || !function->IsOptimized());
1366 }
1367 
1368 
1369 // Count the number of native contexts in the weak list of native contexts.
1371  int count = 0;
1372  Object* object = CcTest::heap()->native_contexts_list();
1373  while (!object->IsUndefined()) {
1374  count++;
1375  object = Context::cast(object)->get(Context::NEXT_CONTEXT_LINK);
1376  }
1377  return count;
1378 }
1379 
1380 
1381 // Count the number of user functions in the weak list of optimized
1382 // functions attached to a native context.
1383 static int CountOptimizedUserFunctions(v8::Handle<v8::Context> context) {
1384  int count = 0;
1385  Handle<Context> icontext = v8::Utils::OpenHandle(*context);
1386  Object* object = icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST);
1387  while (object->IsJSFunction() && !JSFunction::cast(object)->IsBuiltin()) {
1388  count++;
1389  object = JSFunction::cast(object)->next_function_link();
1390  }
1391  return count;
1392 }
1393 
1394 
1395 TEST(TestInternalWeakLists) {
1397 
1398  // Some flags turn Scavenge collections into Mark-sweep collections
1399  // and hence are incompatible with this test case.
1400  if (FLAG_gc_global || FLAG_stress_compaction) return;
1401 
1402  static const int kNumTestContexts = 10;
1403 
1404  Isolate* isolate = CcTest::i_isolate();
1405  Heap* heap = isolate->heap();
1406  HandleScope scope(isolate);
1407  v8::Handle<v8::Context> ctx[kNumTestContexts];
1408 
1410 
1411  // Create a number of global contests which gets linked together.
1412  for (int i = 0; i < kNumTestContexts; i++) {
1413  ctx[i] = v8::Context::New(CcTest::isolate());
1414 
1415  // Collect garbage that might have been created by one of the
1416  // installed extensions.
1417  isolate->compilation_cache()->Clear();
1419 
1420  bool opt = (FLAG_always_opt && isolate->use_crankshaft());
1421 
1422  CHECK_EQ(i + 1, CountNativeContexts());
1423 
1424  ctx[i]->Enter();
1425 
1426  // Create a handle scope so no function objects get stuch in the outer
1427  // handle scope
1428  HandleScope scope(isolate);
1429  const char* source = "function f1() { };"
1430  "function f2() { };"
1431  "function f3() { };"
1432  "function f4() { };"
1433  "function f5() { };";
1434  CompileRun(source);
1435  CHECK_EQ(0, CountOptimizedUserFunctions(ctx[i]));
1436  CompileRun("f1()");
1437  CHECK_EQ(opt ? 1 : 0, CountOptimizedUserFunctions(ctx[i]));
1438  CompileRun("f2()");
1439  CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i]));
1440  CompileRun("f3()");
1441  CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i]));
1442  CompileRun("f4()");
1443  CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i]));
1444  CompileRun("f5()");
1445  CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i]));
1446 
1447  // Remove function f1, and
1448  CompileRun("f1=null");
1449 
1450  // Scavenge treats these references as strong.
1451  for (int j = 0; j < 10; j++) {
1453  CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i]));
1454  }
1455 
1456  // Mark compact handles the weak references.
1457  isolate->compilation_cache()->Clear();
1459  CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i]));
1460 
1461  // Get rid of f3 and f5 in the same way.
1462  CompileRun("f3=null");
1463  for (int j = 0; j < 10; j++) {
1465  CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i]));
1466  }
1468  CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i]));
1469  CompileRun("f5=null");
1470  for (int j = 0; j < 10; j++) {
1472  CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i]));
1473  }
1475  CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i]));
1476 
1477  ctx[i]->Exit();
1478  }
1479 
1480  // Force compilation cache cleanup.
1483 
1484  // Dispose the native contexts one by one.
1485  for (int i = 0; i < kNumTestContexts; i++) {
1486  // TODO(dcarney): is there a better way to do this?
1487  i::Object** unsafe = reinterpret_cast<i::Object**>(*ctx[i]);
1488  *unsafe = CcTest::heap()->undefined_value();
1489  ctx[i].Clear();
1490 
1491  // Scavenge treats these references as strong.
1492  for (int j = 0; j < 10; j++) {
1494  CHECK_EQ(kNumTestContexts - i, CountNativeContexts());
1495  }
1496 
1497  // Mark compact handles the weak references.
1499  CHECK_EQ(kNumTestContexts - i - 1, CountNativeContexts());
1500  }
1501 
1503 }
1504 
1505 
1506 // Count the number of native contexts in the weak list of native contexts
1507 // causing a GC after the specified number of elements.
1508 static int CountNativeContextsWithGC(Isolate* isolate, int n) {
1509  Heap* heap = isolate->heap();
1510  int count = 0;
1511  Handle<Object> object(heap->native_contexts_list(), isolate);
1512  while (!object->IsUndefined()) {
1513  count++;
1514  if (count == n) heap->CollectAllGarbage(Heap::kNoGCFlags);
1515  object =
1517  isolate);
1518  }
1519  return count;
1520 }
1521 
1522 
1523 // Count the number of user functions in the weak list of optimized
1524 // functions attached to a native context causing a GC after the
1525 // specified number of elements.
1526 static int CountOptimizedUserFunctionsWithGC(v8::Handle<v8::Context> context,
1527  int n) {
1528  int count = 0;
1529  Handle<Context> icontext = v8::Utils::OpenHandle(*context);
1530  Isolate* isolate = icontext->GetIsolate();
1531  Handle<Object> object(icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST),
1532  isolate);
1533  while (object->IsJSFunction() &&
1534  !Handle<JSFunction>::cast(object)->IsBuiltin()) {
1535  count++;
1536  if (count == n) isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags);
1537  object = Handle<Object>(
1538  Object::cast(JSFunction::cast(*object)->next_function_link()),
1539  isolate);
1540  }
1541  return count;
1542 }
1543 
1544 
1545 TEST(TestInternalWeakListsTraverseWithGC) {
1547  Isolate* isolate = CcTest::i_isolate();
1548 
1549  static const int kNumTestContexts = 10;
1550 
1551  HandleScope scope(isolate);
1552  v8::Handle<v8::Context> ctx[kNumTestContexts];
1553 
1555 
1556  // Create an number of contexts and check the length of the weak list both
1557  // with and without GCs while iterating the list.
1558  for (int i = 0; i < kNumTestContexts; i++) {
1559  ctx[i] = v8::Context::New(CcTest::isolate());
1560  CHECK_EQ(i + 1, CountNativeContexts());
1561  CHECK_EQ(i + 1, CountNativeContextsWithGC(isolate, i / 2 + 1));
1562  }
1563 
1564  bool opt = (FLAG_always_opt && isolate->use_crankshaft());
1565 
1566  // Compile a number of functions the length of the weak list of optimized
1567  // functions both with and without GCs while iterating the list.
1568  ctx[0]->Enter();
1569  const char* source = "function f1() { };"
1570  "function f2() { };"
1571  "function f3() { };"
1572  "function f4() { };"
1573  "function f5() { };";
1574  CompileRun(source);
1575  CHECK_EQ(0, CountOptimizedUserFunctions(ctx[0]));
1576  CompileRun("f1()");
1577  CHECK_EQ(opt ? 1 : 0, CountOptimizedUserFunctions(ctx[0]));
1578  CHECK_EQ(opt ? 1 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 1));
1579  CompileRun("f2()");
1580  CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[0]));
1581  CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 1));
1582  CompileRun("f3()");
1583  CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[0]));
1584  CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 1));
1585  CompileRun("f4()");
1586  CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[0]));
1587  CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 2));
1588  CompileRun("f5()");
1589  CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[0]));
1590  CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctionsWithGC(ctx[0], 4));
1591 
1592  ctx[0]->Exit();
1593 }
1594 
1595 
1596 TEST(TestSizeOfObjects) {
1598 
1599  // Get initial heap size after several full GCs, which will stabilize
1600  // the heap size and return with sweeping finished completely.
1606  CHECK(CcTest::heap()->old_pointer_space()->IsLazySweepingComplete());
1607  int initial_size = static_cast<int>(CcTest::heap()->SizeOfObjects());
1608 
1609  {
1610  // Allocate objects on several different old-space pages so that
1611  // lazy sweeping kicks in for subsequent GC runs.
1612  AlwaysAllocateScope always_allocate(CcTest::i_isolate());
1613  int filler_size = static_cast<int>(FixedArray::SizeFor(8192));
1614  for (int i = 1; i <= 100; i++) {
1615  CcTest::heap()->AllocateFixedArray(8192, TENURED)->ToObjectChecked();
1616  CHECK_EQ(initial_size + i * filler_size,
1617  static_cast<int>(CcTest::heap()->SizeOfObjects()));
1618  }
1619  }
1620 
1621  // The heap size should go back to initial size after a full GC, even
1622  // though sweeping didn't finish yet.
1624 
1625  // Normally sweeping would not be complete here, but no guarantees.
1626 
1627  CHECK_EQ(initial_size, static_cast<int>(CcTest::heap()->SizeOfObjects()));
1628 
1629  // Advancing the sweeper step-wise should not change the heap size.
1630  while (!CcTest::heap()->old_pointer_space()->IsLazySweepingComplete()) {
1632  CHECK_EQ(initial_size, static_cast<int>(CcTest::heap()->SizeOfObjects()));
1633  }
1634 }
1635 
1636 
1637 TEST(TestSizeOfObjectsVsHeapIteratorPrecision) {
1640  intptr_t size_of_objects_1 = CcTest::heap()->SizeOfObjects();
1641  HeapIterator iterator(CcTest::heap());
1642  intptr_t size_of_objects_2 = 0;
1643  for (HeapObject* obj = iterator.next();
1644  obj != NULL;
1645  obj = iterator.next()) {
1646  if (!obj->IsFreeSpace()) {
1647  size_of_objects_2 += obj->Size();
1648  }
1649  }
1650  // Delta must be within 5% of the larger result.
1651  // TODO(gc): Tighten this up by distinguishing between byte
1652  // arrays that are real and those that merely mark free space
1653  // on the heap.
1654  if (size_of_objects_1 > size_of_objects_2) {
1655  intptr_t delta = size_of_objects_1 - size_of_objects_2;
1656  PrintF("Heap::SizeOfObjects: %" V8_PTR_PREFIX "d, "
1657  "Iterator: %" V8_PTR_PREFIX "d, "
1658  "delta: %" V8_PTR_PREFIX "d\n",
1659  size_of_objects_1, size_of_objects_2, delta);
1660  CHECK_GT(size_of_objects_1 / 20, delta);
1661  } else {
1662  intptr_t delta = size_of_objects_2 - size_of_objects_1;
1663  PrintF("Heap::SizeOfObjects: %" V8_PTR_PREFIX "d, "
1664  "Iterator: %" V8_PTR_PREFIX "d, "
1665  "delta: %" V8_PTR_PREFIX "d\n",
1666  size_of_objects_1, size_of_objects_2, delta);
1667  CHECK_GT(size_of_objects_2 / 20, delta);
1668  }
1669 }
1670 
1671 
1672 static void FillUpNewSpace(NewSpace* new_space) {
1673  // Fill up new space to the point that it is completely full. Make sure
1674  // that the scavenger does not undo the filling.
1675  Heap* heap = new_space->heap();
1676  Isolate* isolate = heap->isolate();
1677  Factory* factory = isolate->factory();
1678  HandleScope scope(isolate);
1679  AlwaysAllocateScope always_allocate(isolate);
1680  intptr_t available = new_space->EffectiveCapacity() - new_space->Size();
1681  intptr_t number_of_fillers = (available / FixedArray::SizeFor(32)) - 1;
1682  for (intptr_t i = 0; i < number_of_fillers; i++) {
1683  CHECK(heap->InNewSpace(*factory->NewFixedArray(32, NOT_TENURED)));
1684  }
1685 }
1686 
1687 
1688 TEST(GrowAndShrinkNewSpace) {
1690  Heap* heap = CcTest::heap();
1691  NewSpace* new_space = heap->new_space();
1692 
1693  if (heap->ReservedSemiSpaceSize() == heap->InitialSemiSpaceSize() ||
1694  heap->MaxSemiSpaceSize() == heap->InitialSemiSpaceSize()) {
1695  // The max size cannot exceed the reserved size, since semispaces must be
1696  // always within the reserved space. We can't test new space growing and
1697  // shrinking if the reserved size is the same as the minimum (initial) size.
1698  return;
1699  }
1700 
1701  // Explicitly growing should double the space capacity.
1702  intptr_t old_capacity, new_capacity;
1703  old_capacity = new_space->Capacity();
1704  new_space->Grow();
1705  new_capacity = new_space->Capacity();
1706  CHECK(2 * old_capacity == new_capacity);
1707 
1708  old_capacity = new_space->Capacity();
1709  FillUpNewSpace(new_space);
1710  new_capacity = new_space->Capacity();
1711  CHECK(old_capacity == new_capacity);
1712 
1713  // Explicitly shrinking should not affect space capacity.
1714  old_capacity = new_space->Capacity();
1715  new_space->Shrink();
1716  new_capacity = new_space->Capacity();
1717  CHECK(old_capacity == new_capacity);
1718 
1719  // Let the scavenger empty the new space.
1720  heap->CollectGarbage(NEW_SPACE);
1721  CHECK_LE(new_space->Size(), old_capacity);
1722 
1723  // Explicitly shrinking should halve the space capacity.
1724  old_capacity = new_space->Capacity();
1725  new_space->Shrink();
1726  new_capacity = new_space->Capacity();
1727  CHECK(old_capacity == 2 * new_capacity);
1728 
1729  // Consecutive shrinking should not affect space capacity.
1730  old_capacity = new_space->Capacity();
1731  new_space->Shrink();
1732  new_space->Shrink();
1733  new_space->Shrink();
1734  new_capacity = new_space->Capacity();
1735  CHECK(old_capacity == new_capacity);
1736 }
1737 
1738 
1739 TEST(CollectingAllAvailableGarbageShrinksNewSpace) {
1741  Heap* heap = CcTest::heap();
1742  if (heap->ReservedSemiSpaceSize() == heap->InitialSemiSpaceSize() ||
1743  heap->MaxSemiSpaceSize() == heap->InitialSemiSpaceSize()) {
1744  // The max size cannot exceed the reserved size, since semispaces must be
1745  // always within the reserved space. We can't test new space growing and
1746  // shrinking if the reserved size is the same as the minimum (initial) size.
1747  return;
1748  }
1749 
1751  NewSpace* new_space = heap->new_space();
1752  intptr_t old_capacity, new_capacity;
1753  old_capacity = new_space->Capacity();
1754  new_space->Grow();
1755  new_capacity = new_space->Capacity();
1756  CHECK(2 * old_capacity == new_capacity);
1757  FillUpNewSpace(new_space);
1759  new_capacity = new_space->Capacity();
1760  CHECK(old_capacity == new_capacity);
1761 }
1762 
1763 
1764 static int NumberOfGlobalObjects() {
1765  int count = 0;
1766  HeapIterator iterator(CcTest::heap());
1767  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
1768  if (obj->IsGlobalObject()) count++;
1769  }
1770  return count;
1771 }
1772 
1773 
1774 // Test that we don't embed maps from foreign contexts into
1775 // optimized code.
1776 TEST(LeakNativeContextViaMap) {
1777  i::FLAG_allow_natives_syntax = true;
1778  v8::Isolate* isolate = CcTest::isolate();
1779  v8::HandleScope outer_scope(isolate);
1782  {
1783  v8::HandleScope scope(isolate);
1784  ctx1p.Reset(isolate, v8::Context::New(isolate));
1785  ctx2p.Reset(isolate, v8::Context::New(isolate));
1786  v8::Local<v8::Context>::New(isolate, ctx1p)->Enter();
1787  }
1788 
1790  CHECK_EQ(4, NumberOfGlobalObjects());
1791 
1792  {
1793  v8::HandleScope inner_scope(isolate);
1794  CompileRun("var v = {x: 42}");
1795  v8::Local<v8::Context> ctx1 = v8::Local<v8::Context>::New(isolate, ctx1p);
1796  v8::Local<v8::Context> ctx2 = v8::Local<v8::Context>::New(isolate, ctx2p);
1797  v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v"));
1798  ctx2->Enter();
1799  ctx2->Global()->Set(v8_str("o"), v);
1800  v8::Local<v8::Value> res = CompileRun(
1801  "function f() { return o.x; }"
1802  "for (var i = 0; i < 10; ++i) f();"
1803  "%OptimizeFunctionOnNextCall(f);"
1804  "f();");
1805  CHECK_EQ(42, res->Int32Value());
1806  ctx2->Global()->Set(v8_str("o"), v8::Int32::New(isolate, 0));
1807  ctx2->Exit();
1808  v8::Local<v8::Context>::New(isolate, ctx1)->Exit();
1809  ctx1p.Reset();
1811  }
1813  CHECK_EQ(2, NumberOfGlobalObjects());
1814  ctx2p.Reset();
1816  CHECK_EQ(0, NumberOfGlobalObjects());
1817 }
1818 
1819 
1820 // Test that we don't embed functions from foreign contexts into
1821 // optimized code.
1822 TEST(LeakNativeContextViaFunction) {
1823  i::FLAG_allow_natives_syntax = true;
1824  v8::Isolate* isolate = CcTest::isolate();
1825  v8::HandleScope outer_scope(isolate);
1828  {
1829  v8::HandleScope scope(isolate);
1830  ctx1p.Reset(isolate, v8::Context::New(isolate));
1831  ctx2p.Reset(isolate, v8::Context::New(isolate));
1832  v8::Local<v8::Context>::New(isolate, ctx1p)->Enter();
1833  }
1834 
1836  CHECK_EQ(4, NumberOfGlobalObjects());
1837 
1838  {
1839  v8::HandleScope inner_scope(isolate);
1840  CompileRun("var v = function() { return 42; }");
1841  v8::Local<v8::Context> ctx1 = v8::Local<v8::Context>::New(isolate, ctx1p);
1842  v8::Local<v8::Context> ctx2 = v8::Local<v8::Context>::New(isolate, ctx2p);
1843  v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v"));
1844  ctx2->Enter();
1845  ctx2->Global()->Set(v8_str("o"), v);
1846  v8::Local<v8::Value> res = CompileRun(
1847  "function f(x) { return x(); }"
1848  "for (var i = 0; i < 10; ++i) f(o);"
1849  "%OptimizeFunctionOnNextCall(f);"
1850  "f(o);");
1851  CHECK_EQ(42, res->Int32Value());
1852  ctx2->Global()->Set(v8_str("o"), v8::Int32::New(isolate, 0));
1853  ctx2->Exit();
1854  ctx1->Exit();
1855  ctx1p.Reset();
1857  }
1859  CHECK_EQ(2, NumberOfGlobalObjects());
1860  ctx2p.Reset();
1862  CHECK_EQ(0, NumberOfGlobalObjects());
1863 }
1864 
1865 
1866 TEST(LeakNativeContextViaMapKeyed) {
1867  i::FLAG_allow_natives_syntax = true;
1868  v8::Isolate* isolate = CcTest::isolate();
1869  v8::HandleScope outer_scope(isolate);
1872  {
1873  v8::HandleScope scope(isolate);
1874  ctx1p.Reset(isolate, v8::Context::New(isolate));
1875  ctx2p.Reset(isolate, v8::Context::New(isolate));
1876  v8::Local<v8::Context>::New(isolate, ctx1p)->Enter();
1877  }
1878 
1880  CHECK_EQ(4, NumberOfGlobalObjects());
1881 
1882  {
1883  v8::HandleScope inner_scope(isolate);
1884  CompileRun("var v = [42, 43]");
1885  v8::Local<v8::Context> ctx1 = v8::Local<v8::Context>::New(isolate, ctx1p);
1886  v8::Local<v8::Context> ctx2 = v8::Local<v8::Context>::New(isolate, ctx2p);
1887  v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v"));
1888  ctx2->Enter();
1889  ctx2->Global()->Set(v8_str("o"), v);
1890  v8::Local<v8::Value> res = CompileRun(
1891  "function f() { return o[0]; }"
1892  "for (var i = 0; i < 10; ++i) f();"
1893  "%OptimizeFunctionOnNextCall(f);"
1894  "f();");
1895  CHECK_EQ(42, res->Int32Value());
1896  ctx2->Global()->Set(v8_str("o"), v8::Int32::New(isolate, 0));
1897  ctx2->Exit();
1898  ctx1->Exit();
1899  ctx1p.Reset();
1901  }
1903  CHECK_EQ(2, NumberOfGlobalObjects());
1904  ctx2p.Reset();
1906  CHECK_EQ(0, NumberOfGlobalObjects());
1907 }
1908 
1909 
1910 TEST(LeakNativeContextViaMapProto) {
1911  i::FLAG_allow_natives_syntax = true;
1912  v8::Isolate* isolate = CcTest::isolate();
1913  v8::HandleScope outer_scope(isolate);
1916  {
1917  v8::HandleScope scope(isolate);
1918  ctx1p.Reset(isolate, v8::Context::New(isolate));
1919  ctx2p.Reset(isolate, v8::Context::New(isolate));
1920  v8::Local<v8::Context>::New(isolate, ctx1p)->Enter();
1921  }
1922 
1924  CHECK_EQ(4, NumberOfGlobalObjects());
1925 
1926  {
1927  v8::HandleScope inner_scope(isolate);
1928  CompileRun("var v = { y: 42}");
1929  v8::Local<v8::Context> ctx1 = v8::Local<v8::Context>::New(isolate, ctx1p);
1930  v8::Local<v8::Context> ctx2 = v8::Local<v8::Context>::New(isolate, ctx2p);
1931  v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v"));
1932  ctx2->Enter();
1933  ctx2->Global()->Set(v8_str("o"), v);
1934  v8::Local<v8::Value> res = CompileRun(
1935  "function f() {"
1936  " var p = {x: 42};"
1937  " p.__proto__ = o;"
1938  " return p.x;"
1939  "}"
1940  "for (var i = 0; i < 10; ++i) f();"
1941  "%OptimizeFunctionOnNextCall(f);"
1942  "f();");
1943  CHECK_EQ(42, res->Int32Value());
1944  ctx2->Global()->Set(v8_str("o"), v8::Int32::New(isolate, 0));
1945  ctx2->Exit();
1946  ctx1->Exit();
1947  ctx1p.Reset();
1949  }
1951  CHECK_EQ(2, NumberOfGlobalObjects());
1952  ctx2p.Reset();
1954  CHECK_EQ(0, NumberOfGlobalObjects());
1955 }
1956 
1957 
1958 TEST(InstanceOfStubWriteBarrier) {
1959  i::FLAG_allow_natives_syntax = true;
1960 #ifdef VERIFY_HEAP
1961  i::FLAG_verify_heap = true;
1962 #endif
1963 
1965  if (!CcTest::i_isolate()->use_crankshaft()) return;
1966  if (i::FLAG_force_marking_deque_overflows) return;
1967  v8::HandleScope outer_scope(CcTest::isolate());
1968 
1969  {
1971  CompileRun(
1972  "function foo () { }"
1973  "function mkbar () { return new (new Function(\"\")) (); }"
1974  "function f (x) { return (x instanceof foo); }"
1975  "function g () { f(mkbar()); }"
1976  "f(new foo()); f(new foo());"
1977  "%OptimizeFunctionOnNextCall(f);"
1978  "f(new foo()); g();");
1979  }
1980 
1982  marking->Abort();
1983  marking->Start();
1984 
1985  Handle<JSFunction> f =
1988  CcTest::global()->Get(v8_str("f"))));
1989 
1990  CHECK(f->IsOptimized());
1991 
1992  while (!Marking::IsBlack(Marking::MarkBitFrom(f->code())) &&
1993  !marking->IsStopped()) {
1994  // Discard any pending GC requests otherwise we will get GC when we enter
1995  // code below.
1997  }
1998 
1999  CHECK(marking->IsMarking());
2000 
2001  {
2005  v8::Handle<v8::Function>::Cast(global->Get(v8_str("g")));
2006  g->Call(global, 0, NULL);
2007  }
2008 
2011 }
2012 
2013 
2014 TEST(PrototypeTransitionClearing) {
2016  Isolate* isolate = CcTest::i_isolate();
2017  Factory* factory = isolate->factory();
2019 
2020  CompileRun("var base = {};");
2021  Handle<JSObject> baseObject =
2024  CcTest::global()->Get(v8_str("base"))));
2025  int initialTransitions = baseObject->map()->NumberOfProtoTransitions();
2026 
2027  CompileRun(
2028  "var live = [];"
2029  "for (var i = 0; i < 10; i++) {"
2030  " var object = {};"
2031  " var prototype = {};"
2032  " object.__proto__ = prototype;"
2033  " if (i >= 3) live.push(object, prototype);"
2034  "}");
2035 
2036  // Verify that only dead prototype transitions are cleared.
2037  CHECK_EQ(initialTransitions + 10,
2038  baseObject->map()->NumberOfProtoTransitions());
2040  const int transitions = 10 - 3;
2041  CHECK_EQ(initialTransitions + transitions,
2042  baseObject->map()->NumberOfProtoTransitions());
2043 
2044  // Verify that prototype transitions array was compacted.
2045  FixedArray* trans = baseObject->map()->GetPrototypeTransitions();
2046  for (int i = initialTransitions; i < initialTransitions + transitions; i++) {
2049  CHECK(trans->get(j + Map::kProtoTransitionMapOffset)->IsMap());
2050  Object* proto = trans->get(j + Map::kProtoTransitionPrototypeOffset);
2051  CHECK(proto->IsJSObject());
2052  }
2053 
2054  // Make sure next prototype is placed on an old-space evacuation candidate.
2055  Handle<JSObject> prototype;
2057  {
2058  AlwaysAllocateScope always_allocate(isolate);
2059  SimulateFullSpace(space);
2060  prototype = factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, TENURED);
2061  }
2062 
2063  // Add a prototype on an evacuation candidate and verify that transition
2064  // clearing correctly records slots in prototype transition array.
2065  i::FLAG_always_compact = true;
2066  Handle<Map> map(baseObject->map());
2067  CHECK(!space->LastPage()->Contains(
2068  map->GetPrototypeTransitions()->address()));
2069  CHECK(space->LastPage()->Contains(prototype->address()));
2070  JSObject::SetPrototype(baseObject, prototype, false);
2071  CHECK(Map::GetPrototypeTransition(map, prototype)->IsMap());
2073  CHECK(Map::GetPrototypeTransition(map, prototype)->IsMap());
2074 }
2075 
2076 
2077 TEST(ResetSharedFunctionInfoCountersDuringIncrementalMarking) {
2078  i::FLAG_stress_compaction = false;
2079  i::FLAG_allow_natives_syntax = true;
2080 #ifdef VERIFY_HEAP
2081  i::FLAG_verify_heap = true;
2082 #endif
2083 
2085  if (!CcTest::i_isolate()->use_crankshaft()) return;
2086  v8::HandleScope outer_scope(CcTest::isolate());
2087 
2088  {
2090  CompileRun(
2091  "function f () {"
2092  " var s = 0;"
2093  " for (var i = 0; i < 100; i++) s += i;"
2094  " return s;"
2095  "}"
2096  "f(); f();"
2097  "%OptimizeFunctionOnNextCall(f);"
2098  "f();");
2099  }
2100  Handle<JSFunction> f =
2103  CcTest::global()->Get(v8_str("f"))));
2104  CHECK(f->IsOptimized());
2105 
2107  marking->Abort();
2108  marking->Start();
2109 
2110  // The following two calls will increment CcTest::heap()->global_ic_age().
2111  const int kLongIdlePauseInMs = 1000;
2113  v8::V8::IdleNotification(kLongIdlePauseInMs);
2114 
2115  while (!marking->IsStopped() && !marking->IsComplete()) {
2116  marking->Step(1 * MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
2117  }
2118  if (!marking->IsStopped() || marking->should_hurry()) {
2119  // We don't normally finish a GC via Step(), we normally finish by
2120  // setting the stack guard and then do the final steps in the stack
2121  // guard interrupt. But here we didn't ask for that, and there is no
2122  // JS code running to trigger the interrupt, so we explicitly finalize
2123  // here.
2125  "Test finalizing incremental mark-sweep");
2126  }
2127 
2128  CHECK_EQ(CcTest::heap()->global_ic_age(), f->shared()->ic_age());
2129  CHECK_EQ(0, f->shared()->opt_count());
2130  CHECK_EQ(0, f->shared()->code()->profiler_ticks());
2131 }
2132 
2133 
2134 TEST(ResetSharedFunctionInfoCountersDuringMarkSweep) {
2135  i::FLAG_stress_compaction = false;
2136  i::FLAG_allow_natives_syntax = true;
2137 #ifdef VERIFY_HEAP
2138  i::FLAG_verify_heap = true;
2139 #endif
2140 
2142  if (!CcTest::i_isolate()->use_crankshaft()) return;
2143  v8::HandleScope outer_scope(CcTest::isolate());
2144 
2145  {
2147  CompileRun(
2148  "function f () {"
2149  " var s = 0;"
2150  " for (var i = 0; i < 100; i++) s += i;"
2151  " return s;"
2152  "}"
2153  "f(); f();"
2154  "%OptimizeFunctionOnNextCall(f);"
2155  "f();");
2156  }
2157  Handle<JSFunction> f =
2160  CcTest::global()->Get(v8_str("f"))));
2161  CHECK(f->IsOptimized());
2162 
2164 
2165  // The following two calls will increment CcTest::heap()->global_ic_age().
2166  // Since incremental marking is off, IdleNotification will do full GC.
2167  const int kLongIdlePauseInMs = 1000;
2169  v8::V8::IdleNotification(kLongIdlePauseInMs);
2170 
2171  CHECK_EQ(CcTest::heap()->global_ic_age(), f->shared()->ic_age());
2172  CHECK_EQ(0, f->shared()->opt_count());
2173  CHECK_EQ(0, f->shared()->code()->profiler_ticks());
2174 }
2175 
2176 
2177 // Test that HAllocateObject will always return an object in new-space.
2178 TEST(OptimizedAllocationAlwaysInNewSpace) {
2179  i::FLAG_allow_natives_syntax = true;
2181  if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
2182  if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
2184 
2185  SimulateFullSpace(CcTest::heap()->new_space());
2186  AlwaysAllocateScope always_allocate(CcTest::i_isolate());
2187  v8::Local<v8::Value> res = CompileRun(
2188  "function c(x) {"
2189  " this.x = x;"
2190  " for (var i = 0; i < 32; i++) {"
2191  " this['x' + i] = x;"
2192  " }"
2193  "}"
2194  "function f(x) { return new c(x); };"
2195  "f(1); f(2); f(3);"
2196  "%OptimizeFunctionOnNextCall(f);"
2197  "f(4);");
2198  CHECK_EQ(4, res->ToObject()->GetRealNamedProperty(v8_str("x"))->Int32Value());
2199 
2200  Handle<JSObject> o =
2202 
2203  CHECK(CcTest::heap()->InNewSpace(*o));
2204 }
2205 
2206 
2207 TEST(OptimizedPretenuringAllocationFolding) {
2208  i::FLAG_allow_natives_syntax = true;
2209  i::FLAG_max_new_space_size = 2048;
2210  i::FLAG_allocation_site_pretenuring = false;
2212  if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
2213  if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
2216 
2217  v8::Local<v8::Value> res = CompileRun(
2218  "function DataObject() {"
2219  " this.a = 1.1;"
2220  " this.b = [{}];"
2221  " this.c = 1.2;"
2222  " this.d = [{}];"
2223  " this.e = 1.3;"
2224  " this.f = [{}];"
2225  "}"
2226  "var number_elements = 20000;"
2227  "var elements = new Array();"
2228  "function f() {"
2229  " for (var i = 0; i < number_elements; i++) {"
2230  " elements[i] = new DataObject();"
2231  " }"
2232  " return elements[number_elements-1]"
2233  "};"
2234  "f(); f(); f();"
2235  "%OptimizeFunctionOnNextCall(f);"
2236  "f();");
2237 
2238  Handle<JSObject> o =
2240 
2241  CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(0)));
2242  CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(1)));
2243  CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(2)));
2244  CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(3)));
2245  CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(4)));
2246  CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(5)));
2247 }
2248 
2249 
2250 TEST(OptimizedPretenuringAllocationFoldingBlocks) {
2251  i::FLAG_allow_natives_syntax = true;
2252  i::FLAG_max_new_space_size = 2048;
2253  i::FLAG_allocation_site_pretenuring = false;
2255  if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
2256  if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
2259 
2260  v8::Local<v8::Value> res = CompileRun(
2261  "var number_elements = 30000;"
2262  "var elements = new Array(number_elements);"
2263  "function DataObject() {"
2264  " this.a = [{}];"
2265  " this.b = [{}];"
2266  " this.c = 1.1;"
2267  " this.d = 1.2;"
2268  " this.e = [{}];"
2269  " this.f = 1.3;"
2270  "}"
2271  "function f() {"
2272  " for (var i = 0; i < number_elements; i++) {"
2273  " elements[i] = new DataObject();"
2274  " }"
2275  " return elements[number_elements - 1];"
2276  "};"
2277  "f(); f(); f();"
2278  "%OptimizeFunctionOnNextCall(f);"
2279  "f();");
2280 
2281  Handle<JSObject> o =
2283 
2284  CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(0)));
2285  CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(1)));
2286  CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(2)));
2287  CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(3)));
2288  CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(4)));
2289  CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(5)));
2290 }
2291 
2292 
2293 TEST(OptimizedPretenuringObjectArrayLiterals) {
2294  i::FLAG_allow_natives_syntax = true;
2295  i::FLAG_max_new_space_size = 2048;
2297  if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
2298  if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
2300 
2301  v8::Local<v8::Value> res = CompileRun(
2302  "var number_elements = 20000;"
2303  "var elements = new Array(number_elements);"
2304  "function f() {"
2305  " for (var i = 0; i < number_elements; i++) {"
2306  " elements[i] = [{}, {}, {}];"
2307  " }"
2308  " return elements[number_elements - 1];"
2309  "};"
2310  "f(); f(); f();"
2311  "%OptimizeFunctionOnNextCall(f);"
2312  "f();");
2313 
2314  Handle<JSObject> o =
2316 
2317  CHECK(CcTest::heap()->InOldPointerSpace(o->elements()));
2318  CHECK(CcTest::heap()->InOldPointerSpace(*o));
2319 }
2320 
2321 
2322 TEST(OptimizedPretenuringMixedInObjectProperties) {
2323  i::FLAG_allow_natives_syntax = true;
2324  i::FLAG_max_new_space_size = 2048;
2326  if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
2327  if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
2329 
2330  v8::Local<v8::Value> res = CompileRun(
2331  "var number_elements = 20000;"
2332  "var elements = new Array(number_elements);"
2333  "function f() {"
2334  " for (var i = 0; i < number_elements; i++) {"
2335  " elements[i] = {a: {c: 2.2, d: {}}, b: 1.1};"
2336  " }"
2337  " return elements[number_elements - 1];"
2338  "};"
2339  "f(); f(); f();"
2340  "%OptimizeFunctionOnNextCall(f);"
2341  "f();");
2342 
2343  Handle<JSObject> o =
2345 
2346  CHECK(CcTest::heap()->InOldPointerSpace(*o));
2347  CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(0)));
2348  CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(1)));
2349 
2350  JSObject* inner_object = reinterpret_cast<JSObject*>(o->RawFastPropertyAt(0));
2351  CHECK(CcTest::heap()->InOldPointerSpace(inner_object));
2352  CHECK(CcTest::heap()->InOldDataSpace(inner_object->RawFastPropertyAt(0)));
2353  CHECK(CcTest::heap()->InOldPointerSpace(inner_object->RawFastPropertyAt(1)));
2354 }
2355 
2356 
2357 TEST(OptimizedPretenuringDoubleArrayProperties) {
2358  i::FLAG_allow_natives_syntax = true;
2359  i::FLAG_max_new_space_size = 2048;
2361  if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
2362  if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
2364 
2365  v8::Local<v8::Value> res = CompileRun(
2366  "var number_elements = 30000;"
2367  "var elements = new Array(number_elements);"
2368  "function f() {"
2369  " for (var i = 0; i < number_elements; i++) {"
2370  " elements[i] = {a: 1.1, b: 2.2};"
2371  " }"
2372  " return elements[i - 1];"
2373  "};"
2374  "f(); f(); f();"
2375  "%OptimizeFunctionOnNextCall(f);"
2376  "f();");
2377 
2378  Handle<JSObject> o =
2380 
2381  CHECK(CcTest::heap()->InOldPointerSpace(*o));
2382  CHECK(CcTest::heap()->InOldDataSpace(o->properties()));
2383 }
2384 
2385 
2386 TEST(OptimizedPretenuringdoubleArrayLiterals) {
2387  i::FLAG_allow_natives_syntax = true;
2388  i::FLAG_max_new_space_size = 2048;
2390  if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
2391  if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
2393 
2394  v8::Local<v8::Value> res = CompileRun(
2395  "var number_elements = 30000;"
2396  "var elements = new Array(number_elements);"
2397  "function f() {"
2398  " for (var i = 0; i < number_elements; i++) {"
2399  " elements[i] = [1.1, 2.2, 3.3];"
2400  " }"
2401  " return elements[number_elements - 1];"
2402  "};"
2403  "f(); f(); f();"
2404  "%OptimizeFunctionOnNextCall(f);"
2405  "f();");
2406 
2407  Handle<JSObject> o =
2409 
2410  CHECK(CcTest::heap()->InOldDataSpace(o->elements()));
2411  CHECK(CcTest::heap()->InOldPointerSpace(*o));
2412 }
2413 
2414 
2415 TEST(OptimizedPretenuringNestedMixedArrayLiterals) {
2416  i::FLAG_allow_natives_syntax = true;
2417  i::FLAG_max_new_space_size = 2048;
2419  if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
2420  if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
2422 
2423  v8::Local<v8::Value> res = CompileRun(
2424  "var number_elements = 20000;"
2425  "var elements = new Array(number_elements);"
2426  "function f() {"
2427  " for (var i = 0; i < number_elements; i++) {"
2428  " elements[i] = [[{}, {}, {}], [1.1, 2.2, 3.3]];"
2429  " }"
2430  " return elements[number_elements - 1];"
2431  "};"
2432  "f(); f(); f();"
2433  "%OptimizeFunctionOnNextCall(f);"
2434  "f();");
2435 
2436  v8::Local<v8::Value> int_array = v8::Object::Cast(*res)->Get(v8_str("0"));
2437  Handle<JSObject> int_array_handle =
2439  v8::Local<v8::Value> double_array = v8::Object::Cast(*res)->Get(v8_str("1"));
2440  Handle<JSObject> double_array_handle =
2442 
2443  Handle<JSObject> o =
2445  CHECK(CcTest::heap()->InOldPointerSpace(*o));
2446  CHECK(CcTest::heap()->InOldPointerSpace(*int_array_handle));
2447  CHECK(CcTest::heap()->InOldPointerSpace(int_array_handle->elements()));
2448  CHECK(CcTest::heap()->InOldPointerSpace(*double_array_handle));
2449  CHECK(CcTest::heap()->InOldDataSpace(double_array_handle->elements()));
2450 }
2451 
2452 
2453 TEST(OptimizedPretenuringNestedObjectLiterals) {
2454  i::FLAG_allow_natives_syntax = true;
2455  i::FLAG_max_new_space_size = 2048;
2457  if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
2458  if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
2460 
2461  v8::Local<v8::Value> res = CompileRun(
2462  "var number_elements = 20000;"
2463  "var elements = new Array(number_elements);"
2464  "function f() {"
2465  " for (var i = 0; i < number_elements; i++) {"
2466  " elements[i] = [[{}, {}, {}],[{}, {}, {}]];"
2467  " }"
2468  " return elements[number_elements - 1];"
2469  "};"
2470  "f(); f(); f();"
2471  "%OptimizeFunctionOnNextCall(f);"
2472  "f();");
2473 
2474  v8::Local<v8::Value> int_array_1 = v8::Object::Cast(*res)->Get(v8_str("0"));
2475  Handle<JSObject> int_array_handle_1 =
2477  v8::Local<v8::Value> int_array_2 = v8::Object::Cast(*res)->Get(v8_str("1"));
2478  Handle<JSObject> int_array_handle_2 =
2480 
2481  Handle<JSObject> o =
2483  CHECK(CcTest::heap()->InOldPointerSpace(*o));
2484  CHECK(CcTest::heap()->InOldPointerSpace(*int_array_handle_1));
2485  CHECK(CcTest::heap()->InOldPointerSpace(int_array_handle_1->elements()));
2486  CHECK(CcTest::heap()->InOldPointerSpace(*int_array_handle_2));
2487  CHECK(CcTest::heap()->InOldPointerSpace(int_array_handle_2->elements()));
2488 }
2489 
2490 
2491 TEST(OptimizedPretenuringNestedDoubleLiterals) {
2492  i::FLAG_allow_natives_syntax = true;
2493  i::FLAG_max_new_space_size = 2048;
2495  if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
2496  if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
2498 
2499  v8::Local<v8::Value> res = CompileRun(
2500  "var number_elements = 20000;"
2501  "var elements = new Array(number_elements);"
2502  "function f() {"
2503  " for (var i = 0; i < number_elements; i++) {"
2504  " elements[i] = [[1.1, 1.2, 1.3],[2.1, 2.2, 2.3]];"
2505  " }"
2506  " return elements[number_elements - 1];"
2507  "};"
2508  "f(); f(); f();"
2509  "%OptimizeFunctionOnNextCall(f);"
2510  "f();");
2511 
2512  v8::Local<v8::Value> double_array_1 =
2513  v8::Object::Cast(*res)->Get(v8_str("0"));
2514  Handle<JSObject> double_array_handle_1 =
2516  v8::Local<v8::Value> double_array_2 =
2517  v8::Object::Cast(*res)->Get(v8_str("1"));
2518  Handle<JSObject> double_array_handle_2 =
2520 
2521  Handle<JSObject> o =
2523  CHECK(CcTest::heap()->InOldPointerSpace(*o));
2524  CHECK(CcTest::heap()->InOldPointerSpace(*double_array_handle_1));
2525  CHECK(CcTest::heap()->InOldDataSpace(double_array_handle_1->elements()));
2526  CHECK(CcTest::heap()->InOldPointerSpace(*double_array_handle_2));
2527  CHECK(CcTest::heap()->InOldDataSpace(double_array_handle_2->elements()));
2528 }
2529 
2530 
2531 // Make sure pretenuring feedback is gathered for constructed objects as well
2532 // as for literals.
2533 TEST(OptimizedPretenuringConstructorCalls) {
2534  if (!FLAG_allocation_site_pretenuring || !i::FLAG_pretenuring_call_new) {
2535  // FLAG_pretenuring_call_new needs to be synced with the snapshot.
2536  return;
2537  }
2538  i::FLAG_allow_natives_syntax = true;
2539  i::FLAG_max_new_space_size = 2048;
2541  if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
2542  if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
2544 
2545  v8::Local<v8::Value> res = CompileRun(
2546  "var number_elements = 20000;"
2547  "var elements = new Array(number_elements);"
2548  "function foo() {"
2549  " this.a = 3;"
2550  " this.b = {};"
2551  "}"
2552  "function f() {"
2553  " for (var i = 0; i < number_elements; i++) {"
2554  " elements[i] = new foo();"
2555  " }"
2556  " return elements[number_elements - 1];"
2557  "};"
2558  "f(); f(); f();"
2559  "%OptimizeFunctionOnNextCall(f);"
2560  "f();");
2561 
2562  Handle<JSObject> o =
2564 
2565  CHECK(CcTest::heap()->InOldPointerSpace(*o));
2566 }
2567 
2568 
2569 // Test regular array literals allocation.
2570 TEST(OptimizedAllocationArrayLiterals) {
2571  i::FLAG_allow_natives_syntax = true;
2573  if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
2574  if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
2576 
2577  v8::Local<v8::Value> res = CompileRun(
2578  "function f() {"
2579  " var numbers = new Array(1, 2, 3);"
2580  " numbers[0] = 3.14;"
2581  " return numbers;"
2582  "};"
2583  "f(); f(); f();"
2584  "%OptimizeFunctionOnNextCall(f);"
2585  "f();");
2586  CHECK_EQ(static_cast<int>(3.14),
2587  v8::Object::Cast(*res)->Get(v8_str("0"))->Int32Value());
2588 
2589  Handle<JSObject> o =
2591 
2592  CHECK(CcTest::heap()->InNewSpace(o->elements()));
2593 }
2594 
2595 
2596 // Test global pretenuring call new.
2597 TEST(OptimizedPretenuringCallNew) {
2598  i::FLAG_allow_natives_syntax = true;
2599  i::FLAG_allocation_site_pretenuring = false;
2600  i::FLAG_pretenuring_call_new = true;
2602  if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
2603  if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
2606 
2607  AlwaysAllocateScope always_allocate(CcTest::i_isolate());
2608  v8::Local<v8::Value> res = CompileRun(
2609  "function g() { this.a = 0; }"
2610  "function f() {"
2611  " return new g();"
2612  "};"
2613  "f(); f(); f();"
2614  "%OptimizeFunctionOnNextCall(f);"
2615  "f();");
2616 
2617  Handle<JSObject> o =
2619  CHECK(CcTest::heap()->InOldPointerSpace(*o));
2620 }
2621 
2622 
2623 static int CountMapTransitions(Map* map) {
2624  return map->transitions()->number_of_transitions();
2625 }
2626 
2627 
2628 // Test that map transitions are cleared and maps are collected with
2629 // incremental marking as well.
2630 TEST(Regress1465) {
2631  i::FLAG_stress_compaction = false;
2632  i::FLAG_allow_natives_syntax = true;
2633  i::FLAG_trace_incremental_marking = true;
2636  static const int transitions_count = 256;
2637 
2638  {
2639  AlwaysAllocateScope always_allocate(CcTest::i_isolate());
2640  for (int i = 0; i < transitions_count; i++) {
2641  EmbeddedVector<char, 64> buffer;
2642  OS::SNPrintF(buffer, "var o = new Object; o.prop%d = %d;", i, i);
2643  CompileRun(buffer.start());
2644  }
2645  CompileRun("var root = new Object;");
2646  }
2647 
2648  Handle<JSObject> root =
2651  CcTest::global()->Get(v8_str("root"))));
2652 
2653  // Count number of live transitions before marking.
2654  int transitions_before = CountMapTransitions(root->map());
2655  CompileRun("%DebugPrint(root);");
2656  CHECK_EQ(transitions_count, transitions_before);
2657 
2658  SimulateIncrementalMarking();
2660 
2661  // Count number of live transitions after marking. Note that one transition
2662  // is left, because 'o' still holds an instance of one transition target.
2663  int transitions_after = CountMapTransitions(root->map());
2664  CompileRun("%DebugPrint(root);");
2665  CHECK_EQ(1, transitions_after);
2666 }
2667 
2668 
2669 TEST(Regress2143a) {
2670  i::FLAG_collect_maps = true;
2671  i::FLAG_incremental_marking = true;
2674 
2675  // Prepare a map transition from the root object together with a yet
2676  // untransitioned root object.
2677  CompileRun("var root = new Object;"
2678  "root.foo = 0;"
2679  "root = new Object;");
2680 
2681  SimulateIncrementalMarking();
2682 
2683  // Compile a StoreIC that performs the prepared map transition. This
2684  // will restart incremental marking and should make sure the root is
2685  // marked grey again.
2686  CompileRun("function f(o) {"
2687  " o.foo = 0;"
2688  "}"
2689  "f(new Object);"
2690  "f(root);");
2691 
2692  // This bug only triggers with aggressive IC clearing.
2694 
2695  // Explicitly request GC to perform final marking step and sweeping.
2697 
2698  Handle<JSObject> root =
2701  CcTest::global()->Get(v8_str("root"))));
2702 
2703  // The root object should be in a sane state.
2704  CHECK(root->IsJSObject());
2705  CHECK(root->map()->IsMap());
2706 }
2707 
2708 
2709 TEST(Regress2143b) {
2710  i::FLAG_collect_maps = true;
2711  i::FLAG_incremental_marking = true;
2712  i::FLAG_allow_natives_syntax = true;
2715 
2716  // Prepare a map transition from the root object together with a yet
2717  // untransitioned root object.
2718  CompileRun("var root = new Object;"
2719  "root.foo = 0;"
2720  "root = new Object;");
2721 
2722  SimulateIncrementalMarking();
2723 
2724  // Compile an optimized LStoreNamedField that performs the prepared
2725  // map transition. This will restart incremental marking and should
2726  // make sure the root is marked grey again.
2727  CompileRun("function f(o) {"
2728  " o.foo = 0;"
2729  "}"
2730  "f(new Object);"
2731  "f(new Object);"
2732  "%OptimizeFunctionOnNextCall(f);"
2733  "f(root);"
2734  "%DeoptimizeFunction(f);");
2735 
2736  // This bug only triggers with aggressive IC clearing.
2738 
2739  // Explicitly request GC to perform final marking step and sweeping.
2741 
2742  Handle<JSObject> root =
2745  CcTest::global()->Get(v8_str("root"))));
2746 
2747  // The root object should be in a sane state.
2748  CHECK(root->IsJSObject());
2749  CHECK(root->map()->IsMap());
2750 }
2751 
2752 
2753 TEST(ReleaseOverReservedPages) {
2754  i::FLAG_trace_gc = true;
2755  // The optimizer can allocate stuff, messing up the test.
2756  i::FLAG_crankshaft = false;
2757  i::FLAG_always_opt = false;
2759  Isolate* isolate = CcTest::i_isolate();
2760  Factory* factory = isolate->factory();
2761  Heap* heap = isolate->heap();
2763  static const int number_of_test_pages = 20;
2764 
2765  // Prepare many pages with low live-bytes count.
2766  PagedSpace* old_pointer_space = heap->old_pointer_space();
2767  CHECK_EQ(1, old_pointer_space->CountTotalPages());
2768  for (int i = 0; i < number_of_test_pages; i++) {
2769  AlwaysAllocateScope always_allocate(isolate);
2770  SimulateFullSpace(old_pointer_space);
2771  factory->NewFixedArray(1, TENURED);
2772  }
2773  CHECK_EQ(number_of_test_pages + 1, old_pointer_space->CountTotalPages());
2774 
2775  // Triggering one GC will cause a lot of garbage to be discovered but
2776  // even spread across all allocated pages.
2777  heap->CollectAllGarbage(Heap::kNoGCFlags, "triggered for preparation");
2778  CHECK_GE(number_of_test_pages + 1, old_pointer_space->CountTotalPages());
2779 
2780  // Triggering subsequent GCs should cause at least half of the pages
2781  // to be released to the OS after at most two cycles.
2782  heap->CollectAllGarbage(Heap::kNoGCFlags, "triggered by test 1");
2783  CHECK_GE(number_of_test_pages + 1, old_pointer_space->CountTotalPages());
2784  heap->CollectAllGarbage(Heap::kNoGCFlags, "triggered by test 2");
2785  CHECK_GE(number_of_test_pages + 1, old_pointer_space->CountTotalPages() * 2);
2786 
2787  // Triggering a last-resort GC should cause all pages to be released to the
2788  // OS so that other processes can seize the memory. If we get a failure here
2789  // where there are 2 pages left instead of 1, then we should increase the
2790  // size of the first page a little in SizeOfFirstPage in spaces.cc. The
2791  // first page should be small in order to reduce memory used when the VM
2792  // boots, but if the 20 small arrays don't fit on the first page then that's
2793  // an indication that it is too small.
2794  heap->CollectAllAvailableGarbage("triggered really hard");
2795  CHECK_EQ(1, old_pointer_space->CountTotalPages());
2796 }
2797 
2798 
2799 TEST(Regress2237) {
2800  i::FLAG_stress_compaction = false;
2802  Isolate* isolate = CcTest::i_isolate();
2803  Factory* factory = isolate->factory();
2805  Handle<String> slice(CcTest::heap()->empty_string());
2806 
2807  {
2808  // Generate a parent that lives in new-space.
2809  v8::HandleScope inner_scope(CcTest::isolate());
2810  const char* c = "This text is long enough to trigger sliced strings.";
2811  Handle<String> s = factory->NewStringFromAscii(CStrVector(c));
2812  CHECK(s->IsSeqOneByteString());
2813  CHECK(CcTest::heap()->InNewSpace(*s));
2814 
2815  // Generate a sliced string that is based on the above parent and
2816  // lives in old-space.
2817  SimulateFullSpace(CcTest::heap()->new_space());
2818  AlwaysAllocateScope always_allocate(isolate);
2819  Handle<String> t = factory->NewProperSubString(s, 5, 35);
2820  CHECK(t->IsSlicedString());
2821  CHECK(!CcTest::heap()->InNewSpace(*t));
2822  *slice.location() = *t.location();
2823  }
2824 
2825  CHECK(SlicedString::cast(*slice)->parent()->IsSeqOneByteString());
2827  CHECK(SlicedString::cast(*slice)->parent()->IsSeqOneByteString());
2828 }
2829 
2830 
2831 #ifdef OBJECT_PRINT
2832 TEST(PrintSharedFunctionInfo) {
2835  const char* source = "f = function() { return 987654321; }\n"
2836  "g = function() { return 123456789; }\n";
2837  CompileRun(source);
2838  Handle<JSFunction> g =
2841  CcTest::global()->Get(v8_str("g"))));
2842 
2843  DisallowHeapAllocation no_allocation;
2844  g->shared()->PrintLn();
2845 }
2846 #endif // OBJECT_PRINT
2847 
2848 
2849 TEST(Regress2211) {
2852 
2853  v8::Handle<v8::String> value = v8_str("val string");
2854  Smi* hash = Smi::FromInt(321);
2855  Heap* heap = CcTest::heap();
2856 
2857  for (int i = 0; i < 2; i++) {
2858  // Store identity hash first and common hidden property second.
2860  Handle<JSObject> internal_obj = v8::Utils::OpenHandle(*obj);
2861  CHECK(internal_obj->HasFastProperties());
2862 
2863  // In the first iteration, set hidden value first and identity hash second.
2864  // In the second iteration, reverse the order.
2865  if (i == 0) obj->SetHiddenValue(v8_str("key string"), value);
2866  JSObject::SetIdentityHash(internal_obj, handle(hash, CcTest::i_isolate()));
2867  if (i == 1) obj->SetHiddenValue(v8_str("key string"), value);
2868 
2869  // Check values.
2870  CHECK_EQ(hash,
2871  internal_obj->GetHiddenProperty(heap->identity_hash_string()));
2872  CHECK(value->Equals(obj->GetHiddenValue(v8_str("key string"))));
2873 
2874  // Check size.
2875  DescriptorArray* descriptors = internal_obj->map()->instance_descriptors();
2877  internal_obj->RawFastPropertyAt(descriptors->GetFieldIndex(0)));
2878  // HashTable header (5) and 4 initial entries (8).
2879  CHECK_LE(hashtable->SizeFor(hashtable->length()), 13 * kPointerSize);
2880  }
2881 }
2882 
2883 
2884 TEST(IncrementalMarkingClearsTypeFeedbackInfo) {
2885  if (i::FLAG_always_opt) return;
2888  v8::Local<v8::Value> fun1, fun2;
2889 
2890  {
2891  LocalContext env;
2892  CompileRun("function fun() {};");
2893  fun1 = env->Global()->Get(v8_str("fun"));
2894  }
2895 
2896  {
2897  LocalContext env;
2898  CompileRun("function fun() {};");
2899  fun2 = env->Global()->Get(v8_str("fun"));
2900  }
2901 
2902  // Prepare function f that contains type feedback for closures
2903  // originating from two different native contexts.
2904  CcTest::global()->Set(v8_str("fun1"), fun1);
2905  CcTest::global()->Set(v8_str("fun2"), fun2);
2906  CompileRun("function f(a, b) { a(); b(); } f(fun1, fun2);");
2907 
2908  Handle<JSFunction> f =
2911  CcTest::global()->Get(v8_str("f"))));
2912 
2914  f->shared()->code()->type_feedback_info())->feedback_vector());
2915 
2916  CHECK_EQ(2, feedback_vector->length());
2917  CHECK(feedback_vector->get(0)->IsJSFunction());
2918  CHECK(feedback_vector->get(1)->IsJSFunction());
2919 
2920  SimulateIncrementalMarking();
2922 
2923  CHECK_EQ(2, feedback_vector->length());
2924  CHECK_EQ(feedback_vector->get(0),
2926  CHECK_EQ(feedback_vector->get(1),
2928 }
2929 
2930 
2931 static Code* FindFirstIC(Code* code, Code::Kind kind) {
2932  int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
2933  RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
2934  RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
2935  for (RelocIterator it(code, mask); !it.done(); it.next()) {
2936  RelocInfo* info = it.rinfo();
2937  Code* target = Code::GetCodeFromTargetAddress(info->target_address());
2938  if (target->is_inline_cache_stub() && target->kind() == kind) {
2939  return target;
2940  }
2941  }
2942  return NULL;
2943 }
2944 
2945 
2946 TEST(IncrementalMarkingPreservesMonomorphicIC) {
2947  if (i::FLAG_always_opt) return;
2950 
2951  // Prepare function f that contains a monomorphic IC for object
2952  // originating from the same native context.
2953  CompileRun("function fun() { this.x = 1; }; var obj = new fun();"
2954  "function f(o) { return o.x; } f(obj); f(obj);");
2955  Handle<JSFunction> f =
2958  CcTest::global()->Get(v8_str("f"))));
2959 
2960  Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
2961  CHECK(ic_before->ic_state() == MONOMORPHIC);
2962 
2963  SimulateIncrementalMarking();
2965 
2966  Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
2967  CHECK(ic_after->ic_state() == MONOMORPHIC);
2968 }
2969 
2970 
2971 TEST(IncrementalMarkingClearsMonomorphicIC) {
2972  if (i::FLAG_always_opt) return;
2975  v8::Local<v8::Value> obj1;
2976 
2977  {
2978  LocalContext env;
2979  CompileRun("function fun() { this.x = 1; }; var obj = new fun();");
2980  obj1 = env->Global()->Get(v8_str("obj"));
2981  }
2982 
2983  // Prepare function f that contains a monomorphic IC for object
2984  // originating from a different native context.
2985  CcTest::global()->Set(v8_str("obj1"), obj1);
2986  CompileRun("function f(o) { return o.x; } f(obj1); f(obj1);");
2987  Handle<JSFunction> f =
2990  CcTest::global()->Get(v8_str("f"))));
2991 
2992  Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
2993  CHECK(ic_before->ic_state() == MONOMORPHIC);
2994 
2995  // Fire context dispose notification.
2997  SimulateIncrementalMarking();
2999 
3000  Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
3001  CHECK(IC::IsCleared(ic_after));
3002 }
3003 
3004 
3005 TEST(IncrementalMarkingClearsPolymorphicIC) {
3006  if (i::FLAG_always_opt) return;
3009  v8::Local<v8::Value> obj1, obj2;
3010 
3011  {
3012  LocalContext env;
3013  CompileRun("function fun() { this.x = 1; }; var obj = new fun();");
3014  obj1 = env->Global()->Get(v8_str("obj"));
3015  }
3016 
3017  {
3018  LocalContext env;
3019  CompileRun("function fun() { this.x = 2; }; var obj = new fun();");
3020  obj2 = env->Global()->Get(v8_str("obj"));
3021  }
3022 
3023  // Prepare function f that contains a polymorphic IC for objects
3024  // originating from two different native contexts.
3025  CcTest::global()->Set(v8_str("obj1"), obj1);
3026  CcTest::global()->Set(v8_str("obj2"), obj2);
3027  CompileRun("function f(o) { return o.x; } f(obj1); f(obj1); f(obj2);");
3028  Handle<JSFunction> f =
3031  CcTest::global()->Get(v8_str("f"))));
3032 
3033  Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
3034  CHECK(ic_before->ic_state() == POLYMORPHIC);
3035 
3036  // Fire context dispose notification.
3038  SimulateIncrementalMarking();
3040 
3041  Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
3042  CHECK(IC::IsCleared(ic_after));
3043 }
3044 
3045 
3047  public:
3048  explicit SourceResource(const char* data)
3049  : data_(data), length_(strlen(data)) { }
3050 
3051  virtual void Dispose() {
3052  i::DeleteArray(data_);
3053  data_ = NULL;
3054  }
3055 
3056  const char* data() const { return data_; }
3057 
3058  size_t length() const { return length_; }
3059 
3060  bool IsDisposed() { return data_ == NULL; }
3061 
3062  private:
3063  const char* data_;
3064  size_t length_;
3065 };
3066 
3067 
3068 void ReleaseStackTraceDataTest(const char* source, const char* accessor) {
3069  // Test that the data retained by the Error.stack accessor is released
3070  // after the first time the accessor is fired. We use external string
3071  // to check whether the data is being released since the external string
3072  // resource's callback is fired when the external string is GC'ed.
3074  SourceResource* resource = new SourceResource(i::StrDup(source));
3075  {
3077  v8::Handle<v8::String> source_string =
3080  v8::Script::Compile(source_string)->Run();
3081  CHECK(!resource->IsDisposed());
3082  }
3083  // CcTest::heap()->CollectAllAvailableGarbage();
3084  CHECK(!resource->IsDisposed());
3085 
3086  CompileRun(accessor);
3088 
3089  // External source has been released.
3090  CHECK(resource->IsDisposed());
3091  delete resource;
3092 }
3093 
3094 
3095 TEST(ReleaseStackTraceData) {
3096  if (i::FLAG_always_opt) {
3097  // TODO(ulan): Remove this once the memory leak via code_next_link is fixed.
3098  // See: https://codereview.chromium.org/181833004/
3099  return;
3100  }
3101  FLAG_use_ic = false; // ICs retain objects.
3102  FLAG_concurrent_recompilation = false;
3104  static const char* source1 = "var error = null; "
3105  /* Normal Error */ "try { "
3106  " throw new Error(); "
3107  "} catch (e) { "
3108  " error = e; "
3109  "} ";
3110  static const char* source2 = "var error = null; "
3111  /* Stack overflow */ "try { "
3112  " (function f() { f(); })(); "
3113  "} catch (e) { "
3114  " error = e; "
3115  "} ";
3116  static const char* source3 = "var error = null; "
3117  /* Normal Error */ "try { "
3118  /* as prototype */ " throw new Error(); "
3119  "} catch (e) { "
3120  " error = {}; "
3121  " error.__proto__ = e; "
3122  "} ";
3123  static const char* source4 = "var error = null; "
3124  /* Stack overflow */ "try { "
3125  /* as prototype */ " (function f() { f(); })(); "
3126  "} catch (e) { "
3127  " error = {}; "
3128  " error.__proto__ = e; "
3129  "} ";
3130  static const char* getter = "error.stack";
3131  static const char* setter = "error.stack = 0";
3132 
3133  ReleaseStackTraceDataTest(source1, setter);
3134  ReleaseStackTraceDataTest(source2, setter);
3135  // We do not test source3 and source4 with setter, since the setter is
3136  // supposed to (untypically) write to the receiver, not the holder. This is
3137  // to emulate the behavior of a data property.
3138 
3139  ReleaseStackTraceDataTest(source1, getter);
3140  ReleaseStackTraceDataTest(source2, getter);
3141  ReleaseStackTraceDataTest(source3, getter);
3142  ReleaseStackTraceDataTest(source4, getter);
3143 }
3144 
3145 
3146 TEST(Regress159140) {
3147  i::FLAG_allow_natives_syntax = true;
3148  i::FLAG_flush_code_incrementally = true;
3150  Isolate* isolate = CcTest::i_isolate();
3151  Heap* heap = isolate->heap();
3152  HandleScope scope(isolate);
3153 
3154  // Perform one initial GC to enable code flushing.
3156 
3157  // Prepare several closures that are all eligible for code flushing
3158  // because all reachable ones are not optimized. Make sure that the
3159  // optimized code object is directly reachable through a handle so
3160  // that it is marked black during incremental marking.
3162  {
3163  HandleScope inner_scope(isolate);
3164  CompileRun("function h(x) {}"
3165  "function mkClosure() {"
3166  " return function(x) { return x + 1; };"
3167  "}"
3168  "var f = mkClosure();"
3169  "var g = mkClosure();"
3170  "f(1); f(2);"
3171  "g(1); g(2);"
3172  "h(1); h(2);"
3173  "%OptimizeFunctionOnNextCall(f); f(3);"
3174  "%OptimizeFunctionOnNextCall(h); h(3);");
3175 
3176  Handle<JSFunction> f =
3179  CcTest::global()->Get(v8_str("f"))));
3180  CHECK(f->is_compiled());
3181  CompileRun("f = null;");
3182 
3183  Handle<JSFunction> g =
3186  CcTest::global()->Get(v8_str("g"))));
3187  CHECK(g->is_compiled());
3188  const int kAgingThreshold = 6;
3189  for (int i = 0; i < kAgingThreshold; i++) {
3190  g->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
3191  }
3192 
3193  code = inner_scope.CloseAndEscape(Handle<Code>(f->code()));
3194  }
3195 
3196  // Simulate incremental marking so that the functions are enqueued as
3197  // code flushing candidates. Then optimize one function. Finally
3198  // finish the GC to complete code flushing.
3199  SimulateIncrementalMarking();
3200  CompileRun("%OptimizeFunctionOnNextCall(g); g(3);");
3202 
3203  // Unoptimized code is missing and the deoptimizer will go ballistic.
3204  CompileRun("g('bozo');");
3205 }
3206 
3207 
3208 TEST(Regress165495) {
3209  i::FLAG_allow_natives_syntax = true;
3210  i::FLAG_flush_code_incrementally = true;
3212  Isolate* isolate = CcTest::i_isolate();
3213  Heap* heap = isolate->heap();
3214  HandleScope scope(isolate);
3215 
3216  // Perform one initial GC to enable code flushing.
3218 
3219  // Prepare an optimized closure that the optimized code map will get
3220  // populated. Then age the unoptimized code to trigger code flushing
3221  // but make sure the optimized code is unreachable.
3222  {
3223  HandleScope inner_scope(isolate);
3224  CompileRun("function mkClosure() {"
3225  " return function(x) { return x + 1; };"
3226  "}"
3227  "var f = mkClosure();"
3228  "f(1); f(2);"
3229  "%OptimizeFunctionOnNextCall(f); f(3);");
3230 
3231  Handle<JSFunction> f =
3234  CcTest::global()->Get(v8_str("f"))));
3235  CHECK(f->is_compiled());
3236  const int kAgingThreshold = 6;
3237  for (int i = 0; i < kAgingThreshold; i++) {
3238  f->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
3239  }
3240 
3241  CompileRun("f = null;");
3242  }
3243 
3244  // Simulate incremental marking so that unoptimized code is flushed
3245  // even though it still is cached in the optimized code map.
3246  SimulateIncrementalMarking();
3248 
3249  // Make a new closure that will get code installed from the code map.
3250  // Unoptimized code is missing and the deoptimizer will go ballistic.
3251  CompileRun("var g = mkClosure(); g('bozo');");
3252 }
3253 
3254 
3255 TEST(Regress169209) {
3256  i::FLAG_stress_compaction = false;
3257  i::FLAG_allow_natives_syntax = true;
3258  i::FLAG_flush_code_incrementally = true;
3259 
3261  Isolate* isolate = CcTest::i_isolate();
3262  Heap* heap = isolate->heap();
3263  HandleScope scope(isolate);
3264 
3265  // Perform one initial GC to enable code flushing.
3267 
3268  // Prepare a shared function info eligible for code flushing for which
3269  // the unoptimized code will be replaced during optimization.
3271  {
3272  HandleScope inner_scope(isolate);
3273  CompileRun("function f() { return 'foobar'; }"
3274  "function g(x) { if (x) f(); }"
3275  "f();"
3276  "g(false);"
3277  "g(false);");
3278 
3279  Handle<JSFunction> f =
3282  CcTest::global()->Get(v8_str("f"))));
3283  CHECK(f->is_compiled());
3284  const int kAgingThreshold = 6;
3285  for (int i = 0; i < kAgingThreshold; i++) {
3286  f->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
3287  }
3288 
3289  shared1 = inner_scope.CloseAndEscape(handle(f->shared(), isolate));
3290  }
3291 
3292  // Prepare a shared function info eligible for code flushing that will
3293  // represent the dangling tail of the candidate list.
3295  {
3296  HandleScope inner_scope(isolate);
3297  CompileRun("function flushMe() { return 0; }"
3298  "flushMe(1);");
3299 
3300  Handle<JSFunction> f =
3303  CcTest::global()->Get(v8_str("flushMe"))));
3304  CHECK(f->is_compiled());
3305  const int kAgingThreshold = 6;
3306  for (int i = 0; i < kAgingThreshold; i++) {
3307  f->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
3308  }
3309 
3310  shared2 = inner_scope.CloseAndEscape(handle(f->shared(), isolate));
3311  }
3312 
3313  // Simulate incremental marking and collect code flushing candidates.
3314  SimulateIncrementalMarking();
3315  CHECK(shared1->code()->gc_metadata() != NULL);
3316 
3317  // Optimize function and make sure the unoptimized code is replaced.
3318 #ifdef DEBUG
3319  FLAG_stop_at = "f";
3320 #endif
3321  CompileRun("%OptimizeFunctionOnNextCall(g);"
3322  "g(false);");
3323 
3324  // Finish garbage collection cycle.
3326  CHECK(shared1->code()->gc_metadata() == NULL);
3327 }
3328 
3329 
3330 // Helper function that simulates a fill new-space in the heap.
3331 static inline void AllocateAllButNBytes(v8::internal::NewSpace* space,
3332  int extra_bytes) {
3333  int space_remaining = static_cast<int>(
3334  *space->allocation_limit_address() - *space->allocation_top_address());
3335  CHECK(space_remaining >= extra_bytes);
3336  int new_linear_size = space_remaining - extra_bytes;
3337  v8::internal::MaybeObject* maybe = space->AllocateRaw(new_linear_size);
3339  node->set_size(space->heap(), new_linear_size);
3340 }
3341 
3342 
3343 TEST(Regress169928) {
3344  i::FLAG_allow_natives_syntax = true;
3345  i::FLAG_crankshaft = false;
3347  Isolate* isolate = CcTest::i_isolate();
3348  Factory* factory = isolate->factory();
3350 
3351  // Some flags turn Scavenge collections into Mark-sweep collections
3352  // and hence are incompatible with this test case.
3353  if (FLAG_gc_global || FLAG_stress_compaction) return;
3354 
3355  // Prepare the environment
3356  CompileRun("function fastliteralcase(literal, value) {"
3357  " literal[0] = value;"
3358  " return literal;"
3359  "}"
3360  "function get_standard_literal() {"
3361  " var literal = [1, 2, 3];"
3362  " return literal;"
3363  "}"
3364  "obj = fastliteralcase(get_standard_literal(), 1);"
3365  "obj = fastliteralcase(get_standard_literal(), 1.5);"
3366  "obj = fastliteralcase(get_standard_literal(), 2);");
3367 
3368  // prepare the heap
3369  v8::Local<v8::String> mote_code_string =
3370  v8_str("fastliteralcase(mote, 2.5);");
3371 
3372  v8::Local<v8::String> array_name = v8_str("mote");
3373  CcTest::global()->Set(array_name, v8::Int32::New(CcTest::isolate(), 0));
3374 
3375  // First make sure we flip spaces
3377 
3378  // Allocate the object.
3379  Handle<FixedArray> array_data = factory->NewFixedArray(2, NOT_TENURED);
3380  array_data->set(0, Smi::FromInt(1));
3381  array_data->set(1, Smi::FromInt(2));
3382 
3383  AllocateAllButNBytes(CcTest::heap()->new_space(),
3385  kPointerSize);
3386 
3387  Handle<JSArray> array = factory->NewJSArrayWithElements(array_data,
3389  NOT_TENURED);
3390 
3391  CHECK_EQ(Smi::FromInt(2), array->length());
3392  CHECK(array->HasFastSmiOrObjectElements());
3393 
3394  // We need filler the size of AllocationMemento object, plus an extra
3395  // fill pointer value.
3396  MaybeObject* maybe_object = CcTest::heap()->AllocateRaw(
3398  Object* obj = NULL;
3399  CHECK(maybe_object->ToObject(&obj));
3400  Address addr_obj = reinterpret_cast<Address>(
3401  reinterpret_cast<byte*>(obj - kHeapObjectTag));
3402  CcTest::heap()->CreateFillerObjectAt(addr_obj,
3404 
3405  // Give the array a name, making sure not to allocate strings.
3406  v8::Handle<v8::Object> array_obj = v8::Utils::ToLocal(array);
3407  CcTest::global()->Set(array_name, array_obj);
3408 
3409  // This should crash with a protection violation if we are running a build
3410  // with the bug.
3411  AlwaysAllocateScope aa_scope(isolate);
3412  v8::Script::Compile(mote_code_string)->Run();
3413 }
3414 
3415 
3416 TEST(Regress168801) {
3417  i::FLAG_always_compact = true;
3418  i::FLAG_cache_optimized_code = false;
3419  i::FLAG_allow_natives_syntax = true;
3420  i::FLAG_flush_code_incrementally = true;
3422  Isolate* isolate = CcTest::i_isolate();
3423  Heap* heap = isolate->heap();
3424  HandleScope scope(isolate);
3425 
3426  // Perform one initial GC to enable code flushing.
3428 
3429  // Ensure the code ends up on an evacuation candidate.
3430  SimulateFullSpace(heap->code_space());
3431 
3432  // Prepare an unoptimized function that is eligible for code flushing.
3433  Handle<JSFunction> function;
3434  {
3435  HandleScope inner_scope(isolate);
3436  CompileRun("function mkClosure() {"
3437  " return function(x) { return x + 1; };"
3438  "}"
3439  "var f = mkClosure();"
3440  "f(1); f(2);");
3441 
3442  Handle<JSFunction> f =
3445  CcTest::global()->Get(v8_str("f"))));
3446  CHECK(f->is_compiled());
3447  const int kAgingThreshold = 6;
3448  for (int i = 0; i < kAgingThreshold; i++) {
3449  f->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
3450  }
3451 
3452  function = inner_scope.CloseAndEscape(handle(*f, isolate));
3453  }
3454 
3455  // Simulate incremental marking so that unoptimized function is enqueued as a
3456  // candidate for code flushing. The shared function info however will not be
3457  // explicitly enqueued.
3458  SimulateIncrementalMarking();
3459 
3460  // Now optimize the function so that it is taken off the candidate list.
3461  {
3462  HandleScope inner_scope(isolate);
3463  CompileRun("%OptimizeFunctionOnNextCall(f); f(3);");
3464  }
3465 
3466  // This cycle will bust the heap and subsequent cycles will go ballistic.
3469 }
3470 
3471 
3472 TEST(Regress173458) {
3473  i::FLAG_always_compact = true;
3474  i::FLAG_cache_optimized_code = false;
3475  i::FLAG_allow_natives_syntax = true;
3476  i::FLAG_flush_code_incrementally = true;
3478  Isolate* isolate = CcTest::i_isolate();
3479  Heap* heap = isolate->heap();
3480  HandleScope scope(isolate);
3481 
3482  // Perform one initial GC to enable code flushing.
3484 
3485  // Ensure the code ends up on an evacuation candidate.
3486  SimulateFullSpace(heap->code_space());
3487 
3488  // Prepare an unoptimized function that is eligible for code flushing.
3489  Handle<JSFunction> function;
3490  {
3491  HandleScope inner_scope(isolate);
3492  CompileRun("function mkClosure() {"
3493  " return function(x) { return x + 1; };"
3494  "}"
3495  "var f = mkClosure();"
3496  "f(1); f(2);");
3497 
3498  Handle<JSFunction> f =
3501  CcTest::global()->Get(v8_str("f"))));
3502  CHECK(f->is_compiled());
3503  const int kAgingThreshold = 6;
3504  for (int i = 0; i < kAgingThreshold; i++) {
3505  f->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
3506  }
3507 
3508  function = inner_scope.CloseAndEscape(handle(*f, isolate));
3509  }
3510 
3511  // Simulate incremental marking so that unoptimized function is enqueued as a
3512  // candidate for code flushing. The shared function info however will not be
3513  // explicitly enqueued.
3514  SimulateIncrementalMarking();
3515 
3516 #ifdef ENABLE_DEBUGGER_SUPPORT
3517  // Now enable the debugger which in turn will disable code flushing.
3518  CHECK(isolate->debug()->Load());
3519 #endif // ENABLE_DEBUGGER_SUPPORT
3520 
3521  // This cycle will bust the heap and subsequent cycles will go ballistic.
3524 }
3525 
3526 
3527 class DummyVisitor : public ObjectVisitor {
3528  public:
3529  void VisitPointers(Object** start, Object** end) { }
3530 };
3531 
3532 
3535  Isolate* isolate = CcTest::i_isolate();
3536  Heap* heap = isolate->heap();
3537  v8::HandleScope scope(reinterpret_cast<v8::Isolate*>(isolate));
3538  HandleScopeData* data = isolate->handle_scope_data();
3539  Handle<Object> init(heap->empty_string(), isolate);
3540  while (data->next < data->limit) {
3541  Handle<Object> obj(heap->empty_string(), isolate);
3542  }
3543  // An entire block of handles has been filled.
3544  // Next handle would require a new block.
3545  ASSERT(data->next == data->limit);
3546 
3547  DeferredHandleScope deferred(isolate);
3548  DummyVisitor visitor;
3549  isolate->handle_scope_implementer()->Iterate(&visitor);
3550  delete deferred.Detach();
3551 }
3552 
3553 
3554 TEST(IncrementalMarkingStepMakesBigProgressWithLargeObjects) {
3557  CompileRun("function f(n) {"
3558  " var a = new Array(n);"
3559  " for (var i = 0; i < n; i += 100) a[i] = i;"
3560  "};"
3561  "f(10 * 1024 * 1024);");
3563  if (marking->IsStopped()) marking->Start();
3564  // This big step should be sufficient to mark the whole array.
3566  ASSERT(marking->IsComplete());
3567 }
3568 
3569 
3570 TEST(DisableInlineAllocation) {
3571  i::FLAG_allow_natives_syntax = true;
3574  CompileRun("function test() {"
3575  " var x = [];"
3576  " for (var i = 0; i < 10; i++) {"
3577  " x[i] = [ {}, [1,2,3], [1,x,3] ];"
3578  " }"
3579  "}"
3580  "function run() {"
3581  " %OptimizeFunctionOnNextCall(test);"
3582  " test();"
3583  " %DeoptimizeFunction(test);"
3584  "}");
3585 
3586  // Warm-up with inline allocation enabled.
3587  CompileRun("test(); test(); run();");
3588 
3589  // Run test with inline allocation disabled.
3591  CompileRun("run()");
3592 
3593  // Run test with inline allocation disabled and pretenuring.
3595  CompileRun("run()");
3596 
3597  // Run test with inline allocation re-enabled.
3599  CompileRun("run()");
3600 }
3601 
3602 
3603 static int AllocationSitesCount(Heap* heap) {
3604  int count = 0;
3605  for (Object* site = heap->allocation_sites_list();
3606  !(site->IsUndefined());
3607  site = AllocationSite::cast(site)->weak_next()) {
3608  count++;
3609  }
3610  return count;
3611 }
3612 
3613 
3614 TEST(EnsureAllocationSiteDependentCodesProcessed) {
3615  if (i::FLAG_always_opt || !i::FLAG_crankshaft) return;
3616  i::FLAG_allow_natives_syntax = true;
3618  Isolate* isolate = CcTest::i_isolate();
3619  v8::internal::Heap* heap = CcTest::heap();
3620  GlobalHandles* global_handles = isolate->global_handles();
3621 
3622  if (!isolate->use_crankshaft()) return;
3623 
3624  // The allocation site at the head of the list is ours.
3626  {
3627  LocalContext context;
3628  v8::HandleScope scope(context->GetIsolate());
3629 
3630  int count = AllocationSitesCount(heap);
3631  CompileRun("var bar = function() { return (new Array()); };"
3632  "var a = bar();"
3633  "bar();"
3634  "bar();");
3635 
3636  // One allocation site should have been created.
3637  int new_count = AllocationSitesCount(heap);
3638  CHECK_EQ(new_count, (count + 1));
3640  global_handles->Create(
3642 
3643  CompileRun("%OptimizeFunctionOnNextCall(bar); bar();");
3644 
3645  DependentCode::GroupStartIndexes starts(site->dependent_code());
3646  CHECK_GE(starts.number_of_entries(), 1);
3648  CHECK(site->dependent_code()->is_code_at(index));
3649  Code* function_bar = site->dependent_code()->code_at(index);
3650  Handle<JSFunction> bar_handle =
3653  CcTest::global()->Get(v8_str("bar"))));
3654  CHECK_EQ(bar_handle->code(), function_bar);
3655  }
3656 
3657  // Now make sure that a gc should get rid of the function, even though we
3658  // still have the allocation site alive.
3659  for (int i = 0; i < 4; i++) {
3660  heap->CollectAllGarbage(false);
3661  }
3662 
3663  // The site still exists because of our global handle, but the code is no
3664  // longer referred to by dependent_code().
3665  DependentCode::GroupStartIndexes starts(site->dependent_code());
3667  CHECK(!(site->dependent_code()->is_code_at(index)));
3668 }
3669 
3670 
3671 TEST(CellsInOptimizedCodeAreWeak) {
3672  if (i::FLAG_always_opt || !i::FLAG_crankshaft) return;
3673  i::FLAG_weak_embedded_objects_in_optimized_code = true;
3674  i::FLAG_allow_natives_syntax = true;
3676  Isolate* isolate = CcTest::i_isolate();
3677  v8::internal::Heap* heap = CcTest::heap();
3678 
3679  if (!isolate->use_crankshaft()) return;
3680  HandleScope outer_scope(heap->isolate());
3682  {
3683  LocalContext context;
3684  HandleScope scope(heap->isolate());
3685 
3686  CompileRun("bar = (function() {"
3687  " function bar() {"
3688  " return foo(1);"
3689  " };"
3690  " var foo = function(x) { with (x) { return 1 + x; } };"
3691  " bar(foo);"
3692  " bar(foo);"
3693  " bar(foo);"
3694  " %OptimizeFunctionOnNextCall(bar);"
3695  " bar(foo);"
3696  " return bar;})();");
3697 
3701  CcTest::global()->Get(v8_str("bar"))));
3702  code = scope.CloseAndEscape(Handle<Code>(bar->code()));
3703  }
3704 
3705  // Now make sure that a gc should get rid of the function
3706  for (int i = 0; i < 4; i++) {
3708  }
3709 
3710  ASSERT(code->marked_for_deoptimization());
3711 }
3712 
3713 
3714 TEST(ObjectsInOptimizedCodeAreWeak) {
3715  if (i::FLAG_always_opt || !i::FLAG_crankshaft) return;
3716  i::FLAG_weak_embedded_objects_in_optimized_code = true;
3717  i::FLAG_allow_natives_syntax = true;
3719  Isolate* isolate = CcTest::i_isolate();
3720  v8::internal::Heap* heap = CcTest::heap();
3721 
3722  if (!isolate->use_crankshaft()) return;
3723  HandleScope outer_scope(heap->isolate());
3725  {
3726  LocalContext context;
3727  HandleScope scope(heap->isolate());
3728 
3729  CompileRun("function bar() {"
3730  " return foo(1);"
3731  "};"
3732  "function foo(x) { with (x) { return 1 + x; } };"
3733  "bar();"
3734  "bar();"
3735  "bar();"
3736  "%OptimizeFunctionOnNextCall(bar);"
3737  "bar();");
3738 
3742  CcTest::global()->Get(v8_str("bar"))));
3743  code = scope.CloseAndEscape(Handle<Code>(bar->code()));
3744  }
3745 
3746  // Now make sure that a gc should get rid of the function
3747  for (int i = 0; i < 4; i++) {
3749  }
3750 
3751  ASSERT(code->marked_for_deoptimization());
3752 }
3753 
3754 
3755 
3756 static Handle<JSFunction> OptimizeDummyFunction(const char* name) {
3758  OS::SNPrintF(source,
3759  "function %s() { return 0; }"
3760  "%s(); %s();"
3761  "%%OptimizeFunctionOnNextCall(%s);"
3762  "%s();", name, name, name, name, name);
3763  CompileRun(source.start());
3764  Handle<JSFunction> fun =
3767  CcTest::global()->Get(v8_str(name))));
3768  return fun;
3769 }
3770 
3771 
3772 static int GetCodeChainLength(Code* code) {
3773  int result = 0;
3774  while (code->next_code_link()->IsCode()) {
3775  result++;
3776  code = Code::cast(code->next_code_link());
3777  }
3778  return result;
3779 }
3780 
3781 
3782 TEST(NextCodeLinkIsWeak) {
3783  i::FLAG_allow_natives_syntax = true;
3785  Isolate* isolate = CcTest::i_isolate();
3786  v8::internal::Heap* heap = CcTest::heap();
3787 
3788  if (!isolate->use_crankshaft()) return;
3789  HandleScope outer_scope(heap->isolate());
3792  int code_chain_length_before, code_chain_length_after;
3793  {
3794  HandleScope scope(heap->isolate());
3795  Handle<JSFunction> mortal = OptimizeDummyFunction("mortal");
3796  Handle<JSFunction> immortal = OptimizeDummyFunction("immortal");
3797  CHECK_EQ(immortal->code()->next_code_link(), mortal->code());
3798  code_chain_length_before = GetCodeChainLength(immortal->code());
3799  // Keep the immortal code and let the mortal code die.
3800  code = scope.CloseAndEscape(Handle<Code>(immortal->code()));
3801  CompileRun("mortal = null; immortal = null;");
3802  }
3804  // Now mortal code should be dead.
3805  code_chain_length_after = GetCodeChainLength(*code);
3806  CHECK_EQ(code_chain_length_before - 1, code_chain_length_after);
3807 }
3808 
3809 
3810 static Handle<Code> DummyOptimizedCode(Isolate* isolate) {
3812  MacroAssembler masm(isolate, buffer, sizeof(buffer));
3813  CodeDesc desc;
3814  masm.Prologue(BUILD_FUNCTION_FRAME);
3815  masm.GetCode(&desc);
3816  Handle<Object> undefined(isolate->heap()->undefined_value(), isolate);
3817  Handle<Code> code = isolate->factory()->NewCode(
3818  desc, Code::ComputeFlags(Code::OPTIMIZED_FUNCTION), undefined);
3819  CHECK(code->IsCode());
3820  return code;
3821 }
3822 
3823 
3824 TEST(NextCodeLinkIsWeak2) {
3825  i::FLAG_allow_natives_syntax = true;
3827  Isolate* isolate = CcTest::i_isolate();
3828  v8::internal::Heap* heap = CcTest::heap();
3829 
3830  if (!isolate->use_crankshaft()) return;
3831  HandleScope outer_scope(heap->isolate());
3833  Handle<Context> context(Context::cast(heap->native_contexts_list()), isolate);
3834  Handle<Code> new_head;
3835  Handle<Object> old_head(context->get(Context::OPTIMIZED_CODE_LIST), isolate);
3836  {
3837  HandleScope scope(heap->isolate());
3838  Handle<Code> immortal = DummyOptimizedCode(isolate);
3839  Handle<Code> mortal = DummyOptimizedCode(isolate);
3840  mortal->set_next_code_link(*old_head);
3841  immortal->set_next_code_link(*mortal);
3842  context->set(Context::OPTIMIZED_CODE_LIST, *immortal);
3843  new_head = scope.CloseAndEscape(immortal);
3844  }
3846  // Now mortal code should be dead.
3847  CHECK_EQ(*old_head, new_head->next_code_link());
3848 }
3849 
3850 
3851 #ifdef DEBUG
3852 TEST(AddInstructionChangesNewSpacePromotion) {
3853  i::FLAG_allow_natives_syntax = true;
3854  i::FLAG_expose_gc = true;
3855  i::FLAG_stress_compaction = true;
3856  i::FLAG_gc_interval = 1000;
3858  if (!i::FLAG_allocation_site_pretenuring) return;
3860  Isolate* isolate = CcTest::i_isolate();
3861  Heap* heap = isolate->heap();
3862 
3863  CompileRun(
3864  "function add(a, b) {"
3865  " return a + b;"
3866  "}"
3867  "add(1, 2);"
3868  "add(\"a\", \"b\");"
3869  "var oldSpaceObject;"
3870  "gc();"
3871  "function crash(x) {"
3872  " var object = {a: null, b: null};"
3873  " var result = add(1.5, x | 0);"
3874  " object.a = result;"
3875  " oldSpaceObject = object;"
3876  " return object;"
3877  "}"
3878  "crash(1);"
3879  "crash(1);"
3880  "%OptimizeFunctionOnNextCall(crash);"
3881  "crash(1);");
3882 
3885  v8::Handle<v8::Function>::Cast(global->Get(v8_str("crash")));
3886  v8::Handle<v8::Value> args1[] = { v8_num(1) };
3887  heap->DisableInlineAllocation();
3888  heap->set_allocation_timeout(1);
3889  g->Call(global, 1, args1);
3891 }
3892 
3893 
3894 void OnFatalErrorExpectOOM(const char* location, const char* message) {
3895  // Exit with 0 if the location matches our expectation.
3896  exit(strcmp(location, "CALL_AND_RETRY_LAST"));
3897 }
3898 
3899 
3900 TEST(CEntryStubOOM) {
3901  i::FLAG_allow_natives_syntax = true;
3904  v8::V8::SetFatalErrorHandler(OnFatalErrorExpectOOM);
3905 
3906  v8::Handle<v8::Value> result = CompileRun(
3907  "%SetFlags('--gc-interval=1');"
3908  "var a = [];"
3909  "a.__proto__ = [];"
3910  "a.unshift(1)");
3911 
3912  CHECK(result->IsNumber());
3913 }
3914 
3915 #endif // DEBUG
void Enter()
Definition: api.cc:650
byte * Address
Definition: globals.h:186
void ReleaseStackTraceDataTest(const char *source, const char *accessor)
Definition: test-heap.cc:3068
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
const SwVfpRegister s2
static V8_INLINE Local< T > New(Isolate *isolate, Handle< T > that)
Definition: v8.h:5713
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if available(ARM only)") DEFINE_bool(enable_sudiv
static V8_INLINE Object * Cast(Value *obj)
Definition: v8.h:6359
static const int kMaxLength
Definition: objects.h:3085
static void Destroy(Object **location)
Handle< T > EscapeFrom(v8::EscapableHandleScope *scope)
Definition: api.h:318
Handle< JSObject > NewJSObject(Handle< JSFunction > constructor, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:1319
#define CHECK_EQ(expected, value)
Definition: checks.h:252
Local< Value > Call(Handle< Value > recv, int argc, Handle< Value > argv[])
Definition: api.cc:3996
void set_size(Heap *heap, int size_in_bytes)
Definition: spaces.cc:2008
static FreeListNode * cast(MaybeObject *maybe)
Definition: spaces.h:1523
bool Contains(Address addr)
Definition: spaces.h:377
CompilationCache * compilation_cache()
Definition: isolate.h:867
int ReservedSemiSpaceSize()
Definition: heap.h:597
void PrintF(const char *format,...)
Definition: v8utils.cc:40
void SetNewSpaceHighPromotionModeActive(bool mode)
Definition: heap.h:1563
void CollectAllGarbage(int flags, const char *gc_reason=NULL, const GCCallbackFlags gc_callback_flags=kNoGCCallbackFlags)
Definition: heap.cc:731
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf map
Definition: flags.cc:350
bool InNewSpace(Object *object)
Definition: heap-inl.h:307
static TypeFeedbackInfo * cast(Object *obj)
static String * cast(Object *obj)
HandleScopeImplementer * handle_scope_implementer()
Definition: isolate.h:902
Isolate * isolate()
Definition: heap-inl.h:624
Local< Value > Get(Handle< Value > key)
Definition: api.cc:3139
static Smi * FromInt(int value)
Definition: objects-inl.h:1209
const int KB
Definition: globals.h:245
#define CHECK_GT(a, b)
Definition: checks.h:260
MUST_USE_RESULT MaybeObject * CopyJSObject(JSObject *source, AllocationSite *site=NULL)
Definition: heap.cc:4712
static void SetIdentityHash(Handle< JSObject > object, Handle< Smi > hash)
Definition: objects.cc:4781
static HeapObject * cast(Object *obj)
static Handle< T > cast(Handle< S > that)
Definition: handles.h:75
void AgeInlineCaches()
Definition: heap.h:1866
Handle< String > NewStringFromAscii(Vector< const char > str, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.h:141
static const int kProtoTransitionElementsPerEntry
Definition: objects.h:6133
internal::Object ** limit
Definition: handles.h:321
const int kVariableSizeSentinel
Definition: objects.h:314
const char * data() const
Definition: test-heap.cc:3056
static Handle< Object > SetPrototype(Handle< JSObject > object, Handle< Object > value, bool skip_hidden_prototypes=false)
Definition: objects.cc:11703
Address * allocation_top_address()
Definition: spaces.h:2534
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage message
Definition: flags.cc:665
static AllocationSite * cast(Object *obj)
Handle< JSArray > NewJSArrayWithElements(Handle< FixedArrayBase > elements, ElementsKind elements_kind, int length, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:1456
static const int kMinimalBufferSize
Definition: assembler.h:89
static v8::Local< v8::Object > global()
Definition: cctest.h:110
Local< Value > GetHiddenValue(Handle< String > key)
Definition: api.cc:3679
static bool IsNearDeath(Object **location)
static Failure * Exception()
Definition: objects-inl.h:1244
HandleScopeData * handle_scope_data()
Definition: isolate.h:900
#define ASSERT(condition)
Definition: checks.h:329
void Step(intptr_t allocated, CompletionAction action)
static i::Heap * heap()
Definition: cctest.h:106
static Context * cast(Object *context)
Definition: contexts.h:244
static Local< Integer > New(Isolate *isolate, int32_t value)
Definition: api.cc:6233
Handle< Object > NewNumber(double value, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:998
#define CHECK(condition)
Definition: checks.h:75
Handle< Object > GetProperty(Handle< JSReceiver > obj, const char *name)
Definition: handles.cc:196
static const int kMaxSize
Definition: objects.h:3083
intptr_t EffectiveCapacity()
Definition: spaces.h:2449
Factory * factory()
Definition: isolate.h:995
#define CHECK_GE(a, b)
Definition: checks.h:261
static Code * cast(Object *obj)
bool Equals(Handle< Value > that) const
Definition: api.cc:2950
Object * FindCodeObject(Address a)
Definition: isolate.cc:2286
static Smi * cast(Object *object)
v8::Isolate * GetIsolate()
Definition: api.cc:5233
int isnan(double x)
static const int kSize
Definition: objects.h:10077
uint8_t byte
Definition: globals.h:185
GlobalObject * global_object()
Definition: contexts.h:388
int NotifyContextDisposed()
Definition: heap.cc:872
Handle< String > NewStringFromUtf8(Vector< const char > str, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:273
DeferredHandles * Detach()
Definition: handles.cc:753
void EnsureHeapIsIterable()
Definition: heap.cc:5679
Handle< Map > CopyMap(Handle< Map > map, int extra_inobject_props)
Definition: factory.cc:855
Handle< JSFunction > NewFunction(Handle< String > name, Handle< Object > prototype)
Definition: factory.cc:1663
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object size
Definition: flags.cc:211
T * start() const
Definition: utils.h:426
bool always_allocate()
Definition: heap.h:668
virtual void Dispose()
Definition: test-heap.cc:3051
bool AdvanceSweeper(intptr_t bytes_to_sweep)
Definition: spaces.cc:2583
bool Contains(Address a)
Definition: spaces.h:2427
bool Contains(Address a)
Definition: spaces-inl.h:179
static SlicedString * cast(Object *obj)
static const int kProtoTransitionMapOffset
Definition: objects.h:6135
Handle< Object > Create(Object *value)
static Failure * RetryAfterGC()
Definition: objects-inl.h:1255
void CollectAllAvailableGarbage(const char *gc_reason=NULL)
Definition: heap.cc:743
static const int kMinValue
Definition: objects.h:1679
static const int kNoGCFlags
Definition: heap.h:1257
const int kPointerSize
Definition: globals.h:268
virtual intptr_t Size()
Definition: spaces.h:2438
int GetFieldIndex(int descriptor_number)
Definition: objects-inl.h:2664
static Handle< JSObject > Copy(Handle< JSObject > object)
Definition: objects.cc:5636
const int kHeapObjectTag
Definition: v8.h:5473
static void SetFatalErrorHandler(FatalErrorCallback that)
Definition: api.cc:393
static int ContextDisposedNotification()
Definition: api.cc:5108
void Start(CompactionFlag flag=ALLOW_COMPACTION)
#define __
Object * RawFastPropertyAt(int index)
Definition: objects-inl.h:1964
GlobalHandles * global_handles()
Definition: isolate.h:918
static Local< Script > Compile(Handle< String > source, ScriptOrigin *origin=NULL, ScriptData *script_data=NULL)
Definition: api.cc:1832
SourceResource(const char *data)
Definition: test-heap.cc:3048
static const int kMaxRegularHeapObjectSize
Definition: spaces.h:820
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
static bool IsCleared(Code *code)
Definition: ic.h:133
static V8_INLINE Handle< T > Cast(Handle< S > that)
Definition: v8.h:297
Local< Object > Global()
Definition: api.cc:5239
Handle< FixedArray > NewFixedArray(int size, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:53
OldSpace * old_pointer_space()
Definition: heap.h:638
static i::Isolate * i_isolate()
Definition: cctest.h:102
static const int kSize
Definition: objects.h:6440
static Code * GetCodeFromTargetAddress(Address address)
Definition: objects-inl.h:4662
bool is_inline_cache_stub()
Definition: objects-inl.h:4568
bool SetHiddenValue(Handle< String > key, Handle< Value > value)
Definition: api.cc:3661
OldSpace * code_space()
Definition: heap.h:640
MUST_USE_RESULT MaybeObject * AllocateJSObjectFromMap(Map *map, PretenureFlag pretenure=NOT_TENURED, bool alloc_props=true, AllocationSite *allocation_site=NULL)
Definition: heap.cc:4488
#define V8_PTR_PREFIX
Definition: globals.h:220
InlineCacheState ic_state()
Definition: objects-inl.h:4308
static v8::internal::Handle< To > OpenHandle(v8::Local< From > handle)
Definition: api.h:308
static const int kAbortIncrementalMarkingMask
Definition: heap.h:1260
Vector< const char > CStrVector(const char *data)
Definition: utils.h:574
bool CollectGarbage(AllocationSpace space, const char *gc_reason=NULL, const GCCallbackFlags gc_callback_flags=kNoGCCallbackFlags)
Definition: heap-inl.h:554
MUST_USE_RESULT MaybeObject * GetProperty(Name *key)
Definition: objects-inl.h:1081
V8_INLINE P * GetParameter() const
Definition: v8.h:451
int StrLength(const char *string)
Definition: utils.h:253
static Local< Context > ToLocal(v8::internal::Handle< v8::internal::Context > obj)
bool use_crankshaft() const
Definition: isolate.h:1017
#define CHECK_LE(a, b)
Definition: checks.h:263
static Local< Object > New(Isolate *isolate)
Definition: api.cc:5589
internal::Object ** next
Definition: handles.h:320
intptr_t SizeOfObjects()
Definition: heap.cc:473
static int SizeFor(int length)
Definition: objects.h:3067
static Handle< Object > SetElement(Handle< JSReceiver > object, uint32_t index, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode)
Definition: objects.cc:12387
static const int kProtoTransitionHeaderSize
Definition: objects.h:6131
Context * context()
Definition: isolate.h:557
const SwVfpRegister s1
Handle< String > NewProperSubString(Handle< String > str, int begin, int end)
Definition: factory.cc:475
static const int kHeaderSize
Definition: objects.h:3016
static Local< Context > New(Isolate *isolate, ExtensionConfiguration *extensions=NULL, Handle< ObjectTemplate > global_template=Handle< ObjectTemplate >(), Handle< Value > global_object=Handle< Value >())
Definition: api.cc:5188
static int SNPrintF(Vector< char > str, const char *format,...)
MUST_USE_RESULT MaybeObject * NumberFromDouble(double value, PretenureFlag pretenure=NOT_TENURED)
Definition: heap.cc:3819
Vector< const uint8_t > OneByteVector(const char *data, int length)
Definition: utils.h:578
MUST_USE_RESULT MaybeObject * CreateCode(const CodeDesc &desc, Code::Flags flags, Handle< Object > self_reference, bool immovable=false, bool crankshafted=false, int prologue_offset=Code::kPrologueOffsetNotSet)
Definition: heap.cc:4119
static void Initialize(Handle< JSArray > array, int capacity, int length=0)
Definition: objects.cc:11244
int InitialSemiSpaceSize()
Definition: heap.h:598
intptr_t Capacity()
Definition: spaces.h:2455
static Handle< Object > SetElementsLength(Handle< JSArray > array, Handle< Object > length)
Definition: objects.cc:11330
Handle< String > InternalizeOneByteString(Vector< const uint8_t > str)
Definition: factory.cc:232
static void InitializeVM()
Definition: cctest.h:116
static const int kSize
Definition: objects.h:1979
static ObjectHashTable * cast(Object *obj)
Definition: objects.h:4226
static Handle< Object > UninitializedSentinel(Isolate *isolate)
Definition: objects-inl.h:6675
void Exit()
Definition: api.cc:661
static Handle< Object > SetProperty(Handle< JSReceiver > object, Handle< Name > key, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode, StoreFromKeyed store_mode=MAY_BE_STORE_FROM_KEYED)
Definition: objects.cc:2858
bool is_null() const
Definition: handles.h:81
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:103
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
Definition: flags.cc:317
bool IsNumber() const
Definition: api.cc:2416
#define OBJECT_POINTER_ALIGN(value)
Definition: v8globals.h:386
Object * native_contexts_list()
Definition: heap.h:1354
static Object * cast(Object *value)
Definition: objects.h:1641
MUST_USE_RESULT MaybeObject * NumberFromUint32(uint32_t value, PretenureFlag pretenure=NOT_TENURED)
Definition: heap-inl.h:280
Heap * heap() const
Definition: spaces.h:900
IncrementalMarking * incremental_marking()
Definition: heap.h:1781
void EnableInlineAllocation()
Definition: heap.cc:6529
static Flags ComputeFlags(Kind kind, InlineCacheState ic_state=UNINITIALIZED, ExtraICState extra_ic_state=kNoExtraICState, StubType type=NORMAL, InlineCacheHolderFlag holder=OWN_MAP)
Definition: objects-inl.h:4601
static Local< String > NewExternal(Isolate *isolate, ExternalStringResource *resource)
Definition: api.cc:5493
static void MakeWeak(Object **location, void *parameter, WeakCallback weak_callback)
Handle< String > InternalizeUtf8String(Vector< const char > str)
Definition: factory.cc:218
void Iterate(v8::internal::ObjectVisitor *v)
Definition: api.cc:7553
V8_INLINE void Reset()
Definition: v8.h:5808
Handle< Code > NewCode(const CodeDesc &desc, Code::Flags flags, Handle< Object > self_reference, bool immovable=false, bool crankshafted=false, int prologue_offset=Code::kPrologueOffsetNotSet)
Definition: factory.cc:1291
int MaxSemiSpaceSize()
Definition: heap.h:596
void VisitPointers(Object **start, Object **end)
Definition: test-heap.cc:3529
static const int kProtoTransitionPrototypeOffset
Definition: objects.h:6134
static Handle< Map > GetPrototypeTransition(Handle< Map > map, Handle< Object > prototype)
Definition: objects.cc:11416
bool IsDisposed()
Definition: test-heap.cc:3060
InstanceType instance_type()
Definition: objects-inl.h:4012
MUST_USE_RESULT MaybeObject * AllocateFixedArray(int length, PretenureFlag pretenure=NOT_TENURED)
Definition: heap.cc:5297
static FixedArray * cast(Object *obj)
MUST_USE_RESULT MaybeObject * InternalizeUtf8String(const char *str)
Definition: heap.h:1222
static const int kHeaderSize
Definition: objects.h:2757
void DisableInlineAllocation()
Definition: heap.cc:6538
MUST_USE_RESULT MaybeObject * NumberFromInt32(int32_t value, PretenureFlag pretenure=NOT_TENURED)
Definition: heap-inl.h:272
Object * get(int index)
Definition: objects-inl.h:2127
static Handle< Object > GetElement(Isolate *isolate, Handle< Object > object, uint32_t index)
Definition: objects-inl.h:1060
HeapObject * obj
void CreateFillerObjectAt(Address addr, int size)
Definition: heap.cc:4005
char * StrDup(const char *str)
Definition: allocation.cc:89
Address * allocation_limit_address()
Definition: spaces.h:2539
size_t length() const
Definition: test-heap.cc:3058
int bar
static Handle< Object > DeleteProperty(Handle< JSReceiver > object, Handle< Name > name, DeleteMode mode=NORMAL_DELETION)
Definition: objects.cc:5273
void DeleteArray(T *array)
Definition: allocation.h:91
T Min(T a, T b)
Definition: utils.h:234
Handle< Map > NewMap(InstanceType type, int instance_size, ElementsKind elements_kind=TERMINAL_FAST_ELEMENTS_KIND)
Definition: factory.cc:809
static const int kMaxValue
Definition: objects.h:1681
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
Definition: flags.cc:505
NewSpace * new_space()
Definition: heap.h:637
static Handle< Object > ToString(Isolate *isolate, Handle< Object > obj, bool *exc)
Definition: execution.cc:719
Handle< Object > NewNumberFromUint(uint32_t value, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:1014
Definition: v8.h:124
MUST_USE_RESULT MaybeObject * AllocateRaw(int size_in_bytes, AllocationSpace space, AllocationSpace retry_space)
Definition: heap-inl.h:217
Object * allocation_sites_list()
Definition: heap.h:1364
FixedArray * GetPrototypeTransitions()
Definition: objects-inl.h:4857
static JSObject * cast(Object *obj)
static bool Initialize()
Definition: api.cc:4967
Handle< JSArray > NewJSArray(ElementsKind elements_kind, int length, int capacity, ArrayStorageAllocationMode mode=INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:1437
MarkCompactCollector * mark_compact_collector()
Definition: heap.h:1769
int CountNativeContexts()
Definition: test-heap.cc:1370
Handle< T > CloseAndEscape(Handle< T > handle_value)
Definition: handles-inl.h:146
static v8::Isolate * isolate()
Definition: cctest.h:96
static bool IdleNotification(int hint=1000)
Definition: api.cc:5091
V8_INLINE void Clear()
Definition: v8.h:253
static bool HasLocalProperty(Handle< JSReceiver >, Handle< Name > name)
Definition: objects-inl.h:6301
const int MB
Definition: globals.h:246
static JSFunction * cast(Object *obj)