Line data Source code
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 "src/v8.h"
29 : #include "test/cctest/cctest.h"
30 :
31 : #include "src/accessors.h"
32 : #include "src/api-inl.h"
33 : #include "src/heap/heap-inl.h"
34 : #include "src/objects-inl.h"
35 : #include "src/objects/api-callbacks.h"
36 : #include "src/property.h"
37 : #include "test/cctest/heap/heap-tester.h"
38 : #include "test/cctest/heap/heap-utils.h"
39 :
40 : namespace v8 {
41 : namespace internal {
42 : namespace heap {
43 :
44 10 : Handle<Object> HeapTester::TestAllocateAfterFailures() {
45 : // Similar to what the factory's retrying logic does in the last-resort case,
46 : // we wrap the allocator function in an AlwaysAllocateScope. Test that
47 : // all allocations succeed immediately without any retry.
48 10 : CcTest::CollectAllAvailableGarbage();
49 : AlwaysAllocateScope scope(CcTest::i_isolate());
50 10 : Heap* heap = CcTest::heap();
51 : int size = FixedArray::SizeFor(100);
52 : // Young generation.
53 : HeapObject obj =
54 20 : heap->AllocateRaw(size, AllocationType::kYoung).ToObjectChecked();
55 : // In order to pass heap verification on Isolate teardown, mark the
56 : // allocated area as a filler.
57 10 : heap->CreateFillerObjectAt(obj->address(), size, ClearRecordedSlots::kNo);
58 :
59 : // Old generation.
60 10 : heap::SimulateFullSpace(heap->old_space());
61 20 : obj = heap->AllocateRaw(size, AllocationType::kOld).ToObjectChecked();
62 10 : heap->CreateFillerObjectAt(obj->address(), size, ClearRecordedSlots::kNo);
63 :
64 : // Large object space.
65 : static const size_t kLargeObjectSpaceFillerLength =
66 : 3 * (Page::kPageSize / 10);
67 : static const size_t kLargeObjectSpaceFillerSize =
68 : FixedArray::SizeFor(kLargeObjectSpaceFillerLength);
69 10 : CHECK_GT(kLargeObjectSpaceFillerSize,
70 : static_cast<size_t>(heap->old_space()->AreaSize()));
71 140 : while (heap->OldGenerationSpaceAvailable() > kLargeObjectSpaceFillerSize) {
72 280 : obj = heap->AllocateRaw(kLargeObjectSpaceFillerSize, AllocationType::kOld)
73 : .ToObjectChecked();
74 140 : heap->CreateFillerObjectAt(obj->address(), size, ClearRecordedSlots::kNo);
75 : }
76 20 : obj = heap->AllocateRaw(kLargeObjectSpaceFillerSize, AllocationType::kOld)
77 : .ToObjectChecked();
78 10 : heap->CreateFillerObjectAt(obj->address(), size, ClearRecordedSlots::kNo);
79 :
80 : // Map space.
81 10 : heap::SimulateFullSpace(heap->map_space());
82 20 : obj = heap->AllocateRaw(Map::kSize, AllocationType::kMap).ToObjectChecked();
83 : heap->CreateFillerObjectAt(obj->address(), Map::kSize,
84 10 : ClearRecordedSlots::kNo);
85 :
86 : // Code space.
87 10 : heap::SimulateFullSpace(heap->code_space());
88 10 : size = CcTest::i_isolate()->builtins()->builtin(Builtins::kIllegal)->Size();
89 20 : obj = heap->AllocateRaw(size, AllocationType::kCode).ToObjectChecked();
90 10 : heap->CreateFillerObjectAt(obj->address(), size, ClearRecordedSlots::kNo);
91 20 : return CcTest::i_isolate()->factory()->true_value();
92 : }
93 :
94 :
95 26644 : HEAP_TEST(StressHandles) {
96 10 : v8::HandleScope scope(CcTest::isolate());
97 5 : v8::Local<v8::Context> env = v8::Context::New(CcTest::isolate());
98 5 : env->Enter();
99 5 : Handle<Object> o = TestAllocateAfterFailures();
100 5 : CHECK(o->IsTrue(CcTest::i_isolate()));
101 5 : env->Exit();
102 5 : }
103 :
104 :
105 5 : void TestGetter(
106 : v8::Local<v8::Name> name,
107 : const v8::PropertyCallbackInfo<v8::Value>& info) {
108 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
109 : HandleScope scope(isolate);
110 5 : info.GetReturnValue().Set(
111 : v8::Utils::ToLocal(HeapTester::TestAllocateAfterFailures()));
112 5 : }
113 :
114 0 : void TestSetter(v8::Local<v8::Name> name, v8::Local<v8::Value> value,
115 : const v8::PropertyCallbackInfo<v8::Boolean>& info) {
116 0 : UNREACHABLE();
117 : }
118 :
119 :
120 5 : Handle<AccessorInfo> TestAccessorInfo(
121 : Isolate* isolate, PropertyAttributes attributes) {
122 5 : Handle<String> name = isolate->factory()->NewStringFromStaticChars("get");
123 5 : return Accessors::MakeAccessor(isolate, name, &TestGetter, &TestSetter);
124 : }
125 :
126 :
127 26644 : TEST(StressJS) {
128 : Isolate* isolate = CcTest::i_isolate();
129 : Factory* factory = isolate->factory();
130 10 : v8::HandleScope scope(CcTest::isolate());
131 5 : v8::Local<v8::Context> env = v8::Context::New(CcTest::isolate());
132 5 : env->Enter();
133 :
134 : NewFunctionArgs args = NewFunctionArgs::ForBuiltin(
135 : factory->function_string(), isolate->sloppy_function_map(),
136 10 : Builtins::kEmptyFunction);
137 5 : Handle<JSFunction> function = factory->NewFunction(args);
138 5 : CHECK(!function->shared()->construct_as_builtin());
139 :
140 : // Force the creation of an initial map.
141 5 : factory->NewJSObject(function);
142 :
143 : // Patch the map to have an accessor for "get".
144 : Handle<Map> map(function->initial_map(), isolate);
145 : Handle<DescriptorArray> instance_descriptors(map->instance_descriptors(),
146 : isolate);
147 5 : CHECK_EQ(0, instance_descriptors->number_of_descriptors());
148 :
149 : PropertyAttributes attrs = NONE;
150 5 : Handle<AccessorInfo> foreign = TestAccessorInfo(isolate, attrs);
151 5 : Map::EnsureDescriptorSlack(isolate, map, 1);
152 :
153 : Descriptor d = Descriptor::AccessorConstant(
154 5 : Handle<Name>(Name::cast(foreign->name()), isolate), foreign, attrs);
155 5 : map->AppendDescriptor(isolate, &d);
156 :
157 : // Add the Foo constructor the global object.
158 20 : CHECK(env->Global()
159 : ->Set(env, v8::String::NewFromUtf8(CcTest::isolate(), "Foo",
160 : v8::NewStringType::kNormal)
161 : .ToLocalChecked(),
162 : v8::Utils::CallableToLocal(function))
163 : .FromJust());
164 : // Call the accessor through JavaScript.
165 : v8::Local<v8::Value> result =
166 5 : v8::Script::Compile(
167 5 : env, v8::String::NewFromUtf8(CcTest::isolate(), "(new Foo).get",
168 5 : v8::NewStringType::kNormal)
169 : .ToLocalChecked())
170 : .ToLocalChecked()
171 5 : ->Run(env)
172 : .ToLocalChecked();
173 5 : CHECK_EQ(true, result->BooleanValue(CcTest::isolate()));
174 5 : env->Exit();
175 5 : }
176 :
177 : } // namespace heap
178 : } // namespace internal
179 79917 : } // namespace v8
|