OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 | 2 |
3 #include <stdlib.h> | 3 #include <stdlib.h> |
4 | 4 |
5 #include "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #include "execution.h" | 7 #include "execution.h" |
8 #include "factory.h" | 8 #include "factory.h" |
9 #include "macro-assembler.h" | 9 #include "macro-assembler.h" |
10 #include "global-handles.h" | 10 #include "global-handles.h" |
(...skipping 850 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
861 Handle<JSObject> runaway; | 861 Handle<JSObject> runaway; |
862 | 862 |
863 { | 863 { |
864 v8::HandleScope nested; | 864 v8::HandleScope nested; |
865 Handle<JSObject> empty; | 865 Handle<JSObject> empty; |
866 runaway = empty.EscapeFrom(&nested); | 866 runaway = empty.EscapeFrom(&nested); |
867 } | 867 } |
868 | 868 |
869 CHECK(runaway.is_null()); | 869 CHECK(runaway.is_null()); |
870 } | 870 } |
| 871 |
| 872 |
| 873 static int LenFromSize(int size) { |
| 874 return (size - FixedArray::kHeaderSize) / kPointerSize; |
| 875 } |
| 876 |
| 877 |
| 878 TEST(Regression39128) { |
| 879 // Test case for crbug.com/39128. |
| 880 InitializeVM(); |
| 881 |
| 882 // Increase the chance of 'bump-the-pointer' allocation in old space. |
| 883 bool force_compaction = true; |
| 884 Heap::CollectAllGarbage(force_compaction); |
| 885 |
| 886 v8::HandleScope scope; |
| 887 |
| 888 // The plan: create JSObject which references objects in new space. |
| 889 // Then clone this object (forcing it to go into old space) and check |
| 890 // that only bits pertaining to the object are updated in remembered set. |
| 891 |
| 892 // Step 1: prepare a map for the object. We add 1 inobject property to it. |
| 893 Handle<JSFunction> object_ctor(Top::global_context()->object_function()); |
| 894 CHECK(object_ctor->has_initial_map()); |
| 895 Handle<Map> object_map(object_ctor->initial_map()); |
| 896 // Create a map with single inobject property. |
| 897 Handle<Map> my_map = Factory::CopyMap(object_map, 1); |
| 898 int n_properties = my_map->inobject_properties(); |
| 899 CHECK_GT(n_properties, 0); |
| 900 |
| 901 int object_size = my_map->instance_size(); |
| 902 |
| 903 // Step 2: allocate a lot of objects so to almost fill new space: we need |
| 904 // just enough room to allocate JSObject and thus fill the newspace. |
| 905 |
| 906 int allocation_amount = Min(FixedArray::kMaxSize, |
| 907 Heap::MaxObjectSizeInNewSpace()); |
| 908 int allocation_len = LenFromSize(allocation_amount); |
| 909 NewSpace* new_space = Heap::new_space(); |
| 910 Address* top_addr = new_space->allocation_top_address(); |
| 911 Address* limit_addr = new_space->allocation_limit_address(); |
| 912 while ((*limit_addr - *top_addr) > allocation_amount) { |
| 913 CHECK(!Heap::always_allocate()); |
| 914 Object* array = Heap::AllocateFixedArray(allocation_len); |
| 915 CHECK(!array->IsFailure()); |
| 916 CHECK(new_space->Contains(array)); |
| 917 } |
| 918 |
| 919 // Step 3: now allocate fixed array and JSObject to fill the whole new space. |
| 920 int to_fill = *limit_addr - *top_addr - object_size; |
| 921 int fixed_array_len = LenFromSize(to_fill); |
| 922 CHECK(fixed_array_len < FixedArray::kMaxLength); |
| 923 |
| 924 CHECK(!Heap::always_allocate()); |
| 925 Object* array = Heap::AllocateFixedArray(fixed_array_len); |
| 926 CHECK(!array->IsFailure()); |
| 927 CHECK(new_space->Contains(array)); |
| 928 |
| 929 Object* object = Heap::AllocateJSObjectFromMap(*my_map); |
| 930 CHECK(!object->IsFailure()); |
| 931 CHECK(new_space->Contains(object)); |
| 932 JSObject* jsobject = JSObject::cast(object); |
| 933 CHECK_EQ(0, jsobject->elements()->length()); |
| 934 CHECK_EQ(0, jsobject->properties()->length()); |
| 935 // Create a reference to object in new space in jsobject. |
| 936 jsobject->FastPropertyAtPut(-1, array); |
| 937 |
| 938 CHECK_EQ(0L, (*limit_addr - *top_addr)); |
| 939 |
| 940 // Step 4: clone jsobject, but force always allocate first to create a clone |
| 941 // in old pointer space. |
| 942 Address old_pointer_space_top = Heap::old_pointer_space()->top(); |
| 943 AlwaysAllocateScope aa_scope; |
| 944 Object* clone_obj = Heap::CopyJSObject(jsobject); |
| 945 CHECK(!object->IsFailure()); |
| 946 JSObject* clone = JSObject::cast(clone_obj); |
| 947 if (clone->address() != old_pointer_space_top) { |
| 948 // Alas, got allocated from free list, we cannot do checks. |
| 949 return; |
| 950 } |
| 951 CHECK(Heap::old_pointer_space()->Contains(clone->address())); |
| 952 |
| 953 // Step 5: verify validity of remembered set. |
| 954 Address clone_addr = clone->address(); |
| 955 Page* page = Page::FromAddress(clone_addr); |
| 956 // Check that remembered set tracks a reference from inobject property 1. |
| 957 CHECK(page->IsRSetSet(clone_addr, object_size - kPointerSize)); |
| 958 // Probe several addresses after the object. |
| 959 for (int i = 0; i < 7; i++) { |
| 960 int offset = object_size + i * kPointerSize; |
| 961 if (clone_addr + offset >= page->ObjectAreaEnd()) { |
| 962 break; |
| 963 } |
| 964 CHECK(!page->IsRSetSet(clone_addr, offset)); |
| 965 } |
| 966 } |
OLD | NEW |