test-weaktypedarrays.cc 12 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <stdlib.h>

#include "v8.h"
#include "api.h"
#include "heap.h"
#include "objects.h"

#include "cctest.h"

using namespace v8::internal;

static Isolate* GetIsolateFrom(LocalContext* context) {
  return reinterpret_cast<Isolate*>((*context)->GetIsolate());
}


static int CountArrayBuffersInWeakList(Heap* heap) {
  int count = 0;
  for (Object* o = heap->array_buffers_list();
47
       !o->IsUndefined();
48 49 50 51 52 53 54 55 56
       o = JSArrayBuffer::cast(o)->weak_next()) {
    count++;
  }
  return count;
}


static bool HasArrayBufferInWeakList(Heap* heap, JSArrayBuffer* ab) {
  for (Object* o = heap->array_buffers_list();
57
       !o->IsUndefined();
58 59 60 61 62 63 64
       o = JSArrayBuffer::cast(o)->weak_next()) {
    if (ab == o) return true;
  }
  return false;
}


65
static int CountViews(JSArrayBuffer* array_buffer) {
66
  int count = 0;
67
  for (Object* o = array_buffer->weak_first_view();
68
       !o->IsUndefined();
69
       o = JSArrayBufferView::cast(o)->weak_next()) {
70 71 72 73 74 75
    count++;
  }

  return count;
}

76
static bool HasViewInWeakList(JSArrayBuffer* array_buffer,
dslomov@chromium.org's avatar
dslomov@chromium.org committed
77
                              JSArrayBufferView* ta) {
78
  for (Object* o = array_buffer->weak_first_view();
79
       !o->IsUndefined();
80
       o = JSArrayBufferView::cast(o)->weak_next()) {
81 82 83 84 85 86 87 88 89 90 91
    if (ta == o) return true;
  }
  return false;
}


TEST(WeakArrayBuffersFromApi) {
  v8::V8::Initialize();
  LocalContext context;
  Isolate* isolate = GetIsolateFrom(&context);

92
  int start = CountArrayBuffersInWeakList(isolate->heap());
93 94
  {
    v8::HandleScope s1(context->GetIsolate());
95 96
    v8::Handle<v8::ArrayBuffer> ab1 =
        v8::ArrayBuffer::New(context->GetIsolate(), 256);
97 98
    {
      v8::HandleScope s2(context->GetIsolate());
99 100
      v8::Handle<v8::ArrayBuffer> ab2 =
          v8::ArrayBuffer::New(context->GetIsolate(), 128);
101 102 103

      Handle<JSArrayBuffer> iab1 = v8::Utils::OpenHandle(*ab1);
      Handle<JSArrayBuffer> iab2 = v8::Utils::OpenHandle(*ab2);
104
      CHECK_EQ(2, CountArrayBuffersInWeakList(isolate->heap()) - start);
105 106 107
      CHECK(HasArrayBufferInWeakList(isolate->heap(), *iab1));
      CHECK(HasArrayBufferInWeakList(isolate->heap(), *iab2));
    }
108
    isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
109
    CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start);
110 111 112 113 114 115 116 117
    {
      HandleScope scope2(isolate);
      Handle<JSArrayBuffer> iab1 = v8::Utils::OpenHandle(*ab1);

      CHECK(HasArrayBufferInWeakList(isolate->heap(), *iab1));
    }
  }

118
  isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
119
  CHECK_EQ(start, CountArrayBuffersInWeakList(isolate->heap()));
120 121 122 123 124 125 126
}


TEST(WeakArrayBuffersFromScript) {
  v8::V8::Initialize();
  LocalContext context;
  Isolate* isolate = GetIsolateFrom(&context);
127
  int start = CountArrayBuffersInWeakList(isolate->heap());
128 129 130 131

  for (int i = 1; i <= 3; i++) {
    // Create 3 array buffers, make i-th of them garbage,
    // validate correct state of array buffer weak list.
132
    CHECK_EQ(start, CountArrayBuffersInWeakList(isolate->heap()));
133 134 135 136 137 138 139 140
    {
      v8::HandleScope scope(context->GetIsolate());

      {
        v8::HandleScope s1(context->GetIsolate());
        CompileRun("var ab1 = new ArrayBuffer(256);"
                   "var ab2 = new ArrayBuffer(256);"
                   "var ab3 = new ArrayBuffer(256);");
141 142 143 144 145 146
        v8::Handle<v8::ArrayBuffer> ab1 =
            v8::Handle<v8::ArrayBuffer>::Cast(CompileRun("ab1"));
        v8::Handle<v8::ArrayBuffer> ab2 =
            v8::Handle<v8::ArrayBuffer>::Cast(CompileRun("ab2"));
        v8::Handle<v8::ArrayBuffer> ab3 =
            v8::Handle<v8::ArrayBuffer>::Cast(CompileRun("ab3"));
147

148
        CHECK_EQ(3, CountArrayBuffersInWeakList(isolate->heap()) - start);
149 150 151 152 153 154 155 156 157 158 159
        CHECK(HasArrayBufferInWeakList(isolate->heap(),
              *v8::Utils::OpenHandle(*ab1)));
        CHECK(HasArrayBufferInWeakList(isolate->heap(),
              *v8::Utils::OpenHandle(*ab2)));
        CHECK(HasArrayBufferInWeakList(isolate->heap(),
              *v8::Utils::OpenHandle(*ab3)));
      }

      i::ScopedVector<char> source(1024);
      i::OS::SNPrintF(source, "ab%d = null;", i);
      CompileRun(source.start());
160
      isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
161

162
      CHECK_EQ(2, CountArrayBuffersInWeakList(isolate->heap()) - start);
163 164 165 166 167 168

      {
        v8::HandleScope s2(context->GetIsolate());
        for (int j = 1; j <= 3; j++) {
          if (j == i) continue;
          i::OS::SNPrintF(source, "ab%d", j);
169 170
          v8::Handle<v8::ArrayBuffer> ab =
              v8::Handle<v8::ArrayBuffer>::Cast(CompileRun(source.start()));
171 172 173 174 175 176 177 178
          CHECK(HasArrayBufferInWeakList(isolate->heap(),
                *v8::Utils::OpenHandle(*ab)));
          }
      }

      CompileRun("ab1 = null; ab2 = null; ab3 = null;");
    }

179
    isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
180
    CHECK_EQ(start, CountArrayBuffersInWeakList(isolate->heap()));
181 182 183
  }
}

dslomov@chromium.org's avatar
dslomov@chromium.org committed
184 185
template <typename View>
void TestViewFromApi() {
186 187 188 189 190
  v8::V8::Initialize();
  LocalContext context;
  Isolate* isolate = GetIsolateFrom(&context);

  v8::HandleScope s1(context->GetIsolate());
191 192
  v8::Handle<v8::ArrayBuffer> ab =
      v8::ArrayBuffer::New(context->GetIsolate(), 2048);
193 194 195
  Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab);
  {
    v8::HandleScope s2(context->GetIsolate());
dslomov@chromium.org's avatar
dslomov@chromium.org committed
196
    v8::Handle<View> ta1 = View::New(ab, 0, 256);
197 198
    {
      v8::HandleScope s3(context->GetIsolate());
dslomov@chromium.org's avatar
dslomov@chromium.org committed
199
      v8::Handle<View> ta2 = View::New(ab, 0, 128);
200

dslomov@chromium.org's avatar
dslomov@chromium.org committed
201 202
      Handle<JSArrayBufferView> ita1 = v8::Utils::OpenHandle(*ta1);
      Handle<JSArrayBufferView> ita2 = v8::Utils::OpenHandle(*ta2);
203 204 205
      CHECK_EQ(2, CountViews(*iab));
      CHECK(HasViewInWeakList(*iab, *ita1));
      CHECK(HasViewInWeakList(*iab, *ita2));
206
    }
207
    isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
208
    CHECK_EQ(1, CountViews(*iab));
dslomov@chromium.org's avatar
dslomov@chromium.org committed
209
    Handle<JSArrayBufferView> ita1 = v8::Utils::OpenHandle(*ta1);
210
    CHECK(HasViewInWeakList(*iab, *ita1));
211
  }
212
  isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
213

214
  CHECK_EQ(0, CountViews(*iab));
215 216 217 218
}


TEST(Uint8ArrayFromApi) {
dslomov@chromium.org's avatar
dslomov@chromium.org committed
219
  TestViewFromApi<v8::Uint8Array>();
220 221 222 223
}


TEST(Int8ArrayFromApi) {
dslomov@chromium.org's avatar
dslomov@chromium.org committed
224
  TestViewFromApi<v8::Int8Array>();
225 226 227 228
}


TEST(Uint16ArrayFromApi) {
dslomov@chromium.org's avatar
dslomov@chromium.org committed
229
  TestViewFromApi<v8::Uint16Array>();
230 231 232 233
}


TEST(Int16ArrayFromApi) {
dslomov@chromium.org's avatar
dslomov@chromium.org committed
234
  TestViewFromApi<v8::Int16Array>();
235 236 237 238
}


TEST(Uint32ArrayFromApi) {
dslomov@chromium.org's avatar
dslomov@chromium.org committed
239
  TestViewFromApi<v8::Uint32Array>();
240 241 242 243
}


TEST(Int32ArrayFromApi) {
dslomov@chromium.org's avatar
dslomov@chromium.org committed
244
  TestViewFromApi<v8::Int32Array>();
245 246 247 248
}


TEST(Float32ArrayFromApi) {
dslomov@chromium.org's avatar
dslomov@chromium.org committed
249
  TestViewFromApi<v8::Float32Array>();
250 251 252 253
}


TEST(Float64ArrayFromApi) {
dslomov@chromium.org's avatar
dslomov@chromium.org committed
254
  TestViewFromApi<v8::Float64Array>();
255 256 257 258
}


TEST(Uint8ClampedArrayFromApi) {
dslomov@chromium.org's avatar
dslomov@chromium.org committed
259 260 261 262 263 264
  TestViewFromApi<v8::Uint8ClampedArray>();
}


TEST(DataViewFromApi) {
  TestViewFromApi<v8::DataView>();
265 266 267 268 269 270 271 272
}

template <typename TypedArray>
static void TestTypedArrayFromScript(const char* constructor) {
  v8::V8::Initialize();
  LocalContext context;
  Isolate* isolate = GetIsolateFrom(&context);
  v8::HandleScope scope(context->GetIsolate());
273
  int start = CountArrayBuffersInWeakList(isolate->heap());
274 275 276 277 278 279 280
  CompileRun("var ab = new ArrayBuffer(2048);");
  for (int i = 1; i <= 3; i++) {
    // Create 3 typed arrays, make i-th of them garbage,
    // validate correct state of typed array weak list.
    v8::HandleScope s0(context->GetIsolate());
    i::ScopedVector<char> source(2048);

281
    CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start);
282 283 284 285 286 287 288 289 290 291

    {
      v8::HandleScope s1(context->GetIsolate());
      i::OS::SNPrintF(source,
                  "var ta1 = new %s(ab);"
                  "var ta2 = new %s(ab);"
                  "var ta3 = new %s(ab)",
                  constructor, constructor, constructor);

      CompileRun(source.start());
292 293 294 295 296 297 298 299
      v8::Handle<v8::ArrayBuffer> ab =
          v8::Handle<v8::ArrayBuffer>::Cast(CompileRun("ab"));
      v8::Handle<TypedArray> ta1 =
          v8::Handle<TypedArray>::Cast(CompileRun("ta1"));
      v8::Handle<TypedArray> ta2 =
          v8::Handle<TypedArray>::Cast(CompileRun("ta2"));
      v8::Handle<TypedArray> ta3 =
          v8::Handle<TypedArray>::Cast(CompileRun("ta3"));
300
      CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start);
301
      Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab);
302 303 304 305
      CHECK_EQ(3, CountViews(*iab));
      CHECK(HasViewInWeakList(*iab, *v8::Utils::OpenHandle(*ta1)));
      CHECK(HasViewInWeakList(*iab, *v8::Utils::OpenHandle(*ta2)));
      CHECK(HasViewInWeakList(*iab, *v8::Utils::OpenHandle(*ta3)));
306 307 308 309
    }

    i::OS::SNPrintF(source, "ta%d = null;", i);
    CompileRun(source.start());
310
    isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
311

312
    CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start);
313 314 315

    {
      v8::HandleScope s2(context->GetIsolate());
316 317
      v8::Handle<v8::ArrayBuffer> ab =
          v8::Handle<v8::ArrayBuffer>::Cast(CompileRun("ab"));
318
      Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab);
319
      CHECK_EQ(2, CountViews(*iab));
320 321 322
      for (int j = 1; j <= 3; j++) {
        if (j == i) continue;
        i::OS::SNPrintF(source, "ta%d", j);
323 324
        v8::Handle<TypedArray> ta =
            v8::Handle<TypedArray>::Cast(CompileRun(source.start()));
325
        CHECK(HasViewInWeakList(*iab, *v8::Utils::OpenHandle(*ta)));
326 327 328 329
      }
    }

    CompileRun("ta1 = null; ta2 = null; ta3 = null;");
330
    isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
331

332
    CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start);
333 334 335

    {
      v8::HandleScope s3(context->GetIsolate());
336 337
      v8::Handle<v8::ArrayBuffer> ab =
          v8::Handle<v8::ArrayBuffer>::Cast(CompileRun("ab"));
338
      Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab);
339
      CHECK_EQ(0, CountViews(*iab));
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
    }
  }
}


TEST(Uint8ArrayFromScript) {
  TestTypedArrayFromScript<v8::Uint8Array>("Uint8Array");
}


TEST(Int8ArrayFromScript) {
  TestTypedArrayFromScript<v8::Int8Array>("Int8Array");
}


TEST(Uint16ArrayFromScript) {
  TestTypedArrayFromScript<v8::Uint16Array>("Uint16Array");
}


TEST(Int16ArrayFromScript) {
  TestTypedArrayFromScript<v8::Int16Array>("Int16Array");
}


TEST(Uint32ArrayFromScript) {
  TestTypedArrayFromScript<v8::Uint32Array>("Uint32Array");
}


TEST(Int32ArrayFromScript) {
  TestTypedArrayFromScript<v8::Int32Array>("Int32Array");
}


TEST(Float32ArrayFromScript) {
  TestTypedArrayFromScript<v8::Float32Array>("Float32Array");
}


TEST(Float64ArrayFromScript) {
  TestTypedArrayFromScript<v8::Float64Array>("Float64Array");
}


TEST(Uint8ClampedArrayFromScript) {
  TestTypedArrayFromScript<v8::Uint8ClampedArray>("Uint8ClampedArray");
}

389 390

TEST(DataViewFromScript) {
dslomov@chromium.org's avatar
dslomov@chromium.org committed
391
  TestTypedArrayFromScript<v8::DataView>("DataView");
392
}