1// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/v8.h"
6
7#include "test/cctest/compiler/function-tester.h"
8
9using namespace v8::internal;
10using namespace v8::internal::compiler;
11
12template <typename U>
13static void TypedArrayLoadHelper(const char* array_type) {
14  static const uint32_t kValues[] = {
15      0x00000000, 0x00000001, 0x00000023, 0x00000042, 0x12345678, 0x87654321,
16      0x0000003f, 0x0000007f, 0x00003fff, 0x00007fff, 0x3fffffff, 0x7fffffff,
17      0x000000ff, 0x00000080, 0x0000ffff, 0x00008000, 0xffffffff, 0x80000000};
18  EmbeddedVector<char, 1024> values_buffer;
19  StringBuilder values_builder(values_buffer.start(), values_buffer.length());
20  for (size_t i = 0; i < arraysize(kValues); ++i) {
21    values_builder.AddFormatted("a[%d] = 0x%08x;", i, kValues[i]);
22  }
23
24  // Note that below source creates two different typed arrays with distinct
25  // elements kind to get coverage for both access patterns:
26  // - IsFixedTypedArrayElementsKind(x)
27  // - IsExternalArrayElementsKind(y)
28  const char* source =
29      "(function(a) {"
30      "  var x = (a = new %sArray(%d)); %s;"
31      "  var y = (a = new %sArray(%d)); %s; %%TypedArrayGetBuffer(y);"
32      "  if (!%%HasFixed%sElements(x)) %%AbortJS('x');"
33      "  if (!%%HasExternal%sElements(y)) %%AbortJS('y');"
34      "  function f(a,b) {"
35      "    a = a | 0; b = b | 0;"
36      "    return x[a] + y[b];"
37      "  }"
38      "  return f;"
39      "})()";
40  EmbeddedVector<char, 1024> source_buffer;
41  SNPrintF(source_buffer, source, array_type, arraysize(kValues),
42           values_buffer.start(), array_type, arraysize(kValues),
43           values_buffer.start(), array_type, array_type);
44
45  FunctionTester T(
46      source_buffer.start(),
47      CompilationInfo::kContextSpecializing | CompilationInfo::kTypingEnabled);
48  for (size_t i = 0; i < arraysize(kValues); ++i) {
49    for (size_t j = 0; j < arraysize(kValues); ++j) {
50      volatile U value_a = static_cast<U>(kValues[i]);
51      volatile U value_b = static_cast<U>(kValues[j]);
52      double expected =
53          static_cast<double>(value_a) + static_cast<double>(value_b);
54      T.CheckCall(T.Val(expected), T.Val(static_cast<double>(i)),
55                  T.Val(static_cast<double>(j)));
56    }
57  }
58}
59
60
61TEST(TypedArrayLoad) {
62  FLAG_typed_array_max_size_in_heap = 256;
63  TypedArrayLoadHelper<int8_t>("Int8");
64  TypedArrayLoadHelper<uint8_t>("Uint8");
65  TypedArrayLoadHelper<int16_t>("Int16");
66  TypedArrayLoadHelper<uint16_t>("Uint16");
67  TypedArrayLoadHelper<int32_t>("Int32");
68  TypedArrayLoadHelper<uint32_t>("Uint32");
69  TypedArrayLoadHelper<float>("Float32");
70  TypedArrayLoadHelper<double>("Float64");
71  // TODO(mstarzinger): Add tests for ClampedUint8.
72}
73
74
75template <typename U>
76static void TypedArrayStoreHelper(const char* array_type) {
77  static const uint32_t kValues[] = {
78      0x00000000, 0x00000001, 0x00000023, 0x00000042, 0x12345678, 0x87654321,
79      0x0000003f, 0x0000007f, 0x00003fff, 0x00007fff, 0x3fffffff, 0x7fffffff,
80      0x000000ff, 0x00000080, 0x0000ffff, 0x00008000, 0xffffffff, 0x80000000};
81  EmbeddedVector<char, 1024> values_buffer;
82  StringBuilder values_builder(values_buffer.start(), values_buffer.length());
83  for (size_t i = 0; i < arraysize(kValues); ++i) {
84    values_builder.AddFormatted("a[%d] = 0x%08x;", i, kValues[i]);
85  }
86
87  // Note that below source creates two different typed arrays with distinct
88  // elements kind to get coverage for both access patterns:
89  // - IsFixedTypedArrayElementsKind(x)
90  // - IsExternalArrayElementsKind(y)
91  const char* source =
92      "(function(a) {"
93      "  var x = (a = new %sArray(%d)); %s;"
94      "  var y = (a = new %sArray(%d)); %s; %%TypedArrayGetBuffer(y);"
95      "  if (!%%HasFixed%sElements(x)) %%AbortJS('x');"
96      "  if (!%%HasExternal%sElements(y)) %%AbortJS('y');"
97      "  function f(a,b) {"
98      "    a = a | 0; b = b | 0;"
99      "    var t = x[a];"
100      "    x[a] = y[b];"
101      "    y[b] = t;"
102      "    t = y[b];"
103      "    y[b] = x[a];"
104      "    x[a] = t;"
105      "    return x[a] + y[b];"
106      "  }"
107      "  return f;"
108      "})()";
109  EmbeddedVector<char, 2048> source_buffer;
110  SNPrintF(source_buffer, source, array_type, arraysize(kValues),
111           values_buffer.start(), array_type, arraysize(kValues),
112           values_buffer.start(), array_type, array_type);
113
114  FunctionTester T(
115      source_buffer.start(),
116      CompilationInfo::kContextSpecializing | CompilationInfo::kTypingEnabled);
117  for (size_t i = 0; i < arraysize(kValues); ++i) {
118    for (size_t j = 0; j < arraysize(kValues); ++j) {
119      volatile U value_a = static_cast<U>(kValues[i]);
120      volatile U value_b = static_cast<U>(kValues[j]);
121      double expected =
122          static_cast<double>(value_a) + static_cast<double>(value_b);
123      T.CheckCall(T.Val(expected), T.Val(static_cast<double>(i)),
124                  T.Val(static_cast<double>(j)));
125    }
126  }
127}
128
129
130TEST(TypedArrayStore) {
131  FLAG_typed_array_max_size_in_heap = 256;
132  TypedArrayStoreHelper<int8_t>("Int8");
133  TypedArrayStoreHelper<uint8_t>("Uint8");
134  TypedArrayStoreHelper<int16_t>("Int16");
135  TypedArrayStoreHelper<uint16_t>("Uint16");
136  TypedArrayStoreHelper<int32_t>("Int32");
137  TypedArrayStoreHelper<uint32_t>("Uint32");
138  TypedArrayStoreHelper<float>("Float32");
139  TypedArrayStoreHelper<double>("Float64");
140  // TODO(mstarzinger): Add tests for ClampedUint8.
141}
142