| 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 // TODO(jochen): Remove this after the setting is turned on globally. | 5 // TODO(jochen): Remove this after the setting is turned on globally. |
| 6 #define V8_IMMINENT_DEPRECATION_WARNINGS | 6 #define V8_IMMINENT_DEPRECATION_WARNINGS |
| 7 | 7 |
| 8 #include <limits> | 8 #include <limits> |
| 9 | 9 |
| 10 #include "src/compiler/access-builder.h" | 10 #include "src/compiler/access-builder.h" |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 SimplifiedLoweringTester<Object*> t; | 104 SimplifiedLoweringTester<Object*> t; |
| 105 FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(), | 105 FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(), |
| 106 kMachFloat64}; | 106 kMachFloat64}; |
| 107 Node* loaded = t.LoadField(load, t.PointerConstant(&input)); | 107 Node* loaded = t.LoadField(load, t.PointerConstant(&input)); |
| 108 NodeProperties::SetType(loaded, Type::Number()); | 108 NodeProperties::SetType(loaded, Type::Number()); |
| 109 Node* convert = t.NumberToInt32(loaded); | 109 Node* convert = t.NumberToInt32(loaded); |
| 110 FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Signed32(), | 110 FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Signed32(), |
| 111 kMachInt32}; | 111 kMachInt32}; |
| 112 t.StoreField(store, t.PointerConstant(&result), convert); | 112 t.StoreField(store, t.PointerConstant(&result), convert); |
| 113 t.Return(t.jsgraph.TrueConstant()); | 113 t.Return(t.jsgraph.TrueConstant()); |
| 114 t.LowerAllNodes(); | 114 t.LowerAllNodesAndLowerChanges(); |
| 115 t.GenerateCode(); | 115 t.GenerateCode(); |
| 116 | 116 |
| 117 FOR_FLOAT64_INPUTS(i) { | 117 FOR_FLOAT64_INPUTS(i) { |
| 118 input = *i; | 118 input = *i; |
| 119 int32_t expected = DoubleToInt32(*i); | 119 int32_t expected = DoubleToInt32(*i); |
| 120 t.Call(); | 120 t.Call(); |
| 121 CHECK_EQ(expected, result); | 121 CHECK_EQ(expected, result); |
| 122 } | 122 } |
| 123 } | 123 } |
| 124 | 124 |
| 125 | 125 |
| 126 // TODO(titzer): test tagged representation for input to NumberToUint32. | 126 // TODO(titzer): test tagged representation for input to NumberToUint32. |
| 127 TEST(RunNumberToUint32_float64) { | 127 TEST(RunNumberToUint32_float64) { |
| 128 // TODO(titzer): explicit load/stores here are only because of representations | 128 // TODO(titzer): explicit load/stores here are only because of representations |
| 129 double input; | 129 double input; |
| 130 uint32_t result; | 130 uint32_t result; |
| 131 SimplifiedLoweringTester<Object*> t; | 131 SimplifiedLoweringTester<Object*> t; |
| 132 FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(), | 132 FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(), |
| 133 kMachFloat64}; | 133 kMachFloat64}; |
| 134 Node* loaded = t.LoadField(load, t.PointerConstant(&input)); | 134 Node* loaded = t.LoadField(load, t.PointerConstant(&input)); |
| 135 NodeProperties::SetType(loaded, Type::Number()); | 135 NodeProperties::SetType(loaded, Type::Number()); |
| 136 Node* convert = t.NumberToUint32(loaded); | 136 Node* convert = t.NumberToUint32(loaded); |
| 137 FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Unsigned32(), | 137 FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Unsigned32(), |
| 138 kMachUint32}; | 138 kMachUint32}; |
| 139 t.StoreField(store, t.PointerConstant(&result), convert); | 139 t.StoreField(store, t.PointerConstant(&result), convert); |
| 140 t.Return(t.jsgraph.TrueConstant()); | 140 t.Return(t.jsgraph.TrueConstant()); |
| 141 t.LowerAllNodes(); | 141 t.LowerAllNodesAndLowerChanges(); |
| 142 t.GenerateCode(); | 142 t.GenerateCode(); |
| 143 | 143 |
| 144 FOR_FLOAT64_INPUTS(i) { | 144 FOR_FLOAT64_INPUTS(i) { |
| 145 input = *i; | 145 input = *i; |
| 146 uint32_t expected = DoubleToUint32(*i); | 146 uint32_t expected = DoubleToUint32(*i); |
| 147 t.Call(); | 147 t.Call(); |
| 148 CHECK_EQ(static_cast<int32_t>(expected), static_cast<int32_t>(result)); | 148 CHECK_EQ(static_cast<int32_t>(expected), static_cast<int32_t>(result)); |
| 149 } | 149 } |
| 150 } | 150 } |
| 151 | 151 |
| 152 | 152 |
| 153 // Create a simple JSObject with a unique map. | 153 // Create a simple JSObject with a unique map. |
| 154 static Handle<JSObject> TestObject() { | 154 static Handle<JSObject> TestObject() { |
| 155 static int index = 0; | 155 static int index = 0; |
| 156 char buffer[50]; | 156 char buffer[50]; |
| 157 v8::base::OS::SNPrintF(buffer, 50, "({'a_%d':1})", index++); | 157 v8::base::OS::SNPrintF(buffer, 50, "({'a_%d':1})", index++); |
| 158 return Handle<JSObject>::cast(v8::Utils::OpenHandle(*CompileRun(buffer))); | 158 return Handle<JSObject>::cast(v8::Utils::OpenHandle(*CompileRun(buffer))); |
| 159 } | 159 } |
| 160 | 160 |
| 161 | 161 |
| 162 TEST(RunLoadMap) { | 162 TEST(RunLoadMap) { |
| 163 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 163 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 164 FieldAccess access = AccessBuilder::ForMap(); | 164 FieldAccess access = AccessBuilder::ForMap(); |
| 165 Node* load = t.LoadField(access, t.Parameter(0)); | 165 Node* load = t.LoadField(access, t.Parameter(0)); |
| 166 t.Return(load); | 166 t.Return(load); |
| 167 | 167 |
| 168 t.LowerAllNodes(); | 168 t.LowerAllNodesAndLowerChanges(); |
| 169 t.GenerateCode(); | 169 t.GenerateCode(); |
| 170 | 170 |
| 171 Handle<JSObject> src = TestObject(); | 171 Handle<JSObject> src = TestObject(); |
| 172 Handle<Map> src_map(src->map()); | 172 Handle<Map> src_map(src->map()); |
| 173 Object* result = t.Call(*src); // TODO(titzer): raw pointers in call | 173 Object* result = t.Call(*src); // TODO(titzer): raw pointers in call |
| 174 CHECK_EQ(*src_map, result); | 174 CHECK_EQ(*src_map, result); |
| 175 } | 175 } |
| 176 | 176 |
| 177 | 177 |
| 178 TEST(RunStoreMap) { | 178 TEST(RunStoreMap) { |
| 179 SimplifiedLoweringTester<int32_t> t(kMachAnyTagged, kMachAnyTagged); | 179 SimplifiedLoweringTester<int32_t> t(kMachAnyTagged, kMachAnyTagged); |
| 180 FieldAccess access = AccessBuilder::ForMap(); | 180 FieldAccess access = AccessBuilder::ForMap(); |
| 181 t.StoreField(access, t.Parameter(1), t.Parameter(0)); | 181 t.StoreField(access, t.Parameter(1), t.Parameter(0)); |
| 182 t.Return(t.jsgraph.TrueConstant()); | 182 t.Return(t.jsgraph.TrueConstant()); |
| 183 | 183 |
| 184 t.LowerAllNodes(); | 184 t.LowerAllNodesAndLowerChanges(); |
| 185 t.GenerateCode(); | 185 t.GenerateCode(); |
| 186 | 186 |
| 187 Handle<JSObject> src = TestObject(); | 187 Handle<JSObject> src = TestObject(); |
| 188 Handle<Map> src_map(src->map()); | 188 Handle<Map> src_map(src->map()); |
| 189 Handle<JSObject> dst = TestObject(); | 189 Handle<JSObject> dst = TestObject(); |
| 190 CHECK(src->map() != dst->map()); | 190 CHECK(src->map() != dst->map()); |
| 191 t.Call(*src_map, *dst); // TODO(titzer): raw pointers in call | 191 t.Call(*src_map, *dst); // TODO(titzer): raw pointers in call |
| 192 CHECK(*src_map == dst->map()); | 192 CHECK(*src_map == dst->map()); |
| 193 } | 193 } |
| 194 | 194 |
| 195 | 195 |
| 196 TEST(RunLoadProperties) { | 196 TEST(RunLoadProperties) { |
| 197 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 197 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 198 FieldAccess access = AccessBuilder::ForJSObjectProperties(); | 198 FieldAccess access = AccessBuilder::ForJSObjectProperties(); |
| 199 Node* load = t.LoadField(access, t.Parameter(0)); | 199 Node* load = t.LoadField(access, t.Parameter(0)); |
| 200 t.Return(load); | 200 t.Return(load); |
| 201 | 201 |
| 202 t.LowerAllNodes(); | 202 t.LowerAllNodesAndLowerChanges(); |
| 203 t.GenerateCode(); | 203 t.GenerateCode(); |
| 204 | 204 |
| 205 Handle<JSObject> src = TestObject(); | 205 Handle<JSObject> src = TestObject(); |
| 206 Handle<FixedArray> src_props(src->properties()); | 206 Handle<FixedArray> src_props(src->properties()); |
| 207 Object* result = t.Call(*src); // TODO(titzer): raw pointers in call | 207 Object* result = t.Call(*src); // TODO(titzer): raw pointers in call |
| 208 CHECK_EQ(*src_props, result); | 208 CHECK_EQ(*src_props, result); |
| 209 } | 209 } |
| 210 | 210 |
| 211 | 211 |
| 212 TEST(RunLoadStoreMap) { | 212 TEST(RunLoadStoreMap) { |
| 213 SimplifiedLoweringTester<Object*> t(kMachAnyTagged, kMachAnyTagged); | 213 SimplifiedLoweringTester<Object*> t(kMachAnyTagged, kMachAnyTagged); |
| 214 FieldAccess access = AccessBuilder::ForMap(); | 214 FieldAccess access = AccessBuilder::ForMap(); |
| 215 Node* load = t.LoadField(access, t.Parameter(0)); | 215 Node* load = t.LoadField(access, t.Parameter(0)); |
| 216 t.StoreField(access, t.Parameter(1), load); | 216 t.StoreField(access, t.Parameter(1), load); |
| 217 t.Return(load); | 217 t.Return(load); |
| 218 | 218 |
| 219 t.LowerAllNodes(); | 219 t.LowerAllNodesAndLowerChanges(); |
| 220 t.GenerateCode(); | 220 t.GenerateCode(); |
| 221 | 221 |
| 222 Handle<JSObject> src = TestObject(); | 222 Handle<JSObject> src = TestObject(); |
| 223 Handle<Map> src_map(src->map()); | 223 Handle<Map> src_map(src->map()); |
| 224 Handle<JSObject> dst = TestObject(); | 224 Handle<JSObject> dst = TestObject(); |
| 225 CHECK(src->map() != dst->map()); | 225 CHECK(src->map() != dst->map()); |
| 226 Object* result = t.Call(*src, *dst); // TODO(titzer): raw pointers in call | 226 Object* result = t.Call(*src, *dst); // TODO(titzer): raw pointers in call |
| 227 CHECK(result->IsMap()); | 227 CHECK(result->IsMap()); |
| 228 CHECK_EQ(*src_map, result); | 228 CHECK_EQ(*src_map, result); |
| 229 CHECK(*src_map == dst->map()); | 229 CHECK(*src_map == dst->map()); |
| 230 } | 230 } |
| 231 | 231 |
| 232 | 232 |
| 233 TEST(RunLoadStoreFixedArrayIndex) { | 233 TEST(RunLoadStoreFixedArrayIndex) { |
| 234 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 234 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 235 ElementAccess access = AccessBuilder::ForFixedArrayElement(); | 235 ElementAccess access = AccessBuilder::ForFixedArrayElement(); |
| 236 Node* load = t.LoadElement(access, t.Parameter(0), t.Int32Constant(0)); | 236 Node* load = t.LoadElement(access, t.Parameter(0), t.Int32Constant(0)); |
| 237 t.StoreElement(access, t.Parameter(0), t.Int32Constant(1), load); | 237 t.StoreElement(access, t.Parameter(0), t.Int32Constant(1), load); |
| 238 t.Return(load); | 238 t.Return(load); |
| 239 | 239 |
| 240 t.LowerAllNodes(); | 240 t.LowerAllNodesAndLowerChanges(); |
| 241 t.GenerateCode(); | 241 t.GenerateCode(); |
| 242 | 242 |
| 243 Handle<FixedArray> array = t.factory()->NewFixedArray(2); | 243 Handle<FixedArray> array = t.factory()->NewFixedArray(2); |
| 244 Handle<JSObject> src = TestObject(); | 244 Handle<JSObject> src = TestObject(); |
| 245 Handle<JSObject> dst = TestObject(); | 245 Handle<JSObject> dst = TestObject(); |
| 246 array->set(0, *src); | 246 array->set(0, *src); |
| 247 array->set(1, *dst); | 247 array->set(1, *dst); |
| 248 Object* result = t.Call(*array); | 248 Object* result = t.Call(*array); |
| 249 CHECK_EQ(*src, result); | 249 CHECK_EQ(*src, result); |
| 250 CHECK_EQ(*src, array->get(0)); | 250 CHECK_EQ(*src, array->get(0)); |
| 251 CHECK_EQ(*src, array->get(1)); | 251 CHECK_EQ(*src, array->get(1)); |
| 252 } | 252 } |
| 253 | 253 |
| 254 | 254 |
| 255 TEST(RunLoadStoreArrayBuffer) { | 255 TEST(RunLoadStoreArrayBuffer) { |
| 256 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 256 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 257 const int index = 12; | 257 const int index = 12; |
| 258 const int array_length = 2 * index; | 258 const int array_length = 2 * index; |
| 259 ElementAccess buffer_access = | 259 ElementAccess buffer_access = |
| 260 AccessBuilder::ForTypedArrayElement(kExternalInt8Array, true); | 260 AccessBuilder::ForTypedArrayElement(kExternalInt8Array, true); |
| 261 Node* backing_store = t.LoadField( | 261 Node* backing_store = t.LoadField( |
| 262 AccessBuilder::ForJSArrayBufferBackingStore(), t.Parameter(0)); | 262 AccessBuilder::ForJSArrayBufferBackingStore(), t.Parameter(0)); |
| 263 Node* load = | 263 Node* load = |
| 264 t.LoadElement(buffer_access, backing_store, t.Int32Constant(index)); | 264 t.LoadElement(buffer_access, backing_store, t.Int32Constant(index)); |
| 265 t.StoreElement(buffer_access, backing_store, t.Int32Constant(index + 1), | 265 t.StoreElement(buffer_access, backing_store, t.Int32Constant(index + 1), |
| 266 load); | 266 load); |
| 267 t.Return(t.jsgraph.TrueConstant()); | 267 t.Return(t.jsgraph.TrueConstant()); |
| 268 | 268 |
| 269 t.LowerAllNodes(); | 269 t.LowerAllNodesAndLowerChanges(); |
| 270 t.GenerateCode(); | 270 t.GenerateCode(); |
| 271 | 271 |
| 272 Handle<JSArrayBuffer> array = t.factory()->NewJSArrayBuffer(); | 272 Handle<JSArrayBuffer> array = t.factory()->NewJSArrayBuffer(); |
| 273 JSArrayBuffer::SetupAllocatingData(array, t.isolate(), array_length); | 273 JSArrayBuffer::SetupAllocatingData(array, t.isolate(), array_length); |
| 274 uint8_t* data = reinterpret_cast<uint8_t*>(array->backing_store()); | 274 uint8_t* data = reinterpret_cast<uint8_t*>(array->backing_store()); |
| 275 for (int i = 0; i < array_length; i++) { | 275 for (int i = 0; i < array_length; i++) { |
| 276 data[i] = i; | 276 data[i] = i; |
| 277 } | 277 } |
| 278 | 278 |
| 279 // TODO(titzer): raw pointers in call | 279 // TODO(titzer): raw pointers in call |
| (...skipping 11 matching lines...) Expand all Loading... |
| 291 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3)}; | 291 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3)}; |
| 292 | 292 |
| 293 for (size_t i = 0; i < arraysize(smis); i++) { | 293 for (size_t i = 0; i < arraysize(smis); i++) { |
| 294 int offset = static_cast<int>(i * sizeof(Smi*)); | 294 int offset = static_cast<int>(i * sizeof(Smi*)); |
| 295 FieldAccess access = {kUntaggedBase, offset, Handle<Name>(), | 295 FieldAccess access = {kUntaggedBase, offset, Handle<Name>(), |
| 296 Type::Integral32(), kMachAnyTagged}; | 296 Type::Integral32(), kMachAnyTagged}; |
| 297 | 297 |
| 298 SimplifiedLoweringTester<Object*> t; | 298 SimplifiedLoweringTester<Object*> t; |
| 299 Node* load = t.LoadField(access, t.PointerConstant(smis)); | 299 Node* load = t.LoadField(access, t.PointerConstant(smis)); |
| 300 t.Return(load); | 300 t.Return(load); |
| 301 t.LowerAllNodes(); | 301 t.LowerAllNodesAndLowerChanges(); |
| 302 | 302 |
| 303 for (int j = -5; j <= 5; j++) { | 303 for (int j = -5; j <= 5; j++) { |
| 304 Smi* expected = Smi::FromInt(j); | 304 Smi* expected = Smi::FromInt(j); |
| 305 smis[i] = expected; | 305 smis[i] = expected; |
| 306 CHECK_EQ(expected, t.Call()); | 306 CHECK_EQ(expected, t.Call()); |
| 307 } | 307 } |
| 308 } | 308 } |
| 309 } | 309 } |
| 310 | 310 |
| 311 | 311 |
| 312 TEST(RunStoreFieldToUntaggedBase) { | 312 TEST(RunStoreFieldToUntaggedBase) { |
| 313 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3)}; | 313 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3)}; |
| 314 | 314 |
| 315 for (size_t i = 0; i < arraysize(smis); i++) { | 315 for (size_t i = 0; i < arraysize(smis); i++) { |
| 316 int offset = static_cast<int>(i * sizeof(Smi*)); | 316 int offset = static_cast<int>(i * sizeof(Smi*)); |
| 317 FieldAccess access = {kUntaggedBase, offset, Handle<Name>(), | 317 FieldAccess access = {kUntaggedBase, offset, Handle<Name>(), |
| 318 Type::Integral32(), kMachAnyTagged}; | 318 Type::Integral32(), kMachAnyTagged}; |
| 319 | 319 |
| 320 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 320 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 321 Node* p0 = t.Parameter(0); | 321 Node* p0 = t.Parameter(0); |
| 322 t.StoreField(access, t.PointerConstant(smis), p0); | 322 t.StoreField(access, t.PointerConstant(smis), p0); |
| 323 t.Return(p0); | 323 t.Return(p0); |
| 324 t.LowerAllNodes(); | 324 t.LowerAllNodesAndLowerChanges(); |
| 325 | 325 |
| 326 for (int j = -5; j <= 5; j++) { | 326 for (int j = -5; j <= 5; j++) { |
| 327 Smi* expected = Smi::FromInt(j); | 327 Smi* expected = Smi::FromInt(j); |
| 328 smis[i] = Smi::FromInt(-100); | 328 smis[i] = Smi::FromInt(-100); |
| 329 CHECK_EQ(expected, t.Call(expected)); | 329 CHECK_EQ(expected, t.Call(expected)); |
| 330 CHECK_EQ(expected, smis[i]); | 330 CHECK_EQ(expected, smis[i]); |
| 331 } | 331 } |
| 332 } | 332 } |
| 333 } | 333 } |
| 334 | 334 |
| 335 | 335 |
| 336 TEST(RunLoadElementFromUntaggedBase) { | 336 TEST(RunLoadElementFromUntaggedBase) { |
| 337 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), | 337 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), |
| 338 Smi::FromInt(4), Smi::FromInt(5)}; | 338 Smi::FromInt(4), Smi::FromInt(5)}; |
| 339 | 339 |
| 340 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes | 340 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes |
| 341 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index | 341 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index |
| 342 int offset = static_cast<int>(i * sizeof(Smi*)); | 342 int offset = static_cast<int>(i * sizeof(Smi*)); |
| 343 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), | 343 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), |
| 344 kMachAnyTagged}; | 344 kMachAnyTagged}; |
| 345 | 345 |
| 346 SimplifiedLoweringTester<Object*> t; | 346 SimplifiedLoweringTester<Object*> t; |
| 347 Node* load = t.LoadElement(access, t.PointerConstant(smis), | 347 Node* load = t.LoadElement(access, t.PointerConstant(smis), |
| 348 t.Int32Constant(static_cast<int>(j))); | 348 t.Int32Constant(static_cast<int>(j))); |
| 349 t.Return(load); | 349 t.Return(load); |
| 350 t.LowerAllNodes(); | 350 t.LowerAllNodesAndLowerChanges(); |
| 351 | 351 |
| 352 for (int k = -5; k <= 5; k++) { | 352 for (int k = -5; k <= 5; k++) { |
| 353 Smi* expected = Smi::FromInt(k); | 353 Smi* expected = Smi::FromInt(k); |
| 354 smis[i + j] = expected; | 354 smis[i + j] = expected; |
| 355 CHECK_EQ(expected, t.Call()); | 355 CHECK_EQ(expected, t.Call()); |
| 356 } | 356 } |
| 357 } | 357 } |
| 358 } | 358 } |
| 359 } | 359 } |
| 360 | 360 |
| 361 | 361 |
| 362 TEST(RunStoreElementFromUntaggedBase) { | 362 TEST(RunStoreElementFromUntaggedBase) { |
| 363 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), | 363 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3), |
| 364 Smi::FromInt(4), Smi::FromInt(5)}; | 364 Smi::FromInt(4), Smi::FromInt(5)}; |
| 365 | 365 |
| 366 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes | 366 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes |
| 367 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index | 367 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index |
| 368 int offset = static_cast<int>(i * sizeof(Smi*)); | 368 int offset = static_cast<int>(i * sizeof(Smi*)); |
| 369 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), | 369 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(), |
| 370 kMachAnyTagged}; | 370 kMachAnyTagged}; |
| 371 | 371 |
| 372 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 372 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 373 Node* p0 = t.Parameter(0); | 373 Node* p0 = t.Parameter(0); |
| 374 t.StoreElement(access, t.PointerConstant(smis), | 374 t.StoreElement(access, t.PointerConstant(smis), |
| 375 t.Int32Constant(static_cast<int>(j)), p0); | 375 t.Int32Constant(static_cast<int>(j)), p0); |
| 376 t.Return(p0); | 376 t.Return(p0); |
| 377 t.LowerAllNodes(); | 377 t.LowerAllNodesAndLowerChanges(); |
| 378 | 378 |
| 379 for (int k = -5; k <= 5; k++) { | 379 for (int k = -5; k <= 5; k++) { |
| 380 Smi* expected = Smi::FromInt(k); | 380 Smi* expected = Smi::FromInt(k); |
| 381 smis[i + j] = Smi::FromInt(-100); | 381 smis[i + j] = Smi::FromInt(-100); |
| 382 CHECK_EQ(expected, t.Call(expected)); | 382 CHECK_EQ(expected, t.Call(expected)); |
| 383 CHECK_EQ(expected, smis[i + j]); | 383 CHECK_EQ(expected, smis[i + j]); |
| 384 } | 384 } |
| 385 | 385 |
| 386 // TODO(titzer): assert the contents of the array. | 386 // TODO(titzer): assert the contents of the array. |
| 387 } | 387 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 // a constant in the code. | 432 // a constant in the code. |
| 433 BoundsCheck(from_index); | 433 BoundsCheck(from_index); |
| 434 BoundsCheck(to_index); | 434 BoundsCheck(to_index); |
| 435 ElementAccess access = GetElementAccess(); | 435 ElementAccess access = GetElementAccess(); |
| 436 | 436 |
| 437 SimplifiedLoweringTester<Object*> t; | 437 SimplifiedLoweringTester<Object*> t; |
| 438 Node* ptr = GetBaseNode(&t); | 438 Node* ptr = GetBaseNode(&t); |
| 439 Node* load = t.LoadElement(access, ptr, t.Int32Constant(from_index)); | 439 Node* load = t.LoadElement(access, ptr, t.Int32Constant(from_index)); |
| 440 t.StoreElement(access, ptr, t.Int32Constant(to_index), load); | 440 t.StoreElement(access, ptr, t.Int32Constant(to_index), load); |
| 441 t.Return(t.jsgraph.TrueConstant()); | 441 t.Return(t.jsgraph.TrueConstant()); |
| 442 t.LowerAllNodes(); | 442 t.LowerAllNodesAndLowerChanges(); |
| 443 t.GenerateCode(); | 443 t.GenerateCode(); |
| 444 | 444 |
| 445 Object* result = t.Call(); | 445 Object* result = t.Call(); |
| 446 CHECK_EQ(t.isolate()->heap()->true_value(), result); | 446 CHECK_EQ(t.isolate()->heap()->true_value(), result); |
| 447 } | 447 } |
| 448 | 448 |
| 449 // Create and run code that copies the field in either {untagged_array} | 449 // Create and run code that copies the field in either {untagged_array} |
| 450 // or {tagged_array} at index {from_index} to index {to_index}. | 450 // or {tagged_array} at index {from_index} to index {to_index}. |
| 451 void RunCopyField(int from_index, int to_index) { | 451 void RunCopyField(int from_index, int to_index) { |
| 452 BoundsCheck(from_index); | 452 BoundsCheck(from_index); |
| 453 BoundsCheck(to_index); | 453 BoundsCheck(to_index); |
| 454 FieldAccess from_access = GetFieldAccess(from_index); | 454 FieldAccess from_access = GetFieldAccess(from_index); |
| 455 FieldAccess to_access = GetFieldAccess(to_index); | 455 FieldAccess to_access = GetFieldAccess(to_index); |
| 456 | 456 |
| 457 SimplifiedLoweringTester<Object*> t; | 457 SimplifiedLoweringTester<Object*> t; |
| 458 Node* ptr = GetBaseNode(&t); | 458 Node* ptr = GetBaseNode(&t); |
| 459 Node* load = t.LoadField(from_access, ptr); | 459 Node* load = t.LoadField(from_access, ptr); |
| 460 t.StoreField(to_access, ptr, load); | 460 t.StoreField(to_access, ptr, load); |
| 461 t.Return(t.jsgraph.TrueConstant()); | 461 t.Return(t.jsgraph.TrueConstant()); |
| 462 t.LowerAllNodes(); | 462 t.LowerAllNodesAndLowerChanges(); |
| 463 t.GenerateCode(); | 463 t.GenerateCode(); |
| 464 | 464 |
| 465 Object* result = t.Call(); | 465 Object* result = t.Call(); |
| 466 CHECK_EQ(t.isolate()->heap()->true_value(), result); | 466 CHECK_EQ(t.isolate()->heap()->true_value(), result); |
| 467 } | 467 } |
| 468 | 468 |
| 469 // Create and run code that copies the elements from {this} to {that}. | 469 // Create and run code that copies the elements from {this} to {that}. |
| 470 void RunCopyElements(AccessTester<E>* that) { | 470 void RunCopyElements(AccessTester<E>* that) { |
| 471 // TODO(titzer): Rewrite this test without StructuredGraphBuilder support. | 471 // TODO(titzer): Rewrite this test without StructuredGraphBuilder support. |
| 472 #if 0 | 472 #if 0 |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 644 | 644 |
| 645 for (size_t i = 0; i < arraysize(flag); i++) { | 645 for (size_t i = 0; i < arraysize(flag); i++) { |
| 646 SimplifiedLoweringTester<HeapObject*> t; | 646 SimplifiedLoweringTester<HeapObject*> t; |
| 647 FieldAccess access = AccessBuilder::ForMap(); | 647 FieldAccess access = AccessBuilder::ForMap(); |
| 648 Node* size = t.jsgraph.Constant(HeapNumber::kSize); | 648 Node* size = t.jsgraph.Constant(HeapNumber::kSize); |
| 649 Node* alloc = t.NewNode(t.simplified()->Allocate(flag[i]), size); | 649 Node* alloc = t.NewNode(t.simplified()->Allocate(flag[i]), size); |
| 650 Node* map = t.jsgraph.Constant(t.factory()->heap_number_map()); | 650 Node* map = t.jsgraph.Constant(t.factory()->heap_number_map()); |
| 651 t.StoreField(access, alloc, map); | 651 t.StoreField(access, alloc, map); |
| 652 t.Return(alloc); | 652 t.Return(alloc); |
| 653 | 653 |
| 654 t.LowerAllNodes(); | 654 t.LowerAllNodesAndLowerChanges(); |
| 655 t.GenerateCode(); | 655 t.GenerateCode(); |
| 656 | 656 |
| 657 HeapObject* result = t.CallWithPotentialGC<HeapObject>(); | 657 HeapObject* result = t.CallWithPotentialGC<HeapObject>(); |
| 658 CHECK(t.heap()->new_space()->Contains(result) || flag[i] == TENURED); | 658 CHECK(t.heap()->new_space()->Contains(result) || flag[i] == TENURED); |
| 659 CHECK(t.heap()->old_space()->Contains(result) || flag[i] == NOT_TENURED); | 659 CHECK(t.heap()->old_space()->Contains(result) || flag[i] == NOT_TENURED); |
| 660 CHECK(result->IsHeapNumber()); | 660 CHECK(result->IsHeapNumber()); |
| 661 } | 661 } |
| 662 } | 662 } |
| 663 | 663 |
| 664 | 664 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 675 Node* end; | 675 Node* end; |
| 676 Node* ret; | 676 Node* ret; |
| 677 | 677 |
| 678 explicit TestingGraph(Type* p0_type, Type* p1_type = Type::None(), | 678 explicit TestingGraph(Type* p0_type, Type* p1_type = Type::None(), |
| 679 Type* p2_type = Type::None()) | 679 Type* p2_type = Type::None()) |
| 680 : GraphAndBuilders(main_zone()), | 680 : GraphAndBuilders(main_zone()), |
| 681 typer(main_isolate(), graph()), | 681 typer(main_isolate(), graph()), |
| 682 javascript(main_zone()), | 682 javascript(main_zone()), |
| 683 jsgraph(main_isolate(), graph(), common(), &javascript, simplified(), | 683 jsgraph(main_isolate(), graph(), common(), &javascript, simplified(), |
| 684 machine()) { | 684 machine()) { |
| 685 start = graph()->NewNode(common()->Start(2)); | 685 start = graph()->NewNode(common()->Start(4)); |
| 686 graph()->SetStart(start); | 686 graph()->SetStart(start); |
| 687 ret = | 687 ret = |
| 688 graph()->NewNode(common()->Return(), jsgraph.Constant(0), start, start); | 688 graph()->NewNode(common()->Return(), jsgraph.Constant(0), start, start); |
| 689 end = graph()->NewNode(common()->End(1), ret); | 689 end = graph()->NewNode(common()->End(1), ret); |
| 690 graph()->SetEnd(end); | 690 graph()->SetEnd(end); |
| 691 p0 = graph()->NewNode(common()->Parameter(0), start); | 691 p0 = graph()->NewNode(common()->Parameter(0), start); |
| 692 p1 = graph()->NewNode(common()->Parameter(1), start); | 692 p1 = graph()->NewNode(common()->Parameter(1), start); |
| 693 p2 = graph()->NewNode(common()->Parameter(2), start); | 693 p2 = graph()->NewNode(common()->Parameter(2), start); |
| 694 typer.Run(); | 694 typer.Run(); |
| 695 NodeProperties::SetType(p0, p0_type); | 695 NodeProperties::SetType(p0, p0_type); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 716 Return(graph()->NewNode(trunc, node)); | 716 Return(graph()->NewNode(trunc, node)); |
| 717 Lower(); | 717 Lower(); |
| 718 CHECK_EQ(expected, node->opcode()); | 718 CHECK_EQ(expected, node->opcode()); |
| 719 } | 719 } |
| 720 | 720 |
| 721 void Lower() { | 721 void Lower() { |
| 722 SourcePositionTable table(jsgraph.graph()); | 722 SourcePositionTable table(jsgraph.graph()); |
| 723 SimplifiedLowering(&jsgraph, jsgraph.zone(), &table).LowerAllNodes(); | 723 SimplifiedLowering(&jsgraph, jsgraph.zone(), &table).LowerAllNodes(); |
| 724 } | 724 } |
| 725 | 725 |
| 726 void LowerAllNodesAndLowerChanges() { |
| 727 SourcePositionTable table(jsgraph.graph()); |
| 728 SimplifiedLowering(&jsgraph, jsgraph.zone(), &table).LowerAllNodes(); |
| 729 |
| 730 ChangeLowering lowering(&jsgraph); |
| 731 GraphReducer reducer(this->zone(), this->graph()); |
| 732 reducer.AddReducer(&lowering); |
| 733 reducer.ReduceGraph(); |
| 734 Verifier::Run(this->graph()); |
| 735 } |
| 736 |
| 726 // Inserts the node as the return value of the graph. | 737 // Inserts the node as the return value of the graph. |
| 727 Node* Return(Node* node) { | 738 Node* Return(Node* node) { |
| 728 ret->ReplaceInput(0, node); | 739 ret->ReplaceInput(0, node); |
| 729 return node; | 740 return node; |
| 730 } | 741 } |
| 731 | 742 |
| 732 // Inserts the node as the effect input to the return of the graph. | 743 // Inserts the node as the effect input to the return of the graph. |
| 733 void Effect(Node* node) { ret->ReplaceInput(1, node); } | 744 void Effect(Node* node) { ret->ReplaceInput(1, node); } |
| 734 | 745 |
| 735 Node* ExampleWithOutput(MachineType type) { | 746 Node* ExampleWithOutput(MachineType type) { |
| (...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1361 TestingGraph t(Type::Any(), Type::Signed32()); | 1372 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1362 | 1373 |
| 1363 for (size_t i = 0; i < arraysize(kMachineReps); i++) { | 1374 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
| 1364 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1375 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| 1365 Handle<Name>::null(), Type::Any(), kMachineReps[i]}; | 1376 Handle<Name>::null(), Type::Any(), kMachineReps[i]}; |
| 1366 | 1377 |
| 1367 Node* load = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, | 1378 Node* load = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, |
| 1368 t.start, t.start); | 1379 t.start, t.start); |
| 1369 Node* use = t.Use(load, kMachineReps[i]); | 1380 Node* use = t.Use(load, kMachineReps[i]); |
| 1370 t.Return(use); | 1381 t.Return(use); |
| 1371 t.Lower(); | 1382 t.LowerAllNodesAndLowerChanges(); |
| 1372 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1383 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
| 1373 CHECK_EQ(t.p0, load->InputAt(0)); | 1384 CHECK_EQ(t.p0, load->InputAt(0)); |
| 1374 CheckFieldAccessArithmetic(access, load); | 1385 CheckFieldAccessArithmetic(access, load); |
| 1375 | 1386 |
| 1376 MachineType rep = OpParameter<MachineType>(load); | 1387 MachineType rep = OpParameter<MachineType>(load); |
| 1377 CHECK_EQ(kMachineReps[i], rep); | 1388 CHECK_EQ(kMachineReps[i], rep); |
| 1378 } | 1389 } |
| 1379 } | 1390 } |
| 1380 | 1391 |
| 1381 | 1392 |
| 1382 TEST(LowerStoreField_to_store) { | 1393 TEST(LowerStoreField_to_store) { |
| 1383 { | 1394 { |
| 1384 TestingGraph t(Type::Any(), Type::Signed32()); | 1395 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1385 | 1396 |
| 1386 for (size_t i = 0; i < arraysize(kMachineReps); i++) { | 1397 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
| 1387 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1398 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| 1388 Handle<Name>::null(), Type::Any(), kMachineReps[i]}; | 1399 Handle<Name>::null(), Type::Any(), kMachineReps[i]}; |
| 1389 | 1400 |
| 1390 | 1401 |
| 1391 Node* val = t.ExampleWithOutput(kMachineReps[i]); | 1402 Node* val = t.ExampleWithOutput(kMachineReps[i]); |
| 1392 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, | 1403 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, |
| 1393 val, t.start, t.start); | 1404 val, t.start, t.start); |
| 1394 t.Effect(store); | 1405 t.Effect(store); |
| 1395 t.Lower(); | 1406 t.LowerAllNodesAndLowerChanges(); |
| 1396 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1407 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
| 1397 CHECK_EQ(val, store->InputAt(2)); | 1408 CHECK_EQ(val, store->InputAt(2)); |
| 1398 CheckFieldAccessArithmetic(access, store); | 1409 CheckFieldAccessArithmetic(access, store); |
| 1399 | 1410 |
| 1400 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); | 1411 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); |
| 1401 if (kMachineReps[i] & kRepTagged) { | 1412 if (kMachineReps[i] & kRepTagged) { |
| 1402 CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); | 1413 CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); |
| 1403 } | 1414 } |
| 1404 CHECK_EQ(kMachineReps[i], rep.machine_type()); | 1415 CHECK_EQ(kMachineReps[i], rep.machine_type()); |
| 1405 } | 1416 } |
| 1406 } | 1417 } |
| 1407 { | 1418 { |
| 1408 HandleAndZoneScope scope; | 1419 HandleAndZoneScope scope; |
| 1409 Zone* z = scope.main_zone(); | 1420 Zone* z = scope.main_zone(); |
| 1410 TestingGraph t(Type::Any(), Type::Intersect(Type::SignedSmall(), | 1421 TestingGraph t(Type::Any(), Type::Intersect(Type::SignedSmall(), |
| 1411 Type::TaggedSigned(), z)); | 1422 Type::TaggedSigned(), z)); |
| 1412 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1423 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| 1413 Handle<Name>::null(), Type::Any(), kMachAnyTagged}; | 1424 Handle<Name>::null(), Type::Any(), kMachAnyTagged}; |
| 1414 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, | 1425 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, |
| 1415 t.p1, t.start, t.start); | 1426 t.p1, t.start, t.start); |
| 1416 t.Effect(store); | 1427 t.Effect(store); |
| 1417 t.Lower(); | 1428 t.LowerAllNodesAndLowerChanges(); |
| 1418 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1429 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
| 1419 CHECK_EQ(t.p1, store->InputAt(2)); | 1430 CHECK_EQ(t.p1, store->InputAt(2)); |
| 1420 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); | 1431 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); |
| 1421 CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind()); | 1432 CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind()); |
| 1422 } | 1433 } |
| 1423 } | 1434 } |
| 1424 | 1435 |
| 1425 | 1436 |
| 1426 TEST(LowerLoadElement_to_load) { | 1437 TEST(LowerLoadElement_to_load) { |
| 1427 TestingGraph t(Type::Any(), Type::Signed32()); | 1438 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1428 | 1439 |
| 1429 for (size_t i = 0; i < arraysize(kMachineReps); i++) { | 1440 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
| 1430 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1441 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| 1431 Type::Any(), kMachineReps[i]}; | 1442 Type::Any(), kMachineReps[i]}; |
| 1432 | 1443 |
| 1433 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, | 1444 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, |
| 1434 t.p1, t.start, t.start); | 1445 t.p1, t.start, t.start); |
| 1435 Node* use = t.Use(load, kMachineReps[i]); | 1446 Node* use = t.Use(load, kMachineReps[i]); |
| 1436 t.Return(use); | 1447 t.Return(use); |
| 1437 t.Lower(); | 1448 t.LowerAllNodesAndLowerChanges(); |
| 1438 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1449 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
| 1439 CHECK_EQ(t.p0, load->InputAt(0)); | 1450 CHECK_EQ(t.p0, load->InputAt(0)); |
| 1440 CheckElementAccessArithmetic(access, load); | 1451 CheckElementAccessArithmetic(access, load); |
| 1441 | 1452 |
| 1442 MachineType rep = OpParameter<MachineType>(load); | 1453 MachineType rep = OpParameter<MachineType>(load); |
| 1443 CHECK_EQ(kMachineReps[i], rep); | 1454 CHECK_EQ(kMachineReps[i], rep); |
| 1444 } | 1455 } |
| 1445 } | 1456 } |
| 1446 | 1457 |
| 1447 | 1458 |
| 1448 TEST(LowerStoreElement_to_store) { | 1459 TEST(LowerStoreElement_to_store) { |
| 1449 { | 1460 { |
| 1450 TestingGraph t(Type::Any(), Type::Signed32()); | 1461 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1451 | 1462 |
| 1452 for (size_t i = 0; i < arraysize(kMachineReps); i++) { | 1463 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
| 1453 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1464 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| 1454 Type::Any(), kMachineReps[i]}; | 1465 Type::Any(), kMachineReps[i]}; |
| 1455 | 1466 |
| 1456 Node* val = t.ExampleWithOutput(kMachineReps[i]); | 1467 Node* val = t.ExampleWithOutput(kMachineReps[i]); |
| 1457 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), | 1468 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), |
| 1458 t.p0, t.p1, val, t.start, t.start); | 1469 t.p0, t.p1, val, t.start, t.start); |
| 1459 t.Effect(store); | 1470 t.Effect(store); |
| 1460 t.Lower(); | 1471 t.LowerAllNodesAndLowerChanges(); |
| 1461 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1472 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
| 1462 CHECK_EQ(val, store->InputAt(2)); | 1473 CHECK_EQ(val, store->InputAt(2)); |
| 1463 CheckElementAccessArithmetic(access, store); | 1474 CheckElementAccessArithmetic(access, store); |
| 1464 | 1475 |
| 1465 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); | 1476 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); |
| 1466 if (kMachineReps[i] & kRepTagged) { | 1477 if (kMachineReps[i] & kRepTagged) { |
| 1467 CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); | 1478 CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); |
| 1468 } | 1479 } |
| 1469 CHECK_EQ(kMachineReps[i], rep.machine_type()); | 1480 CHECK_EQ(kMachineReps[i], rep.machine_type()); |
| 1470 } | 1481 } |
| 1471 } | 1482 } |
| 1472 { | 1483 { |
| 1473 HandleAndZoneScope scope; | 1484 HandleAndZoneScope scope; |
| 1474 Zone* z = scope.main_zone(); | 1485 Zone* z = scope.main_zone(); |
| 1475 TestingGraph t( | 1486 TestingGraph t( |
| 1476 Type::Any(), Type::Signed32(), | 1487 Type::Any(), Type::Signed32(), |
| 1477 Type::Intersect(Type::SignedSmall(), Type::TaggedSigned(), z)); | 1488 Type::Intersect(Type::SignedSmall(), Type::TaggedSigned(), z)); |
| 1478 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1489 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| 1479 Type::Any(), kMachAnyTagged}; | 1490 Type::Any(), kMachAnyTagged}; |
| 1480 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, | 1491 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, |
| 1481 t.p1, t.p2, t.start, t.start); | 1492 t.p1, t.p2, t.start, t.start); |
| 1482 t.Effect(store); | 1493 t.Effect(store); |
| 1483 t.Lower(); | 1494 t.LowerAllNodesAndLowerChanges(); |
| 1484 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1495 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
| 1485 CHECK_EQ(t.p2, store->InputAt(2)); | 1496 CHECK_EQ(t.p2, store->InputAt(2)); |
| 1486 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); | 1497 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); |
| 1487 CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind()); | 1498 CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind()); |
| 1488 } | 1499 } |
| 1489 } | 1500 } |
| 1490 | 1501 |
| 1491 | 1502 |
| 1492 TEST(InsertChangeForLoadElementIndex) { | 1503 TEST(InsertChangeForLoadElementIndex) { |
| 1493 // LoadElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length) => | 1504 // LoadElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length) => |
| 1494 // Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k)) | 1505 // Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k)) |
| 1495 TestingGraph t(Type::Any(), Type::Signed32()); | 1506 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1496 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), | 1507 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), |
| 1497 kMachAnyTagged}; | 1508 kMachAnyTagged}; |
| 1498 | 1509 |
| 1499 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, | 1510 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, |
| 1500 t.p1, t.start, t.start); | 1511 t.p1, t.start, t.start); |
| 1501 t.Return(load); | 1512 t.Return(load); |
| 1502 t.Lower(); | 1513 t.Lower(); |
| 1503 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1514 CHECK_EQ(IrOpcode::kLoadElement, load->opcode()); |
| 1504 CHECK_EQ(t.p0, load->InputAt(0)); | 1515 CHECK_EQ(t.p0, load->InputAt(0)); |
| 1505 | 1516 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, load->InputAt(1)); |
| 1506 Node* index = CheckElementAccessArithmetic(access, load); | |
| 1507 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, index); | |
| 1508 } | 1517 } |
| 1509 | 1518 |
| 1510 | 1519 |
| 1511 TEST(InsertChangeForStoreElementIndex) { | 1520 TEST(InsertChangeForStoreElementIndex) { |
| 1512 // StoreElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length, val) => | 1521 // StoreElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length, val) => |
| 1513 // Store(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k), val) | 1522 // Store(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k), val) |
| 1514 TestingGraph t(Type::Any(), Type::Signed32()); | 1523 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1515 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), | 1524 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), |
| 1516 kMachAnyTagged}; | 1525 kMachAnyTagged}; |
| 1517 | 1526 |
| 1518 Node* store = | 1527 Node* store = |
| 1519 t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, t.p1, | 1528 t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, t.p1, |
| 1520 t.jsgraph.TrueConstant(), t.start, t.start); | 1529 t.jsgraph.TrueConstant(), t.start, t.start); |
| 1521 t.Effect(store); | 1530 t.Effect(store); |
| 1522 t.Lower(); | 1531 t.Lower(); |
| 1523 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1532 CHECK_EQ(IrOpcode::kStoreElement, store->opcode()); |
| 1524 CHECK_EQ(t.p0, store->InputAt(0)); | 1533 CHECK_EQ(t.p0, store->InputAt(0)); |
| 1525 | 1534 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, store->InputAt(1)); |
| 1526 Node* index = CheckElementAccessArithmetic(access, store); | |
| 1527 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, index); | |
| 1528 } | 1535 } |
| 1529 | 1536 |
| 1530 | 1537 |
| 1531 TEST(InsertChangeForLoadElement) { | 1538 TEST(InsertChangeForLoadElement) { |
| 1532 // TODO(titzer): test all load/store representation change insertions. | 1539 // TODO(titzer): test all load/store representation change insertions. |
| 1533 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); | 1540 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); |
| 1534 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), | 1541 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), |
| 1535 kMachFloat64}; | 1542 kMachFloat64}; |
| 1536 | 1543 |
| 1537 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, | 1544 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, |
| 1538 t.p1, t.start, t.start); | 1545 t.p1, t.start, t.start); |
| 1539 t.Return(load); | 1546 t.Return(load); |
| 1540 t.Lower(); | 1547 t.Lower(); |
| 1541 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1548 CHECK_EQ(IrOpcode::kLoadElement, load->opcode()); |
| 1542 CHECK_EQ(t.p0, load->InputAt(0)); | 1549 CHECK_EQ(t.p0, load->InputAt(0)); |
| 1543 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); | 1550 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); |
| 1544 } | 1551 } |
| 1545 | 1552 |
| 1546 | 1553 |
| 1547 TEST(InsertChangeForLoadField) { | 1554 TEST(InsertChangeForLoadField) { |
| 1548 // TODO(titzer): test all load/store representation change insertions. | 1555 // TODO(titzer): test all load/store representation change insertions. |
| 1549 TestingGraph t(Type::Any(), Type::Signed32()); | 1556 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1550 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1557 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| 1551 Handle<Name>::null(), Type::Any(), kMachFloat64}; | 1558 Handle<Name>::null(), Type::Any(), kMachFloat64}; |
| 1552 | 1559 |
| 1553 Node* load = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, | 1560 Node* load = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, |
| 1554 t.start, t.start); | 1561 t.start, t.start); |
| 1555 t.Return(load); | 1562 t.Return(load); |
| 1556 t.Lower(); | 1563 t.Lower(); |
| 1557 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1564 CHECK_EQ(IrOpcode::kLoadField, load->opcode()); |
| 1558 CHECK_EQ(t.p0, load->InputAt(0)); | 1565 CHECK_EQ(t.p0, load->InputAt(0)); |
| 1559 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); | 1566 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0)); |
| 1560 } | 1567 } |
| 1561 | 1568 |
| 1562 | 1569 |
| 1563 TEST(InsertChangeForStoreElement) { | 1570 TEST(InsertChangeForStoreElement) { |
| 1564 // TODO(titzer): test all load/store representation change insertions. | 1571 // TODO(titzer): test all load/store representation change insertions. |
| 1565 TestingGraph t(Type::Any(), Type::Signed32()); | 1572 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1566 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), | 1573 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), |
| 1567 kMachFloat64}; | 1574 kMachFloat64}; |
| 1568 | 1575 |
| 1569 Node* store = | 1576 Node* store = |
| 1570 t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, | 1577 t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, |
| 1571 t.jsgraph.Int32Constant(0), t.p1, t.start, t.start); | 1578 t.jsgraph.Int32Constant(0), t.p1, t.start, t.start); |
| 1572 t.Effect(store); | 1579 t.Effect(store); |
| 1573 t.Lower(); | 1580 t.Lower(); |
| 1574 | 1581 |
| 1575 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1582 CHECK_EQ(IrOpcode::kStoreElement, store->opcode()); |
| 1576 CHECK_EQ(t.p0, store->InputAt(0)); | 1583 CHECK_EQ(t.p0, store->InputAt(0)); |
| 1577 CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(2)); | 1584 CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(2)); |
| 1578 } | 1585 } |
| 1579 | 1586 |
| 1580 | 1587 |
| 1581 TEST(InsertChangeForStoreField) { | 1588 TEST(InsertChangeForStoreField) { |
| 1582 // TODO(titzer): test all load/store representation change insertions. | 1589 // TODO(titzer): test all load/store representation change insertions. |
| 1583 TestingGraph t(Type::Any(), Type::Signed32()); | 1590 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1584 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1591 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| 1585 Handle<Name>::null(), Type::Any(), kMachFloat64}; | 1592 Handle<Name>::null(), Type::Any(), kMachFloat64}; |
| 1586 | 1593 |
| 1587 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, | 1594 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, |
| 1588 t.p1, t.start, t.start); | 1595 t.p1, t.start, t.start); |
| 1589 t.Effect(store); | 1596 t.Effect(store); |
| 1590 t.Lower(); | 1597 t.Lower(); |
| 1591 | 1598 |
| 1592 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1599 CHECK_EQ(IrOpcode::kStoreField, store->opcode()); |
| 1593 CHECK_EQ(t.p0, store->InputAt(0)); | 1600 CHECK_EQ(t.p0, store->InputAt(0)); |
| 1594 CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(2)); | 1601 CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(1)); |
| 1595 } | 1602 } |
| 1596 | 1603 |
| 1597 | 1604 |
| 1598 TEST(UpdatePhi) { | 1605 TEST(UpdatePhi) { |
| 1599 TestingGraph t(Type::Any(), Type::Signed32()); | 1606 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1600 static const MachineType kMachineTypes[] = {kMachInt32, kMachUint32, | 1607 static const MachineType kMachineTypes[] = {kMachInt32, kMachUint32, |
| 1601 kMachFloat64}; | 1608 kMachFloat64}; |
| 1602 Type* kTypes[] = {Type::Signed32(), Type::Unsigned32(), Type::Number()}; | 1609 Type* kTypes[] = {Type::Signed32(), Type::Unsigned32(), Type::Number()}; |
| 1603 | 1610 |
| 1604 for (size_t i = 0; i < arraysize(kMachineTypes); i++) { | 1611 for (size_t i = 0; i < arraysize(kMachineTypes); i++) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1621 } | 1628 } |
| 1622 | 1629 |
| 1623 | 1630 |
| 1624 TEST(RunNumberDivide_minus_1_TruncatingToInt32) { | 1631 TEST(RunNumberDivide_minus_1_TruncatingToInt32) { |
| 1625 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 1632 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
| 1626 Node* num = t.NumberToInt32(t.Parameter(0)); | 1633 Node* num = t.NumberToInt32(t.Parameter(0)); |
| 1627 Node* div = t.NumberDivide(num, t.jsgraph.Constant(-1)); | 1634 Node* div = t.NumberDivide(num, t.jsgraph.Constant(-1)); |
| 1628 Node* trunc = t.NumberToInt32(div); | 1635 Node* trunc = t.NumberToInt32(div); |
| 1629 t.Return(trunc); | 1636 t.Return(trunc); |
| 1630 | 1637 |
| 1631 t.LowerAllNodesAndLowerChanges(); | 1638 t.LowerAllNodesAndLowerChanges(); |
| 1632 t.GenerateCode(); | 1639 t.GenerateCode(); |
| 1633 | 1640 |
| 1634 FOR_INT32_INPUTS(i) { | 1641 FOR_INT32_INPUTS(i) { |
| 1635 int32_t x = 0 - *i; | 1642 int32_t x = 0 - *i; |
| 1636 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); | 1643 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); |
| 1637 } | 1644 } |
| 1638 } | 1645 } |
| 1639 | 1646 |
| 1640 | 1647 |
| 1641 TEST(NumberMultiply_TruncatingToInt32) { | 1648 TEST(NumberMultiply_TruncatingToInt32) { |
| 1642 int32_t constants[] = {-100, -10, -1, 0, 1, 100, 1000}; | 1649 int32_t constants[] = {-100, -10, -1, 0, 1, 100, 1000}; |
| 1643 | 1650 |
| 1644 for (size_t i = 0; i < arraysize(constants); i++) { | 1651 for (size_t i = 0; i < arraysize(constants); i++) { |
| 1645 TestingGraph t(Type::Signed32()); | 1652 TestingGraph t(Type::Signed32()); |
| 1646 Node* k = t.jsgraph.Constant(constants[i]); | 1653 Node* k = t.jsgraph.Constant(constants[i]); |
| 1647 Node* mul = t.graph()->NewNode(t.simplified()->NumberMultiply(), t.p0, k); | 1654 Node* mul = t.graph()->NewNode(t.simplified()->NumberMultiply(), t.p0, k); |
| (...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2004 t.Return(use); | 2011 t.Return(use); |
| 2005 t.Lower(); | 2012 t.Lower(); |
| 2006 | 2013 |
| 2007 CHECK_EQ(d.expected, OpParameter<MachineType>(phi)); | 2014 CHECK_EQ(d.expected, OpParameter<MachineType>(phi)); |
| 2008 } | 2015 } |
| 2009 } | 2016 } |
| 2010 | 2017 |
| 2011 } // namespace compiler | 2018 } // namespace compiler |
| 2012 } // namespace internal | 2019 } // namespace internal |
| 2013 } // namespace v8 | 2020 } // namespace v8 |
| OLD | NEW |