1 // Copyright 2011 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 <stdlib.h> 29 30 #include <vector> 31 32 #include "src/v8.h" 33 34 #include "src/base/platform/platform.h" 35 #include "src/collector.h" 36 #include "test/cctest/cctest.h" 37 38 using namespace v8::internal; 39 40 41 TEST(Utils1) { 42 CHECK_EQ(-1000000, FastD2I(-1000000.0)); 43 CHECK_EQ(-1, FastD2I(-1.0)); 44 CHECK_EQ(0, FastD2I(0.0)); 45 CHECK_EQ(1, FastD2I(1.0)); 46 CHECK_EQ(1000000, FastD2I(1000000.0)); 47 48 CHECK_EQ(-1000000, FastD2I(-1000000.123)); 49 CHECK_EQ(-1, FastD2I(-1.234)); 50 CHECK_EQ(0, FastD2I(0.345)); 51 CHECK_EQ(1, FastD2I(1.234)); 52 CHECK_EQ(1000000, FastD2I(1000000.123)); 53 // Check that >> is implemented as arithmetic shift right. 54 // If this is not true, then ArithmeticShiftRight() must be changed, 55 // There are also documented right shifts in assembler.cc of 56 // int8_t and intptr_t signed integers. 57 CHECK_EQ(-2, -8 >> 2); 58 CHECK_EQ(-2, static_cast<int8_t>(-8) >> 2); 59 CHECK_EQ(-2, static_cast<int>(static_cast<intptr_t>(-8) >> 2)); 60 61 CHECK_EQ(-1000000, FastD2IChecked(-1000000.0)); 62 CHECK_EQ(-1, FastD2IChecked(-1.0)); 63 CHECK_EQ(0, FastD2IChecked(0.0)); 64 CHECK_EQ(1, FastD2IChecked(1.0)); 65 CHECK_EQ(1000000, FastD2IChecked(1000000.0)); 66 67 CHECK_EQ(-1000000, FastD2IChecked(-1000000.123)); 68 CHECK_EQ(-1, FastD2IChecked(-1.234)); 69 CHECK_EQ(0, FastD2IChecked(0.345)); 70 CHECK_EQ(1, FastD2IChecked(1.234)); 71 CHECK_EQ(1000000, FastD2IChecked(1000000.123)); 72 73 CHECK_EQ(INT_MAX, FastD2IChecked(1.0e100)); 74 CHECK_EQ(INT_MIN, FastD2IChecked(-1.0e100)); 75 CHECK_EQ(INT_MIN, FastD2IChecked(std::numeric_limits<double>::quiet_NaN())); 76 } 77 78 79 TEST(BitSetComputer) { 80 typedef BitSetComputer<bool, 1, kSmiValueSize, uint32_t> BoolComputer; 81 CHECK_EQ(0, BoolComputer::word_count(0)); 82 CHECK_EQ(1, BoolComputer::word_count(8)); 83 CHECK_EQ(2, BoolComputer::word_count(50)); 84 CHECK_EQ(0, BoolComputer::index(0, 8)); 85 CHECK_EQ(100, BoolComputer::index(100, 8)); 86 CHECK_EQ(1, BoolComputer::index(0, 40)); 87 uint32_t data = 0; 88 data = BoolComputer::encode(data, 1, true); 89 data = BoolComputer::encode(data, 4, true); 90 CHECK_EQ(true, BoolComputer::decode(data, 1)); 91 CHECK_EQ(true, BoolComputer::decode(data, 4)); 92 CHECK_EQ(false, BoolComputer::decode(data, 0)); 93 CHECK_EQ(false, BoolComputer::decode(data, 2)); 94 CHECK_EQ(false, BoolComputer::decode(data, 3)); 95 96 // Lets store 2 bits per item with 3000 items and verify the values are 97 // correct. 98 typedef BitSetComputer<unsigned char, 2, 8, unsigned char> TwoBits; 99 const int words = 750; 100 CHECK_EQ(words, TwoBits::word_count(3000)); 101 const int offset = 10; 102 Vector<unsigned char> buffer = Vector<unsigned char>::New(offset + words); 103 memset(buffer.start(), 0, sizeof(unsigned char) * buffer.length()); 104 for (int i = 0; i < words; i++) { 105 const int index = TwoBits::index(offset, i); 106 unsigned char data = buffer[index]; 107 data = TwoBits::encode(data, i, i % 4); 108 buffer[index] = data; 109 } 110 111 for (int i = 0; i < words; i++) { 112 const int index = TwoBits::index(offset, i); 113 unsigned char data = buffer[index]; 114 CHECK_EQ(i % 4, TwoBits::decode(data, i)); 115 } 116 buffer.Dispose(); 117 } 118 119 120 TEST(SNPrintF) { 121 // Make sure that strings that are truncated because of too small 122 // buffers are zero-terminated anyway. 123 const char* s = "the quick lazy .... oh forget it!"; 124 int length = StrLength(s); 125 for (int i = 1; i < length * 2; i++) { 126 static const char kMarker = static_cast<char>(42); 127 Vector<char> buffer = Vector<char>::New(i + 1); 128 buffer[i] = kMarker; 129 int n = SNPrintF(Vector<char>(buffer.start(), i), "%s", s); 130 CHECK(n <= i); 131 CHECK(n == length || n == -1); 132 CHECK_EQ(0, strncmp(buffer.start(), s, i - 1)); 133 CHECK_EQ(kMarker, buffer[i]); 134 if (i <= length) { 135 CHECK_EQ(i - 1, StrLength(buffer.start())); 136 } else { 137 CHECK_EQ(length, StrLength(buffer.start())); 138 } 139 buffer.Dispose(); 140 } 141 } 142 143 144 static const int kAreaSize = 512; 145 146 147 void TestMemMove(byte* area1, 148 byte* area2, 149 int src_offset, 150 int dest_offset, 151 int length) { 152 for (int i = 0; i < kAreaSize; i++) { 153 area1[i] = i & 0xFF; 154 area2[i] = i & 0xFF; 155 } 156 MemMove(area1 + dest_offset, area1 + src_offset, length); 157 memmove(area2 + dest_offset, area2 + src_offset, length); 158 if (memcmp(area1, area2, kAreaSize) != 0) { 159 printf("MemMove(): src_offset: %d, dest_offset: %d, length: %d\n", 160 src_offset, dest_offset, length); 161 for (int i = 0; i < kAreaSize; i++) { 162 if (area1[i] == area2[i]) continue; 163 printf("diff at offset %d (%p): is %d, should be %d\n", i, 164 reinterpret_cast<void*>(area1 + i), area1[i], area2[i]); 165 } 166 CHECK(false); 167 } 168 } 169 170 171 TEST(MemMove) { 172 v8::V8::Initialize(); 173 byte* area1 = new byte[kAreaSize]; 174 byte* area2 = new byte[kAreaSize]; 175 176 static const int kMinOffset = 32; 177 static const int kMaxOffset = 64; 178 static const int kMaxLength = 128; 179 STATIC_ASSERT(kMaxOffset + kMaxLength < kAreaSize); 180 181 for (int src_offset = kMinOffset; src_offset <= kMaxOffset; src_offset++) { 182 for (int dst_offset = kMinOffset; dst_offset <= kMaxOffset; dst_offset++) { 183 for (int length = 0; length <= kMaxLength; length++) { 184 TestMemMove(area1, area2, src_offset, dst_offset, length); 185 } 186 } 187 } 188 delete[] area1; 189 delete[] area2; 190 } 191 192 193 TEST(Collector) { 194 Collector<int> collector(8); 195 const int kLoops = 5; 196 const int kSequentialSize = 1000; 197 const int kBlockSize = 7; 198 for (int loop = 0; loop < kLoops; loop++) { 199 Vector<int> block = collector.AddBlock(7, 0xbadcafe); 200 for (int i = 0; i < kSequentialSize; i++) { 201 collector.Add(i); 202 } 203 for (int i = 0; i < kBlockSize - 1; i++) { 204 block[i] = i * 7; 205 } 206 } 207 Vector<int> result = collector.ToVector(); 208 CHECK_EQ(kLoops * (kBlockSize + kSequentialSize), result.length()); 209 for (int i = 0; i < kLoops; i++) { 210 int offset = i * (kSequentialSize + kBlockSize); 211 for (int j = 0; j < kBlockSize - 1; j++) { 212 CHECK_EQ(j * 7, result[offset + j]); 213 } 214 CHECK_EQ(0xbadcafe, result[offset + kBlockSize - 1]); 215 for (int j = 0; j < kSequentialSize; j++) { 216 CHECK_EQ(j, result[offset + kBlockSize + j]); 217 } 218 } 219 result.Dispose(); 220 } 221 222 223 TEST(SequenceCollector) { 224 SequenceCollector<int> collector(8); 225 const int kLoops = 5000; 226 const int kMaxSequenceSize = 13; 227 int total_length = 0; 228 for (int loop = 0; loop < kLoops; loop++) { 229 int seq_length = loop % kMaxSequenceSize; 230 collector.StartSequence(); 231 for (int j = 0; j < seq_length; j++) { 232 collector.Add(j); 233 } 234 Vector<int> sequence = collector.EndSequence(); 235 for (int j = 0; j < seq_length; j++) { 236 CHECK_EQ(j, sequence[j]); 237 } 238 total_length += seq_length; 239 } 240 Vector<int> result = collector.ToVector(); 241 CHECK_EQ(total_length, result.length()); 242 int offset = 0; 243 for (int loop = 0; loop < kLoops; loop++) { 244 int seq_length = loop % kMaxSequenceSize; 245 for (int j = 0; j < seq_length; j++) { 246 CHECK_EQ(j, result[offset]); 247 offset++; 248 } 249 } 250 result.Dispose(); 251 } 252 253 254 TEST(SequenceCollectorRegression) { 255 SequenceCollector<char> collector(16); 256 collector.StartSequence(); 257 collector.Add('0'); 258 collector.AddBlock( 259 i::Vector<const char>("12345678901234567890123456789012", 32)); 260 i::Vector<char> seq = collector.EndSequence(); 261 CHECK_EQ(0, strncmp("0123456789012345678901234567890123", 262 seq.start(), seq.length())); 263 } 264 265 266 TEST(CPlusPlus11Features) { 267 struct S { 268 bool x; 269 struct T { 270 double y; 271 int z[3]; 272 } t; 273 }; 274 S s{true, {3.1415, {1, 2, 3}}}; 275 CHECK_EQ(2, s.t.z[1]); 276 277 // TODO(svenpanne) Remove the old-skool code when we ship the new C++ headers. 278 #if 0 279 std::vector<int> vec{11, 22, 33, 44}; 280 #else 281 std::vector<int> vec; 282 vec.push_back(11); 283 vec.push_back(22); 284 vec.push_back(33); 285 vec.push_back(44); 286 #endif 287 vec.push_back(55); 288 vec.push_back(66); 289 for (auto& i : vec) { 290 ++i; 291 } 292 int j = 12; 293 for (auto i : vec) { 294 CHECK_EQ(j, i); 295 j += 11; 296 } 297 } 298