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