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