| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <limits> | 5 #include <limits> |
| 6 | 6 |
| 7 #include "src/compiler/access-builder.h" | 7 #include "src/compiler/access-builder.h" |
| 8 #include "src/compiler/change-lowering.h" | 8 #include "src/compiler/change-lowering.h" |
| 9 #include "src/compiler/control-builders.h" | 9 #include "src/compiler/control-builders.h" |
| 10 #include "src/compiler/graph-reducer.h" | 10 #include "src/compiler/graph-reducer.h" |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 Node* loaded = t.LoadField(load, t.PointerConstant(&input)); | 103 Node* loaded = t.LoadField(load, t.PointerConstant(&input)); |
| 104 NodeProperties::SetBounds(loaded, Bounds(Type::Number())); | 104 NodeProperties::SetBounds(loaded, Bounds(Type::Number())); |
| 105 Node* convert = t.NumberToInt32(loaded); | 105 Node* convert = t.NumberToInt32(loaded); |
| 106 FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Signed32(), | 106 FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Signed32(), |
| 107 kMachInt32}; | 107 kMachInt32}; |
| 108 t.StoreField(store, t.PointerConstant(&result), convert); | 108 t.StoreField(store, t.PointerConstant(&result), convert); |
| 109 t.Return(t.jsgraph.TrueConstant()); | 109 t.Return(t.jsgraph.TrueConstant()); |
| 110 t.LowerAllNodes(); | 110 t.LowerAllNodes(); |
| 111 t.GenerateCode(); | 111 t.GenerateCode(); |
| 112 | 112 |
| 113 if (Pipeline::SupportedTarget()) { | |
| 114 FOR_FLOAT64_INPUTS(i) { | 113 FOR_FLOAT64_INPUTS(i) { |
| 115 input = *i; | 114 input = *i; |
| 116 int32_t expected = DoubleToInt32(*i); | 115 int32_t expected = DoubleToInt32(*i); |
| 117 t.Call(); | 116 t.Call(); |
| 118 CHECK_EQ(expected, result); | 117 CHECK_EQ(expected, result); |
| 119 } | 118 } |
| 120 } | |
| 121 } | 119 } |
| 122 | 120 |
| 123 | 121 |
| 124 // TODO(titzer): test tagged representation for input to NumberToUint32. | 122 // TODO(titzer): test tagged representation for input to NumberToUint32. |
| 125 TEST(RunNumberToUint32_float64) { | 123 TEST(RunNumberToUint32_float64) { |
| 126 // TODO(titzer): explicit load/stores here are only because of representations | 124 // TODO(titzer): explicit load/stores here are only because of representations |
| 127 double input; | 125 double input; |
| 128 uint32_t result; | 126 uint32_t result; |
| 129 SimplifiedLoweringTester<Object*> t; | 127 SimplifiedLoweringTester<Object*> t; |
| 130 FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(), | 128 FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(), |
| 131 kMachFloat64}; | 129 kMachFloat64}; |
| 132 Node* loaded = t.LoadField(load, t.PointerConstant(&input)); | 130 Node* loaded = t.LoadField(load, t.PointerConstant(&input)); |
| 133 NodeProperties::SetBounds(loaded, Bounds(Type::Number())); | 131 NodeProperties::SetBounds(loaded, Bounds(Type::Number())); |
| 134 Node* convert = t.NumberToUint32(loaded); | 132 Node* convert = t.NumberToUint32(loaded); |
| 135 FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Unsigned32(), | 133 FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Unsigned32(), |
| 136 kMachUint32}; | 134 kMachUint32}; |
| 137 t.StoreField(store, t.PointerConstant(&result), convert); | 135 t.StoreField(store, t.PointerConstant(&result), convert); |
| 138 t.Return(t.jsgraph.TrueConstant()); | 136 t.Return(t.jsgraph.TrueConstant()); |
| 139 t.LowerAllNodes(); | 137 t.LowerAllNodes(); |
| 140 t.GenerateCode(); | 138 t.GenerateCode(); |
| 141 | 139 |
| 142 if (Pipeline::SupportedTarget()) { | |
| 143 FOR_FLOAT64_INPUTS(i) { | 140 FOR_FLOAT64_INPUTS(i) { |
| 144 input = *i; | 141 input = *i; |
| 145 uint32_t expected = DoubleToUint32(*i); | 142 uint32_t expected = DoubleToUint32(*i); |
| 146 t.Call(); | 143 t.Call(); |
| 147 CHECK_EQ(static_cast<int32_t>(expected), static_cast<int32_t>(result)); | 144 CHECK_EQ(static_cast<int32_t>(expected), static_cast<int32_t>(result)); |
| 148 } | 145 } |
| 149 } | 146 } |
| 150 } | |
| 151 | 147 |
| 152 | 148 |
| 153 // Create a simple JSObject with a unique map. | 149 // Create a simple JSObject with a unique map. |
| 154 static Handle<JSObject> TestObject() { | 150 static Handle<JSObject> TestObject() { |
| 155 static int index = 0; | 151 static int index = 0; |
| 156 char buffer[50]; | 152 char buffer[50]; |
| 157 v8::base::OS::SNPrintF(buffer, 50, "({'a_%d':1})", index++); | 153 v8::base::OS::SNPrintF(buffer, 50, "({'a_%d':1})", index++); |
| 158 return Handle<JSObject>::cast(v8::Utils::OpenHandle(*CompileRun(buffer))); | 154 return Handle<JSObject>::cast(v8::Utils::OpenHandle(*CompileRun(buffer))); |
| 159 } | 155 } |
| 160 | 156 |
| 161 | 157 |
| 162 TEST(RunLoadMap) { | 158 TEST(RunLoadMap) { |
| 163 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 159 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 164 FieldAccess access = AccessBuilder::ForMap(); | 160 FieldAccess access = AccessBuilder::ForMap(); |
| 165 Node* load = t.LoadField(access, t.Parameter(0)); | 161 Node* load = t.LoadField(access, t.Parameter(0)); |
| 166 t.Return(load); | 162 t.Return(load); |
| 167 | 163 |
| 168 t.LowerAllNodes(); | 164 t.LowerAllNodes(); |
| 169 t.GenerateCode(); | 165 t.GenerateCode(); |
| 170 | 166 |
| 171 if (Pipeline::SupportedTarget()) { | 167 Handle<JSObject> src = TestObject(); |
| 172 Handle<JSObject> src = TestObject(); | 168 Handle<Map> src_map(src->map()); |
| 173 Handle<Map> src_map(src->map()); | 169 Object* result = t.Call(*src); // TODO(titzer): raw pointers in call |
| 174 Object* result = t.Call(*src); // TODO(titzer): raw pointers in call | 170 CHECK_EQ(*src_map, result); |
| 175 CHECK_EQ(*src_map, result); | |
| 176 } | |
| 177 } | 171 } |
| 178 | 172 |
| 179 | 173 |
| 180 TEST(RunStoreMap) { | 174 TEST(RunStoreMap) { |
| 181 SimplifiedLoweringTester<int32_t> t(kMachAnyTagged, kMachAnyTagged); | 175 SimplifiedLoweringTester<int32_t> t(kMachAnyTagged, kMachAnyTagged); |
| 182 FieldAccess access = AccessBuilder::ForMap(); | 176 FieldAccess access = AccessBuilder::ForMap(); |
| 183 t.StoreField(access, t.Parameter(1), t.Parameter(0)); | 177 t.StoreField(access, t.Parameter(1), t.Parameter(0)); |
| 184 t.Return(t.jsgraph.TrueConstant()); | 178 t.Return(t.jsgraph.TrueConstant()); |
| 185 | 179 |
| 186 t.LowerAllNodes(); | 180 t.LowerAllNodes(); |
| 187 t.GenerateCode(); | 181 t.GenerateCode(); |
| 188 | 182 |
| 189 if (Pipeline::SupportedTarget()) { | |
| 190 Handle<JSObject> src = TestObject(); | 183 Handle<JSObject> src = TestObject(); |
| 191 Handle<Map> src_map(src->map()); | 184 Handle<Map> src_map(src->map()); |
| 192 Handle<JSObject> dst = TestObject(); | 185 Handle<JSObject> dst = TestObject(); |
| 193 CHECK(src->map() != dst->map()); | 186 CHECK(src->map() != dst->map()); |
| 194 t.Call(*src_map, *dst); // TODO(titzer): raw pointers in call | 187 t.Call(*src_map, *dst); // TODO(titzer): raw pointers in call |
| 195 CHECK(*src_map == dst->map()); | 188 CHECK(*src_map == dst->map()); |
| 196 } | 189 } |
| 197 } | |
| 198 | 190 |
| 199 | 191 |
| 200 TEST(RunLoadProperties) { | 192 TEST(RunLoadProperties) { |
| 201 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 193 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 202 FieldAccess access = AccessBuilder::ForJSObjectProperties(); | 194 FieldAccess access = AccessBuilder::ForJSObjectProperties(); |
| 203 Node* load = t.LoadField(access, t.Parameter(0)); | 195 Node* load = t.LoadField(access, t.Parameter(0)); |
| 204 t.Return(load); | 196 t.Return(load); |
| 205 | 197 |
| 206 t.LowerAllNodes(); | 198 t.LowerAllNodes(); |
| 207 t.GenerateCode(); | 199 t.GenerateCode(); |
| 208 | 200 |
| 209 if (Pipeline::SupportedTarget()) { | |
| 210 Handle<JSObject> src = TestObject(); | 201 Handle<JSObject> src = TestObject(); |
| 211 Handle<FixedArray> src_props(src->properties()); | 202 Handle<FixedArray> src_props(src->properties()); |
| 212 Object* result = t.Call(*src); // TODO(titzer): raw pointers in call | 203 Object* result = t.Call(*src); // TODO(titzer): raw pointers in call |
| 213 CHECK_EQ(*src_props, result); | 204 CHECK_EQ(*src_props, result); |
| 214 } | |
| 215 } | 205 } |
| 216 | 206 |
| 217 | 207 |
| 218 TEST(RunLoadStoreMap) { | 208 TEST(RunLoadStoreMap) { |
| 219 SimplifiedLoweringTester<Object*> t(kMachAnyTagged, kMachAnyTagged); | 209 SimplifiedLoweringTester<Object*> t(kMachAnyTagged, kMachAnyTagged); |
| 220 FieldAccess access = AccessBuilder::ForMap(); | 210 FieldAccess access = AccessBuilder::ForMap(); |
| 221 Node* load = t.LoadField(access, t.Parameter(0)); | 211 Node* load = t.LoadField(access, t.Parameter(0)); |
| 222 t.StoreField(access, t.Parameter(1), load); | 212 t.StoreField(access, t.Parameter(1), load); |
| 223 t.Return(load); | 213 t.Return(load); |
| 224 | 214 |
| 225 t.LowerAllNodes(); | 215 t.LowerAllNodes(); |
| 226 t.GenerateCode(); | 216 t.GenerateCode(); |
| 227 | 217 |
| 228 if (Pipeline::SupportedTarget()) { | |
| 229 Handle<JSObject> src = TestObject(); | 218 Handle<JSObject> src = TestObject(); |
| 230 Handle<Map> src_map(src->map()); | 219 Handle<Map> src_map(src->map()); |
| 231 Handle<JSObject> dst = TestObject(); | 220 Handle<JSObject> dst = TestObject(); |
| 232 CHECK(src->map() != dst->map()); | 221 CHECK(src->map() != dst->map()); |
| 233 Object* result = t.Call(*src, *dst); // TODO(titzer): raw pointers in call | 222 Object* result = t.Call(*src, *dst); // TODO(titzer): raw pointers in call |
| 234 CHECK(result->IsMap()); | 223 CHECK(result->IsMap()); |
| 235 CHECK_EQ(*src_map, result); | 224 CHECK_EQ(*src_map, result); |
| 236 CHECK(*src_map == dst->map()); | 225 CHECK(*src_map == dst->map()); |
| 237 } | |
| 238 } | 226 } |
| 239 | 227 |
| 240 | 228 |
| 241 TEST(RunLoadStoreFixedArrayIndex) { | 229 TEST(RunLoadStoreFixedArrayIndex) { |
| 242 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 230 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 243 ElementAccess access = AccessBuilder::ForFixedArrayElement(); | 231 ElementAccess access = AccessBuilder::ForFixedArrayElement(); |
| 244 Node* load = t.LoadElement(access, t.Parameter(0), t.Int32Constant(0)); | 232 Node* load = t.LoadElement(access, t.Parameter(0), t.Int32Constant(0)); |
| 245 t.StoreElement(access, t.Parameter(0), t.Int32Constant(1), load); | 233 t.StoreElement(access, t.Parameter(0), t.Int32Constant(1), load); |
| 246 t.Return(load); | 234 t.Return(load); |
| 247 | 235 |
| 248 t.LowerAllNodes(); | 236 t.LowerAllNodes(); |
| 249 t.GenerateCode(); | 237 t.GenerateCode(); |
| 250 | 238 |
| 251 if (Pipeline::SupportedTarget()) { | |
| 252 Handle<FixedArray> array = t.factory()->NewFixedArray(2); | 239 Handle<FixedArray> array = t.factory()->NewFixedArray(2); |
| 253 Handle<JSObject> src = TestObject(); | 240 Handle<JSObject> src = TestObject(); |
| 254 Handle<JSObject> dst = TestObject(); | 241 Handle<JSObject> dst = TestObject(); |
| 255 array->set(0, *src); | 242 array->set(0, *src); |
| 256 array->set(1, *dst); | 243 array->set(1, *dst); |
| 257 Object* result = t.Call(*array); | 244 Object* result = t.Call(*array); |
| 258 CHECK_EQ(*src, result); | 245 CHECK_EQ(*src, result); |
| 259 CHECK_EQ(*src, array->get(0)); | 246 CHECK_EQ(*src, array->get(0)); |
| 260 CHECK_EQ(*src, array->get(1)); | 247 CHECK_EQ(*src, array->get(1)); |
| 261 } | |
| 262 } | 248 } |
| 263 | 249 |
| 264 | 250 |
| 265 TEST(RunLoadStoreArrayBuffer) { | 251 TEST(RunLoadStoreArrayBuffer) { |
| 266 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 252 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 267 const int index = 12; | 253 const int index = 12; |
| 268 const int array_length = 2 * index; | 254 const int array_length = 2 * index; |
| 269 ElementAccess buffer_access = | 255 ElementAccess buffer_access = |
| 270 AccessBuilder::ForTypedArrayElement(kExternalInt8Array, true); | 256 AccessBuilder::ForTypedArrayElement(kExternalInt8Array, true); |
| 271 Node* backing_store = t.LoadField( | 257 Node* backing_store = t.LoadField( |
| 272 AccessBuilder::ForJSArrayBufferBackingStore(), t.Parameter(0)); | 258 AccessBuilder::ForJSArrayBufferBackingStore(), t.Parameter(0)); |
| 273 Node* load = | 259 Node* load = |
| 274 t.LoadElement(buffer_access, backing_store, t.Int32Constant(index)); | 260 t.LoadElement(buffer_access, backing_store, t.Int32Constant(index)); |
| 275 t.StoreElement(buffer_access, backing_store, t.Int32Constant(index + 1), | 261 t.StoreElement(buffer_access, backing_store, t.Int32Constant(index + 1), |
| 276 load); | 262 load); |
| 277 t.Return(t.jsgraph.TrueConstant()); | 263 t.Return(t.jsgraph.TrueConstant()); |
| 278 | 264 |
| 279 t.LowerAllNodes(); | 265 t.LowerAllNodes(); |
| 280 t.GenerateCode(); | 266 t.GenerateCode(); |
| 281 | 267 |
| 282 if (Pipeline::SupportedTarget()) { | |
| 283 Handle<JSArrayBuffer> array = t.factory()->NewJSArrayBuffer(); | 268 Handle<JSArrayBuffer> array = t.factory()->NewJSArrayBuffer(); |
| 284 Runtime::SetupArrayBufferAllocatingData(t.isolate(), array, array_length); | 269 Runtime::SetupArrayBufferAllocatingData(t.isolate(), array, array_length); |
| 285 uint8_t* data = reinterpret_cast<uint8_t*>(array->backing_store()); | 270 uint8_t* data = reinterpret_cast<uint8_t*>(array->backing_store()); |
| 286 for (int i = 0; i < array_length; i++) { | 271 for (int i = 0; i < array_length; i++) { |
| 287 data[i] = i; | 272 data[i] = i; |
| 288 } | 273 } |
| 289 | 274 |
| 290 // TODO(titzer): raw pointers in call | 275 // TODO(titzer): raw pointers in call |
| 291 Object* result = t.Call(*array); | 276 Object* result = t.Call(*array); |
| 292 CHECK_EQ(t.isolate()->heap()->true_value(), result); | 277 CHECK_EQ(t.isolate()->heap()->true_value(), result); |
| 293 for (int i = 0; i < array_length; i++) { | 278 for (int i = 0; i < array_length; i++) { |
| 294 uint8_t expected = i; | 279 uint8_t expected = i; |
| 295 if (i == (index + 1)) expected = index; | 280 if (i == (index + 1)) expected = index; |
| 296 CHECK_EQ(data[i], expected); | 281 CHECK_EQ(data[i], expected); |
| 297 } | 282 } |
| 298 } | 283 } |
| 299 } | |
| 300 | 284 |
| 301 | 285 |
| 302 TEST(RunLoadFieldFromUntaggedBase) { | 286 TEST(RunLoadFieldFromUntaggedBase) { |
| 303 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3)}; | 287 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3)}; |
| 304 | 288 |
| 305 for (size_t i = 0; i < arraysize(smis); i++) { | 289 for (size_t i = 0; i < arraysize(smis); i++) { |
| 306 int offset = static_cast<int>(i * sizeof(Smi*)); | 290 int offset = static_cast<int>(i * sizeof(Smi*)); |
| 307 FieldAccess access = {kUntaggedBase, offset, Handle<Name>(), | 291 FieldAccess access = {kUntaggedBase, offset, Handle<Name>(), |
| 308 Type::Integral32(), kMachAnyTagged}; | 292 Type::Integral32(), kMachAnyTagged}; |
| 309 | 293 |
| 310 SimplifiedLoweringTester<Object*> t; | 294 SimplifiedLoweringTester<Object*> t; |
| 311 Node* load = t.LoadField(access, t.PointerConstant(smis)); | 295 Node* load = t.LoadField(access, t.PointerConstant(smis)); |
| 312 t.Return(load); | 296 t.Return(load); |
| 313 t.LowerAllNodes(); | 297 t.LowerAllNodes(); |
| 314 | 298 |
| 315 if (!Pipeline::SupportedTarget()) continue; | |
| 316 | |
| 317 for (int j = -5; j <= 5; j++) { | 299 for (int j = -5; j <= 5; j++) { |
| 318 Smi* expected = Smi::FromInt(j); | 300 Smi* expected = Smi::FromInt(j); |
| 319 smis[i] = expected; | 301 smis[i] = expected; |
| 320 CHECK_EQ(expected, t.Call()); | 302 CHECK_EQ(expected, t.Call()); |
| 321 } | 303 } |
| 322 } | 304 } |
| 323 } | 305 } |
| 324 | 306 |
| 325 | 307 |
| 326 TEST(RunStoreFieldToUntaggedBase) { | 308 TEST(RunStoreFieldToUntaggedBase) { |
| 327 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3)}; | 309 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3)}; |
| 328 | 310 |
| 329 for (size_t i = 0; i < arraysize(smis); i++) { | 311 for (size_t i = 0; i < arraysize(smis); i++) { |
| 330 int offset = static_cast<int>(i * sizeof(Smi*)); | 312 int offset = static_cast<int>(i * sizeof(Smi*)); |
| 331 FieldAccess access = {kUntaggedBase, offset, Handle<Name>(), | 313 FieldAccess access = {kUntaggedBase, offset, Handle<Name>(), |
| 332 Type::Integral32(), kMachAnyTagged}; | 314 Type::Integral32(), kMachAnyTagged}; |
| 333 | 315 |
| 334 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 316 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 335 Node* p0 = t.Parameter(0); | 317 Node* p0 = t.Parameter(0); |
| 336 t.StoreField(access, t.PointerConstant(smis), p0); | 318 t.StoreField(access, t.PointerConstant(smis), p0); |
| 337 t.Return(p0); | 319 t.Return(p0); |
| 338 t.LowerAllNodes(); | 320 t.LowerAllNodes(); |
| 339 | 321 |
| 340 if (!Pipeline::SupportedTarget()) continue; | |
| 341 | |
| 342 for (int j = -5; j <= 5; j++) { | 322 for (int j = -5; j <= 5; j++) { |
| 343 Smi* expected = Smi::FromInt(j); | 323 Smi* expected = Smi::FromInt(j); |
| 344 smis[i] = Smi::FromInt(-100); | 324 smis[i] = Smi::FromInt(-100); |
| 345 CHECK_EQ(expected, t.Call(expected)); | 325 CHECK_EQ(expected, t.Call(expected)); |
| 346 CHECK_EQ(expected, smis[i]); | 326 CHECK_EQ(expected, smis[i]); |
| 347 } | 327 } |
| 348 } | 328 } |
| 349 } | 329 } |
| 350 | 330 |
| 351 | 331 |
| 352 TEST(RunLoadElementFromUntaggedBase) { | 332 TEST(RunLoadElementFromUntaggedBase) { |
| 353 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), | 333 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), |
| 354 Smi::FromInt(4), Smi::FromInt(5)}; | 334 Smi::FromInt(4), Smi::FromInt(5)}; |
| 355 | 335 |
| 356 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes | 336 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes |
| 357 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index | 337 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index |
| 358 int offset = static_cast<int>(i * sizeof(Smi*)); | 338 int offset = static_cast<int>(i * sizeof(Smi*)); |
| 359 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), | 339 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), |
| 360 kMachAnyTagged}; | 340 kMachAnyTagged}; |
| 361 | 341 |
| 362 SimplifiedLoweringTester<Object*> t; | 342 SimplifiedLoweringTester<Object*> t; |
| 363 Node* load = t.LoadElement(access, t.PointerConstant(smis), | 343 Node* load = t.LoadElement(access, t.PointerConstant(smis), |
| 364 t.Int32Constant(static_cast<int>(j))); | 344 t.Int32Constant(static_cast<int>(j))); |
| 365 t.Return(load); | 345 t.Return(load); |
| 366 t.LowerAllNodes(); | 346 t.LowerAllNodes(); |
| 367 | 347 |
| 368 if (!Pipeline::SupportedTarget()) continue; | |
| 369 | |
| 370 for (int k = -5; k <= 5; k++) { | 348 for (int k = -5; k <= 5; k++) { |
| 371 Smi* expected = Smi::FromInt(k); | 349 Smi* expected = Smi::FromInt(k); |
| 372 smis[i + j] = expected; | 350 smis[i + j] = expected; |
| 373 CHECK_EQ(expected, t.Call()); | 351 CHECK_EQ(expected, t.Call()); |
| 374 } | 352 } |
| 375 } | 353 } |
| 376 } | 354 } |
| 377 } | 355 } |
| 378 | 356 |
| 379 | 357 |
| 380 TEST(RunStoreElementFromUntaggedBase) { | 358 TEST(RunStoreElementFromUntaggedBase) { |
| 381 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), | 359 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), |
| 382 Smi::FromInt(4), Smi::FromInt(5)}; | 360 Smi::FromInt(4), Smi::FromInt(5)}; |
| 383 | 361 |
| 384 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes | 362 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes |
| 385 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index | 363 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index |
| 386 int offset = static_cast<int>(i * sizeof(Smi*)); | 364 int offset = static_cast<int>(i * sizeof(Smi*)); |
| 387 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), | 365 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), |
| 388 kMachAnyTagged}; | 366 kMachAnyTagged}; |
| 389 | 367 |
| 390 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 368 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 391 Node* p0 = t.Parameter(0); | 369 Node* p0 = t.Parameter(0); |
| 392 t.StoreElement(access, t.PointerConstant(smis), | 370 t.StoreElement(access, t.PointerConstant(smis), |
| 393 t.Int32Constant(static_cast<int>(j)), p0); | 371 t.Int32Constant(static_cast<int>(j)), p0); |
| 394 t.Return(p0); | 372 t.Return(p0); |
| 395 t.LowerAllNodes(); | 373 t.LowerAllNodes(); |
| 396 | 374 |
| 397 if (!Pipeline::SupportedTarget()) continue; | |
| 398 | |
| 399 for (int k = -5; k <= 5; k++) { | 375 for (int k = -5; k <= 5; k++) { |
| 400 Smi* expected = Smi::FromInt(k); | 376 Smi* expected = Smi::FromInt(k); |
| 401 smis[i + j] = Smi::FromInt(-100); | 377 smis[i + j] = Smi::FromInt(-100); |
| 402 CHECK_EQ(expected, t.Call(expected)); | 378 CHECK_EQ(expected, t.Call(expected)); |
| 403 CHECK_EQ(expected, smis[i + j]); | 379 CHECK_EQ(expected, smis[i + j]); |
| 404 } | 380 } |
| 405 | 381 |
| 406 // TODO(titzer): assert the contents of the array. | 382 // TODO(titzer): assert the contents of the array. |
| 407 } | 383 } |
| 408 } | 384 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 ElementAccess access = GetElementAccess(); | 431 ElementAccess access = GetElementAccess(); |
| 456 | 432 |
| 457 SimplifiedLoweringTester<Object*> t; | 433 SimplifiedLoweringTester<Object*> t; |
| 458 Node* ptr = GetBaseNode(&t); | 434 Node* ptr = GetBaseNode(&t); |
| 459 Node* load = t.LoadElement(access, ptr, t.Int32Constant(from_index)); | 435 Node* load = t.LoadElement(access, ptr, t.Int32Constant(from_index)); |
| 460 t.StoreElement(access, ptr, t.Int32Constant(to_index), load); | 436 t.StoreElement(access, ptr, t.Int32Constant(to_index), load); |
| 461 t.Return(t.jsgraph.TrueConstant()); | 437 t.Return(t.jsgraph.TrueConstant()); |
| 462 t.LowerAllNodes(); | 438 t.LowerAllNodes(); |
| 463 t.GenerateCode(); | 439 t.GenerateCode(); |
| 464 | 440 |
| 465 if (Pipeline::SupportedTarget()) { | |
| 466 Object* result = t.Call(); | 441 Object* result = t.Call(); |
| 467 CHECK_EQ(t.isolate()->heap()->true_value(), result); | 442 CHECK_EQ(t.isolate()->heap()->true_value(), result); |
| 468 } | |
| 469 } | 443 } |
| 470 | 444 |
| 471 // Create and run code that copies the field in either {untagged_array} | 445 // Create and run code that copies the field in either {untagged_array} |
| 472 // or {tagged_array} at index {from_index} to index {to_index}. | 446 // or {tagged_array} at index {from_index} to index {to_index}. |
| 473 void RunCopyField(int from_index, int to_index) { | 447 void RunCopyField(int from_index, int to_index) { |
| 474 BoundsCheck(from_index); | 448 BoundsCheck(from_index); |
| 475 BoundsCheck(to_index); | 449 BoundsCheck(to_index); |
| 476 FieldAccess from_access = GetFieldAccess(from_index); | 450 FieldAccess from_access = GetFieldAccess(from_index); |
| 477 FieldAccess to_access = GetFieldAccess(to_index); | 451 FieldAccess to_access = GetFieldAccess(to_index); |
| 478 | 452 |
| 479 SimplifiedLoweringTester<Object*> t; | 453 SimplifiedLoweringTester<Object*> t; |
| 480 Node* ptr = GetBaseNode(&t); | 454 Node* ptr = GetBaseNode(&t); |
| 481 Node* load = t.LoadField(from_access, ptr); | 455 Node* load = t.LoadField(from_access, ptr); |
| 482 t.StoreField(to_access, ptr, load); | 456 t.StoreField(to_access, ptr, load); |
| 483 t.Return(t.jsgraph.TrueConstant()); | 457 t.Return(t.jsgraph.TrueConstant()); |
| 484 t.LowerAllNodes(); | 458 t.LowerAllNodes(); |
| 485 t.GenerateCode(); | 459 t.GenerateCode(); |
| 486 | 460 |
| 487 if (Pipeline::SupportedTarget()) { | |
| 488 Object* result = t.Call(); | 461 Object* result = t.Call(); |
| 489 CHECK_EQ(t.isolate()->heap()->true_value(), result); | 462 CHECK_EQ(t.isolate()->heap()->true_value(), result); |
| 490 } | |
| 491 } | 463 } |
| 492 | 464 |
| 493 // Create and run code that copies the elements from {this} to {that}. | 465 // Create and run code that copies the elements from {this} to {that}. |
| 494 void RunCopyElements(AccessTester<E>* that) { | 466 void RunCopyElements(AccessTester<E>* that) { |
| 495 // TODO(titzer): Rewrite this test without StructuredGraphBuilder support. | 467 // TODO(titzer): Rewrite this test without StructuredGraphBuilder support. |
| 496 #if 0 | 468 #if 0 |
| 497 SimplifiedLoweringTester<Object*> t; | 469 SimplifiedLoweringTester<Object*> t; |
| 498 | 470 |
| 499 Node* one = t.Int32Constant(1); | 471 Node* one = t.Int32Constant(1); |
| 500 Node* index = t.Int32Constant(0); | 472 Node* index = t.Int32Constant(0); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 518 t.environment()->Push(index); | 490 t.environment()->Push(index); |
| 519 // continue | 491 // continue |
| 520 loop.EndBody(); | 492 loop.EndBody(); |
| 521 loop.EndLoop(); | 493 loop.EndLoop(); |
| 522 } | 494 } |
| 523 index = t.environment()->Pop(); | 495 index = t.environment()->Pop(); |
| 524 t.Return(t.jsgraph.TrueConstant()); | 496 t.Return(t.jsgraph.TrueConstant()); |
| 525 t.LowerAllNodes(); | 497 t.LowerAllNodes(); |
| 526 t.GenerateCode(); | 498 t.GenerateCode(); |
| 527 | 499 |
| 528 if (Pipeline::SupportedTarget()) { | |
| 529 Object* result = t.Call(); | 500 Object* result = t.Call(); |
| 530 CHECK_EQ(t.isolate()->heap()->true_value(), result); | 501 CHECK_EQ(t.isolate()->heap()->true_value(), result); |
| 531 } | |
| 532 #endif | 502 #endif |
| 533 } | 503 } |
| 534 | 504 |
| 535 E GetElement(int index) { | 505 E GetElement(int index) { |
| 536 BoundsCheck(index); | 506 BoundsCheck(index); |
| 537 if (tagged) { | 507 if (tagged) { |
| 538 return GetTaggedElement(index); | 508 return GetTaggedElement(index); |
| 539 } else { | 509 } else { |
| 540 return untagged_array[index]; | 510 return untagged_array[index]; |
| 541 } | 511 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 for (int taggedness = 0; taggedness < 2; taggedness++) { | 559 for (int taggedness = 0; taggedness < 2; taggedness++) { |
| 590 AccessTester<E> a(taggedness == 1, rep, original_elements, num); | 560 AccessTester<E> a(taggedness == 1, rep, original_elements, num); |
| 591 for (int field = 0; field < 2; field++) { | 561 for (int field = 0; field < 2; field++) { |
| 592 for (int i = 0; i < num_elements - 1; i++) { | 562 for (int i = 0; i < num_elements - 1; i++) { |
| 593 a.Reinitialize(); | 563 a.Reinitialize(); |
| 594 if (field == 0) { | 564 if (field == 0) { |
| 595 a.RunCopyField(i, i + 1); // Test field read/write. | 565 a.RunCopyField(i, i + 1); // Test field read/write. |
| 596 } else { | 566 } else { |
| 597 a.RunCopyElement(i, i + 1); // Test element read/write. | 567 a.RunCopyElement(i, i + 1); // Test element read/write. |
| 598 } | 568 } |
| 599 if (Pipeline::SupportedTarget()) { // verify. | |
| 600 for (int j = 0; j < num_elements; j++) { | 569 for (int j = 0; j < num_elements; j++) { |
| 601 E expect = | 570 E expect = |
| 602 j == (i + 1) ? original_elements[i] : original_elements[j]; | 571 j == (i + 1) ? original_elements[i] : original_elements[j]; |
| 603 CHECK_EQ(expect, a.GetElement(j)); | 572 CHECK_EQ(expect, a.GetElement(j)); |
| 604 } | 573 } |
| 605 } | |
| 606 } | 574 } |
| 607 } | 575 } |
| 608 } | 576 } |
| 609 // Test array copy. | 577 // Test array copy. |
| 610 for (int tf = 0; tf < 2; tf++) { | 578 for (int tf = 0; tf < 2; tf++) { |
| 611 for (int tt = 0; tt < 2; tt++) { | 579 for (int tt = 0; tt < 2; tt++) { |
| 612 AccessTester<E> a(tf == 1, rep, original_elements, num); | 580 AccessTester<E> a(tf == 1, rep, original_elements, num); |
| 613 AccessTester<E> b(tt == 1, rep, original_elements, num); | 581 AccessTester<E> b(tt == 1, rep, original_elements, num); |
| 614 a.RunCopyElements(&b); | 582 a.RunCopyElements(&b); |
| 615 if (Pipeline::SupportedTarget()) { // verify. | |
| 616 for (int i = 0; i < num_elements; i++) { | 583 for (int i = 0; i < num_elements; i++) { |
| 617 CHECK_EQ(a.GetElement(i), b.GetElement(i)); | 584 CHECK_EQ(a.GetElement(i), b.GetElement(i)); |
| 618 } | |
| 619 } | 585 } |
| 620 } | 586 } |
| 621 } | 587 } |
| 622 } | 588 } |
| 623 | 589 |
| 624 | 590 |
| 625 TEST(RunAccessTests_uint8) { | 591 TEST(RunAccessTests_uint8) { |
| 626 uint8_t data[] = {0x07, 0x16, 0x25, 0x34, 0x43, 0x99, | 592 uint8_t data[] = {0x07, 0x16, 0x25, 0x34, 0x43, 0x99, |
| 627 0xab, 0x78, 0x89, 0x19, 0x2b, 0x38}; | 593 0xab, 0x78, 0x89, 0x19, 0x2b, 0x38}; |
| 628 RunAccessTest<uint8_t>(kMachInt8, data, arraysize(data)); | 594 RunAccessTest<uint8_t>(kMachInt8, data, arraysize(data)); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 } | 627 } |
| 662 | 628 |
| 663 | 629 |
| 664 TEST(RunAccessTests_Smi) { | 630 TEST(RunAccessTests_Smi) { |
| 665 Smi* data[] = {Smi::FromInt(-1), Smi::FromInt(-9), | 631 Smi* data[] = {Smi::FromInt(-1), Smi::FromInt(-9), |
| 666 Smi::FromInt(0), Smi::FromInt(666), | 632 Smi::FromInt(0), Smi::FromInt(666), |
| 667 Smi::FromInt(77777), Smi::FromInt(Smi::kMaxValue)}; | 633 Smi::FromInt(77777), Smi::FromInt(Smi::kMaxValue)}; |
| 668 RunAccessTest<Smi*>(kMachAnyTagged, data, arraysize(data)); | 634 RunAccessTest<Smi*>(kMachAnyTagged, data, arraysize(data)); |
| 669 } | 635 } |
| 670 | 636 |
| 671 #if V8_TURBOFAN_TARGET | 637 |
| 672 TEST(RunAllocate) { | 638 TEST(RunAllocate) { |
| 673 PretenureFlag flag[] = {NOT_TENURED, TENURED}; | 639 PretenureFlag flag[] = {NOT_TENURED, TENURED}; |
| 674 | 640 |
| 675 for (size_t i = 0; i < arraysize(flag); i++) { | 641 for (size_t i = 0; i < arraysize(flag); i++) { |
| 676 SimplifiedLoweringTester<HeapObject*> t; | 642 SimplifiedLoweringTester<HeapObject*> t; |
| 677 FieldAccess access = AccessBuilder::ForMap(); | 643 FieldAccess access = AccessBuilder::ForMap(); |
| 678 Node* size = t.jsgraph.Constant(HeapNumber::kSize); | 644 Node* size = t.jsgraph.Constant(HeapNumber::kSize); |
| 679 Node* alloc = t.NewNode(t.simplified()->Allocate(flag[i]), size); | 645 Node* alloc = t.NewNode(t.simplified()->Allocate(flag[i]), size); |
| 680 Node* map = t.jsgraph.Constant(t.factory()->heap_number_map()); | 646 Node* map = t.jsgraph.Constant(t.factory()->heap_number_map()); |
| 681 t.StoreField(access, alloc, map); | 647 t.StoreField(access, alloc, map); |
| 682 t.Return(alloc); | 648 t.Return(alloc); |
| 683 | 649 |
| 684 t.LowerAllNodes(); | 650 t.LowerAllNodes(); |
| 685 t.GenerateCode(); | 651 t.GenerateCode(); |
| 686 | 652 |
| 687 if (Pipeline::SupportedTarget()) { | |
| 688 HeapObject* result = t.CallWithPotentialGC<HeapObject>(); | 653 HeapObject* result = t.CallWithPotentialGC<HeapObject>(); |
| 689 CHECK(t.heap()->new_space()->Contains(result) || flag[i] == TENURED); | 654 CHECK(t.heap()->new_space()->Contains(result) || flag[i] == TENURED); |
| 690 CHECK(t.heap()->old_space()->Contains(result) || flag[i] == NOT_TENURED); | 655 CHECK(t.heap()->old_space()->Contains(result) || flag[i] == NOT_TENURED); |
| 691 CHECK(result->IsHeapNumber()); | 656 CHECK(result->IsHeapNumber()); |
| 692 } | |
| 693 } | 657 } |
| 694 } | 658 } |
| 695 #endif | 659 |
| 696 | 660 |
| 697 // Fills in most of the nodes of the graph in order to make tests shorter. | 661 // Fills in most of the nodes of the graph in order to make tests shorter. |
| 698 class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders { | 662 class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders { |
| 699 public: | 663 public: |
| 700 Typer typer; | 664 Typer typer; |
| 701 JSOperatorBuilder javascript; | 665 JSOperatorBuilder javascript; |
| 702 JSGraph jsgraph; | 666 JSGraph jsgraph; |
| 703 Node* p0; | 667 Node* p0; |
| 704 Node* p1; | 668 Node* p1; |
| 705 Node* p2; | 669 Node* p2; |
| (...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1257 | 1221 |
| 1258 TEST(LowerReferenceEqual_to_wordeq) { | 1222 TEST(LowerReferenceEqual_to_wordeq) { |
| 1259 TestingGraph t(Type::Any(), Type::Any()); | 1223 TestingGraph t(Type::Any(), Type::Any()); |
| 1260 IrOpcode::Value opcode = | 1224 IrOpcode::Value opcode = |
| 1261 static_cast<IrOpcode::Value>(t.machine()->WordEqual()->opcode()); | 1225 static_cast<IrOpcode::Value>(t.machine()->WordEqual()->opcode()); |
| 1262 t.CheckLoweringBinop(opcode, t.simplified()->ReferenceEqual(Type::Any())); | 1226 t.CheckLoweringBinop(opcode, t.simplified()->ReferenceEqual(Type::Any())); |
| 1263 } | 1227 } |
| 1264 | 1228 |
| 1265 | 1229 |
| 1266 TEST(LowerStringOps_to_call_and_compare) { | 1230 TEST(LowerStringOps_to_call_and_compare) { |
| 1267 if (Pipeline::SupportedTarget()) { | |
| 1268 // These tests need linkage for the calls. | 1231 // These tests need linkage for the calls. |
| 1269 TestingGraph t(Type::String(), Type::String()); | 1232 TestingGraph t(Type::String(), Type::String()); |
| 1270 IrOpcode::Value compare_eq = | 1233 IrOpcode::Value compare_eq = |
| 1271 static_cast<IrOpcode::Value>(t.machine()->WordEqual()->opcode()); | 1234 static_cast<IrOpcode::Value>(t.machine()->WordEqual()->opcode()); |
| 1272 IrOpcode::Value compare_lt = | 1235 IrOpcode::Value compare_lt = |
| 1273 static_cast<IrOpcode::Value>(t.machine()->IntLessThan()->opcode()); | 1236 static_cast<IrOpcode::Value>(t.machine()->IntLessThan()->opcode()); |
| 1274 IrOpcode::Value compare_le = static_cast<IrOpcode::Value>( | 1237 IrOpcode::Value compare_le = static_cast<IrOpcode::Value>( |
| 1275 t.machine()->IntLessThanOrEqual()->opcode()); | 1238 t.machine()->IntLessThanOrEqual()->opcode()); |
| 1276 t.CheckLoweringBinop(compare_eq, t.simplified()->StringEqual()); | 1239 t.CheckLoweringBinop(compare_eq, t.simplified()->StringEqual()); |
| 1277 t.CheckLoweringBinop(compare_lt, t.simplified()->StringLessThan()); | 1240 t.CheckLoweringBinop(compare_lt, t.simplified()->StringLessThan()); |
| 1278 t.CheckLoweringBinop(compare_le, t.simplified()->StringLessThanOrEqual()); | 1241 t.CheckLoweringBinop(compare_le, t.simplified()->StringLessThanOrEqual()); |
| 1279 } | 1242 } |
| 1280 } | |
| 1281 | 1243 |
| 1282 | 1244 |
| 1283 void CheckChangeInsertion(IrOpcode::Value expected, MachineType from, | 1245 void CheckChangeInsertion(IrOpcode::Value expected, MachineType from, |
| 1284 MachineType to) { | 1246 MachineType to) { |
| 1285 TestingGraph t(Type::Any()); | 1247 TestingGraph t(Type::Any()); |
| 1286 Node* in = t.ExampleWithOutput(from); | 1248 Node* in = t.ExampleWithOutput(from); |
| 1287 Node* use = t.Use(in, to); | 1249 Node* use = t.Use(in, to); |
| 1288 t.Return(use); | 1250 t.Return(use); |
| 1289 t.Lower(); | 1251 t.Lower(); |
| 1290 CHECK_EQ(expected, use->InputAt(0)->opcode()); | 1252 CHECK_EQ(expected, use->InputAt(0)->opcode()); |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1701 } | 1663 } |
| 1702 | 1664 |
| 1703 | 1665 |
| 1704 TEST(RunNumberDivide_minus_1_TruncatingToInt32) { | 1666 TEST(RunNumberDivide_minus_1_TruncatingToInt32) { |
| 1705 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 1667 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 1706 Node* num = t.NumberToInt32(t.Parameter(0)); | 1668 Node* num = t.NumberToInt32(t.Parameter(0)); |
| 1707 Node* div = t.NumberDivide(num, t.jsgraph.Constant(-1)); | 1669 Node* div = t.NumberDivide(num, t.jsgraph.Constant(-1)); |
| 1708 Node* trunc = t.NumberToInt32(div); | 1670 Node* trunc = t.NumberToInt32(div); |
| 1709 t.Return(trunc); | 1671 t.Return(trunc); |
| 1710 | 1672 |
| 1711 if (Pipeline::SupportedTarget()) { | |
| 1712 t.LowerAllNodesAndLowerChanges(); | 1673 t.LowerAllNodesAndLowerChanges(); |
| 1713 t.GenerateCode(); | 1674 t.GenerateCode(); |
| 1714 | 1675 |
| 1715 FOR_INT32_INPUTS(i) { | 1676 FOR_INT32_INPUTS(i) { |
| 1716 int32_t x = 0 - *i; | 1677 int32_t x = 0 - *i; |
| 1717 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); | 1678 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); |
| 1718 } | 1679 } |
| 1719 } | |
| 1720 } | 1680 } |
| 1721 | 1681 |
| 1722 | 1682 |
| 1723 TEST(NumberMultiply_TruncatingToInt32) { | 1683 TEST(NumberMultiply_TruncatingToInt32) { |
| 1724 int32_t constants[] = {-100, -10, -1, 0, 1, 100, 1000}; | 1684 int32_t constants[] = {-100, -10, -1, 0, 1, 100, 1000}; |
| 1725 | 1685 |
| 1726 for (size_t i = 0; i < arraysize(constants); i++) { | 1686 for (size_t i = 0; i < arraysize(constants); i++) { |
| 1727 TestingGraph t(Type::Signed32()); | 1687 TestingGraph t(Type::Signed32()); |
| 1728 Node* k = t.jsgraph.Constant(constants[i]); | 1688 Node* k = t.jsgraph.Constant(constants[i]); |
| 1729 Node* mul = t.graph()->NewNode(t.simplified()->NumberMultiply(), t.p0, k); | 1689 Node* mul = t.graph()->NewNode(t.simplified()->NumberMultiply(), t.p0, k); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1740 int32_t constants[] = {-100, -10, -1, 0, 1, 100, 1000, 3000999}; | 1700 int32_t constants[] = {-100, -10, -1, 0, 1, 100, 1000, 3000999}; |
| 1741 | 1701 |
| 1742 for (size_t i = 0; i < arraysize(constants); i++) { | 1702 for (size_t i = 0; i < arraysize(constants); i++) { |
| 1743 double k = static_cast<double>(constants[i]); | 1703 double k = static_cast<double>(constants[i]); |
| 1744 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 1704 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 1745 Node* num = t.NumberToInt32(t.Parameter(0)); | 1705 Node* num = t.NumberToInt32(t.Parameter(0)); |
| 1746 Node* mul = t.NumberMultiply(num, t.jsgraph.Constant(k)); | 1706 Node* mul = t.NumberMultiply(num, t.jsgraph.Constant(k)); |
| 1747 Node* trunc = t.NumberToInt32(mul); | 1707 Node* trunc = t.NumberToInt32(mul); |
| 1748 t.Return(trunc); | 1708 t.Return(trunc); |
| 1749 | 1709 |
| 1750 if (Pipeline::SupportedTarget()) { | |
| 1751 t.LowerAllNodesAndLowerChanges(); | 1710 t.LowerAllNodesAndLowerChanges(); |
| 1752 t.GenerateCode(); | 1711 t.GenerateCode(); |
| 1753 | 1712 |
| 1754 FOR_INT32_INPUTS(i) { | 1713 FOR_INT32_INPUTS(i) { |
| 1755 int32_t x = DoubleToInt32(static_cast<double>(*i) * k); | 1714 int32_t x = DoubleToInt32(static_cast<double>(*i) * k); |
| 1756 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); | 1715 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); |
| 1757 } | 1716 } |
| 1758 } | 1717 } |
| 1759 } | |
| 1760 } | 1718 } |
| 1761 | 1719 |
| 1762 | 1720 |
| 1763 TEST(RunNumberMultiply_TruncatingToUint32) { | 1721 TEST(RunNumberMultiply_TruncatingToUint32) { |
| 1764 uint32_t constants[] = {0, 1, 2, 3, 4, 100, 1000, 1024, 2048, 3000999}; | 1722 uint32_t constants[] = {0, 1, 2, 3, 4, 100, 1000, 1024, 2048, 3000999}; |
| 1765 | 1723 |
| 1766 for (size_t i = 0; i < arraysize(constants); i++) { | 1724 for (size_t i = 0; i < arraysize(constants); i++) { |
| 1767 double k = static_cast<double>(constants[i]); | 1725 double k = static_cast<double>(constants[i]); |
| 1768 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 1726 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 1769 Node* num = t.NumberToUint32(t.Parameter(0)); | 1727 Node* num = t.NumberToUint32(t.Parameter(0)); |
| 1770 Node* mul = t.NumberMultiply(num, t.jsgraph.Constant(k)); | 1728 Node* mul = t.NumberMultiply(num, t.jsgraph.Constant(k)); |
| 1771 Node* trunc = t.NumberToUint32(mul); | 1729 Node* trunc = t.NumberToUint32(mul); |
| 1772 t.Return(trunc); | 1730 t.Return(trunc); |
| 1773 | 1731 |
| 1774 if (Pipeline::SupportedTarget()) { | |
| 1775 t.LowerAllNodesAndLowerChanges(); | 1732 t.LowerAllNodesAndLowerChanges(); |
| 1776 t.GenerateCode(); | 1733 t.GenerateCode(); |
| 1777 | 1734 |
| 1778 FOR_UINT32_INPUTS(i) { | 1735 FOR_UINT32_INPUTS(i) { |
| 1779 uint32_t x = DoubleToUint32(static_cast<double>(*i) * k); | 1736 uint32_t x = DoubleToUint32(static_cast<double>(*i) * k); |
| 1780 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); | 1737 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); |
| 1781 } | |
| 1782 } | 1738 } |
| 1783 } | 1739 } |
| 1784 } | 1740 } |
| 1785 | 1741 |
| 1786 | 1742 |
| 1787 TEST(RunNumberDivide_2_TruncatingToUint32) { | 1743 TEST(RunNumberDivide_2_TruncatingToUint32) { |
| 1788 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 1744 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 1789 Node* num = t.NumberToUint32(t.Parameter(0)); | 1745 Node* num = t.NumberToUint32(t.Parameter(0)); |
| 1790 Node* div = t.NumberDivide(num, t.jsgraph.Constant(2)); | 1746 Node* div = t.NumberDivide(num, t.jsgraph.Constant(2)); |
| 1791 Node* trunc = t.NumberToUint32(div); | 1747 Node* trunc = t.NumberToUint32(div); |
| 1792 t.Return(trunc); | 1748 t.Return(trunc); |
| 1793 | 1749 |
| 1794 if (Pipeline::SupportedTarget()) { | |
| 1795 t.LowerAllNodesAndLowerChanges(); | 1750 t.LowerAllNodesAndLowerChanges(); |
| 1796 t.GenerateCode(); | 1751 t.GenerateCode(); |
| 1797 | 1752 |
| 1798 FOR_UINT32_INPUTS(i) { | 1753 FOR_UINT32_INPUTS(i) { |
| 1799 uint32_t x = DoubleToUint32(static_cast<double>(*i / 2.0)); | 1754 uint32_t x = DoubleToUint32(static_cast<double>(*i / 2.0)); |
| 1800 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); | 1755 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); |
| 1801 } | 1756 } |
| 1802 } | |
| 1803 } | 1757 } |
| 1804 | 1758 |
| 1805 | 1759 |
| 1806 TEST(NumberMultiply_ConstantOutOfRange) { | 1760 TEST(NumberMultiply_ConstantOutOfRange) { |
| 1807 TestingGraph t(Type::Signed32()); | 1761 TestingGraph t(Type::Signed32()); |
| 1808 Node* k = t.jsgraph.Constant(1000000023); | 1762 Node* k = t.jsgraph.Constant(1000000023); |
| 1809 Node* mul = t.graph()->NewNode(t.simplified()->NumberMultiply(), t.p0, k); | 1763 Node* mul = t.graph()->NewNode(t.simplified()->NumberMultiply(), t.p0, k); |
| 1810 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), mul); | 1764 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), mul); |
| 1811 t.Return(trunc); | 1765 t.Return(trunc); |
| 1812 t.Lower(); | 1766 t.Lower(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1846 int32_t constants[] = {-100, -10, -1, 1, 2, 100, 1000, 1024, 2048}; | 1800 int32_t constants[] = {-100, -10, -1, 1, 2, 100, 1000, 1024, 2048}; |
| 1847 | 1801 |
| 1848 for (size_t i = 0; i < arraysize(constants); i++) { | 1802 for (size_t i = 0; i < arraysize(constants); i++) { |
| 1849 int32_t k = constants[i]; | 1803 int32_t k = constants[i]; |
| 1850 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 1804 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 1851 Node* num = t.NumberToInt32(t.Parameter(0)); | 1805 Node* num = t.NumberToInt32(t.Parameter(0)); |
| 1852 Node* div = t.NumberDivide(num, t.jsgraph.Constant(k)); | 1806 Node* div = t.NumberDivide(num, t.jsgraph.Constant(k)); |
| 1853 Node* trunc = t.NumberToInt32(div); | 1807 Node* trunc = t.NumberToInt32(div); |
| 1854 t.Return(trunc); | 1808 t.Return(trunc); |
| 1855 | 1809 |
| 1856 if (Pipeline::SupportedTarget()) { | |
| 1857 t.LowerAllNodesAndLowerChanges(); | 1810 t.LowerAllNodesAndLowerChanges(); |
| 1858 t.GenerateCode(); | 1811 t.GenerateCode(); |
| 1859 | 1812 |
| 1860 FOR_INT32_INPUTS(i) { | 1813 FOR_INT32_INPUTS(i) { |
| 1861 if (*i == INT_MAX) continue; // exclude max int. | 1814 if (*i == INT_MAX) continue; // exclude max int. |
| 1862 int32_t x = DoubleToInt32(static_cast<double>(*i) / k); | 1815 int32_t x = DoubleToInt32(static_cast<double>(*i) / k); |
| 1863 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); | 1816 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); |
| 1864 } | |
| 1865 } | 1817 } |
| 1866 } | 1818 } |
| 1867 } | 1819 } |
| 1868 | 1820 |
| 1869 | 1821 |
| 1870 TEST(NumberDivide_TruncatingToUint32) { | 1822 TEST(NumberDivide_TruncatingToUint32) { |
| 1871 double constants[] = {1, 3, 100, 1000, 100998348}; | 1823 double constants[] = {1, 3, 100, 1000, 100998348}; |
| 1872 | 1824 |
| 1873 for (size_t i = 0; i < arraysize(constants); i++) { | 1825 for (size_t i = 0; i < arraysize(constants); i++) { |
| 1874 TestingGraph t(Type::Unsigned32()); | 1826 TestingGraph t(Type::Unsigned32()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1887 uint32_t constants[] = {100, 10, 1, 1, 2, 4, 1000, 1024, 2048}; | 1839 uint32_t constants[] = {100, 10, 1, 1, 2, 4, 1000, 1024, 2048}; |
| 1888 | 1840 |
| 1889 for (size_t i = 0; i < arraysize(constants); i++) { | 1841 for (size_t i = 0; i < arraysize(constants); i++) { |
| 1890 uint32_t k = constants[i]; | 1842 uint32_t k = constants[i]; |
| 1891 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 1843 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 1892 Node* num = t.NumberToUint32(t.Parameter(0)); | 1844 Node* num = t.NumberToUint32(t.Parameter(0)); |
| 1893 Node* div = t.NumberDivide(num, t.jsgraph.Constant(static_cast<double>(k))); | 1845 Node* div = t.NumberDivide(num, t.jsgraph.Constant(static_cast<double>(k))); |
| 1894 Node* trunc = t.NumberToUint32(div); | 1846 Node* trunc = t.NumberToUint32(div); |
| 1895 t.Return(trunc); | 1847 t.Return(trunc); |
| 1896 | 1848 |
| 1897 if (Pipeline::SupportedTarget()) { | |
| 1898 t.LowerAllNodesAndLowerChanges(); | 1849 t.LowerAllNodesAndLowerChanges(); |
| 1899 t.GenerateCode(); | 1850 t.GenerateCode(); |
| 1900 | 1851 |
| 1901 FOR_UINT32_INPUTS(i) { | 1852 FOR_UINT32_INPUTS(i) { |
| 1902 uint32_t x = *i / k; | 1853 uint32_t x = *i / k; |
| 1903 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); | 1854 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); |
| 1904 } | |
| 1905 } | 1855 } |
| 1906 } | 1856 } |
| 1907 } | 1857 } |
| 1908 | 1858 |
| 1909 | 1859 |
| 1910 TEST(NumberDivide_BadConstants) { | 1860 TEST(NumberDivide_BadConstants) { |
| 1911 { | 1861 { |
| 1912 TestingGraph t(Type::Signed32()); | 1862 TestingGraph t(Type::Signed32()); |
| 1913 Node* k = t.jsgraph.Constant(-1); | 1863 Node* k = t.jsgraph.Constant(-1); |
| 1914 Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k); | 1864 Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1965 int32_t constants[] = {-100, -10, -1, 1, 2, 100, 1000, 1024, 2048}; | 1915 int32_t constants[] = {-100, -10, -1, 1, 2, 100, 1000, 1024, 2048}; |
| 1966 | 1916 |
| 1967 for (size_t i = 0; i < arraysize(constants); i++) { | 1917 for (size_t i = 0; i < arraysize(constants); i++) { |
| 1968 int32_t k = constants[i]; | 1918 int32_t k = constants[i]; |
| 1969 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 1919 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 1970 Node* num = t.NumberToInt32(t.Parameter(0)); | 1920 Node* num = t.NumberToInt32(t.Parameter(0)); |
| 1971 Node* mod = t.NumberModulus(num, t.jsgraph.Constant(k)); | 1921 Node* mod = t.NumberModulus(num, t.jsgraph.Constant(k)); |
| 1972 Node* trunc = t.NumberToInt32(mod); | 1922 Node* trunc = t.NumberToInt32(mod); |
| 1973 t.Return(trunc); | 1923 t.Return(trunc); |
| 1974 | 1924 |
| 1975 if (Pipeline::SupportedTarget()) { | |
| 1976 t.LowerAllNodesAndLowerChanges(); | 1925 t.LowerAllNodesAndLowerChanges(); |
| 1977 t.GenerateCode(); | 1926 t.GenerateCode(); |
| 1978 | 1927 |
| 1979 FOR_INT32_INPUTS(i) { | 1928 FOR_INT32_INPUTS(i) { |
| 1980 if (*i == INT_MAX) continue; // exclude max int. | 1929 if (*i == INT_MAX) continue; // exclude max int. |
| 1981 int32_t x = DoubleToInt32(std::fmod(static_cast<double>(*i), k)); | 1930 int32_t x = DoubleToInt32(std::fmod(static_cast<double>(*i), k)); |
| 1982 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); | 1931 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); |
| 1983 } | |
| 1984 } | 1932 } |
| 1985 } | 1933 } |
| 1986 } | 1934 } |
| 1987 | 1935 |
| 1988 | 1936 |
| 1989 TEST(NumberModulus_TruncatingToUint32) { | 1937 TEST(NumberModulus_TruncatingToUint32) { |
| 1990 double constants[] = {1, 3, 100, 1000, 100998348}; | 1938 double constants[] = {1, 3, 100, 1000, 100998348}; |
| 1991 | 1939 |
| 1992 for (size_t i = 0; i < arraysize(constants); i++) { | 1940 for (size_t i = 0; i < arraysize(constants); i++) { |
| 1993 TestingGraph t(Type::Unsigned32()); | 1941 TestingGraph t(Type::Unsigned32()); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2007 | 1955 |
| 2008 for (size_t i = 0; i < arraysize(constants); i++) { | 1956 for (size_t i = 0; i < arraysize(constants); i++) { |
| 2009 uint32_t k = constants[i]; | 1957 uint32_t k = constants[i]; |
| 2010 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 1958 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 2011 Node* num = t.NumberToUint32(t.Parameter(0)); | 1959 Node* num = t.NumberToUint32(t.Parameter(0)); |
| 2012 Node* mod = | 1960 Node* mod = |
| 2013 t.NumberModulus(num, t.jsgraph.Constant(static_cast<double>(k))); | 1961 t.NumberModulus(num, t.jsgraph.Constant(static_cast<double>(k))); |
| 2014 Node* trunc = t.NumberToUint32(mod); | 1962 Node* trunc = t.NumberToUint32(mod); |
| 2015 t.Return(trunc); | 1963 t.Return(trunc); |
| 2016 | 1964 |
| 2017 if (Pipeline::SupportedTarget()) { | |
| 2018 t.LowerAllNodesAndLowerChanges(); | 1965 t.LowerAllNodesAndLowerChanges(); |
| 2019 t.GenerateCode(); | 1966 t.GenerateCode(); |
| 2020 | 1967 |
| 2021 FOR_UINT32_INPUTS(i) { | 1968 FOR_UINT32_INPUTS(i) { |
| 2022 uint32_t x = *i % k; | 1969 uint32_t x = *i % k; |
| 2023 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); | 1970 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); |
| 2024 } | |
| 2025 } | 1971 } |
| 2026 } | 1972 } |
| 2027 } | 1973 } |
| 2028 | 1974 |
| 2029 | 1975 |
| 2030 TEST(NumberModulus_Int32) { | 1976 TEST(NumberModulus_Int32) { |
| 2031 int32_t constants[] = {-100, -10, 1, 4, 100, 1000}; | 1977 int32_t constants[] = {-100, -10, 1, 4, 100, 1000}; |
| 2032 | 1978 |
| 2033 for (size_t i = 0; i < arraysize(constants); i++) { | 1979 for (size_t i = 0; i < arraysize(constants); i++) { |
| 2034 TestingGraph t(Type::Signed32()); | 1980 TestingGraph t(Type::Signed32()); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2096 Bounds phi_bounds = Bounds::Either(Bounds(d.arg1), Bounds(d.arg2), z); | 2042 Bounds phi_bounds = Bounds::Either(Bounds(d.arg1), Bounds(d.arg2), z); |
| 2097 NodeProperties::SetBounds(phi, phi_bounds); | 2043 NodeProperties::SetBounds(phi, phi_bounds); |
| 2098 | 2044 |
| 2099 Node* use = t.Use(phi, d.use); | 2045 Node* use = t.Use(phi, d.use); |
| 2100 t.Return(use); | 2046 t.Return(use); |
| 2101 t.Lower(); | 2047 t.Lower(); |
| 2102 | 2048 |
| 2103 CHECK_EQ(d.expected, OpParameter<MachineType>(phi)); | 2049 CHECK_EQ(d.expected, OpParameter<MachineType>(phi)); |
| 2104 } | 2050 } |
| 2105 } | 2051 } |
| OLD | NEW |