diff options
author | Michaƫl Zasso <targos@protonmail.com> | 2019-05-21 08:21:34 +0200 |
---|---|---|
committer | Ruben Bridgewater <ruben@bridgewater.de> | 2019-05-22 14:24:41 +0200 |
commit | f2fe1e5a78d6decf04536764c8c4cf3f6c5f8dd7 (patch) | |
tree | e11d1d4d1b71c3d8cd9741e6bd2d80009f7d05bb /deps/v8/test/cctest/test-field-type-tracking.cc | |
parent | c3f72510c8f629ed2178b50bb2860efc3feb9249 (diff) | |
download | android-node-v8-f2fe1e5a78d6decf04536764c8c4cf3f6c5f8dd7.tar.gz android-node-v8-f2fe1e5a78d6decf04536764c8c4cf3f6c5f8dd7.tar.bz2 android-node-v8-f2fe1e5a78d6decf04536764c8c4cf3f6c5f8dd7.zip |
deps: V8: cherry-pick 94c87fe
Original commit message:
[ic] Fix handling of +0/-0 when constant field tracking is enabled
... and ensure that runtime behaviour is in sync with the IC code.
Bug: chromium:950747, v8:9113
Change-Id: Ied66c9514cbe3a4d75fc71d4fc3b19ea1538f9b2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1561319
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60768}
PR-URL: https://github.com/nodejs/node/pull/27792
Fixes: https://github.com/nodejs/node/issues/27784
Refs: https://github.com/v8/v8/commit/94c87fe0746fc95618ae091351f2f8c342212917
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Gus Caplan <me@gus.host>
Diffstat (limited to 'deps/v8/test/cctest/test-field-type-tracking.cc')
-rw-r--r-- | deps/v8/test/cctest/test-field-type-tracking.cc | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/deps/v8/test/cctest/test-field-type-tracking.cc b/deps/v8/test/cctest/test-field-type-tracking.cc index 49b0f92011..0253a16735 100644 --- a/deps/v8/test/cctest/test-field-type-tracking.cc +++ b/deps/v8/test/cctest/test-field-type-tracking.cc @@ -2883,6 +2883,192 @@ TEST(HoleyMutableHeapNumber) { CHECK_EQ(kHoleNanInt64, MutableHeapNumber::cast(*obj)->value_as_bits()); } +namespace { + +template <class... Args> +MaybeHandle<Object> Call(Isolate* isolate, Handle<JSFunction> function, + Args... args) { + Handle<Object> argv[] = {args...}; + return Execution::Call(isolate, function, + isolate->factory()->undefined_value(), sizeof...(args), + argv); +} + +void TestStoreToConstantField(const char* store_func_source, + Handle<Object> value1, Handle<Object> value2, + Representation expected_rep, + PropertyConstness expected_constness, + int store_repetitions) { + Isolate* isolate = CcTest::i_isolate(); + CompileRun(store_func_source); + + Handle<JSFunction> store_func = GetGlobal<JSFunction>("store"); + + const PropertyConstness kExpectedInitialFieldConstness = + FLAG_track_constant_fields ? PropertyConstness::kConst + : PropertyConstness::kMutable; + + Handle<Map> initial_map = Map::Create(isolate, 4); + + // Store value1 to obj1 and check that it got property with expected + // representation and constness. + Handle<JSObject> obj1 = isolate->factory()->NewJSObjectFromMap(initial_map); + for (int i = 0; i < store_repetitions; i++) { + Call(isolate, store_func, obj1, value1).Check(); + } + + Handle<Map> map(obj1->map(), isolate); + CHECK(!map->is_dictionary_map()); + CHECK(!map->is_deprecated()); + CHECK_EQ(1, map->NumberOfOwnDescriptors()); + + CHECK(map->instance_descriptors()->GetDetails(0).representation().Equals( + expected_rep)); + CHECK_EQ(kExpectedInitialFieldConstness, + map->instance_descriptors()->GetDetails(0).constness()); + + // Store value2 to obj2 and check that it got same map and property details + // did not change. + Handle<JSObject> obj2 = isolate->factory()->NewJSObjectFromMap(initial_map); + Call(isolate, store_func, obj2, value2).Check(); + + CHECK_EQ(*map, obj2->map()); + CHECK(!map->is_dictionary_map()); + CHECK(!map->is_deprecated()); + CHECK_EQ(1, map->NumberOfOwnDescriptors()); + + CHECK(map->instance_descriptors()->GetDetails(0).representation().Equals( + expected_rep)); + CHECK_EQ(kExpectedInitialFieldConstness, + map->instance_descriptors()->GetDetails(0).constness()); + + // Store value2 to obj1 and check that property became mutable. + Call(isolate, store_func, obj1, value2).Check(); + + CHECK_EQ(*map, obj1->map()); + CHECK(!map->is_dictionary_map()); + CHECK(!map->is_deprecated()); + CHECK_EQ(1, map->NumberOfOwnDescriptors()); + + CHECK(map->instance_descriptors()->GetDetails(0).representation().Equals( + expected_rep)); + CHECK_EQ(expected_constness, + map->instance_descriptors()->GetDetails(0).constness()); +} + +void TestStoreToConstantField_PlusMinusZero(const char* store_func_source, + int store_repetitions) { + Isolate* isolate = CcTest::i_isolate(); + CompileRun(store_func_source); + + Handle<Object> minus_zero = isolate->factory()->NewNumber(-0.0); + Handle<Object> plus_zero = isolate->factory()->NewNumber(0.0); + + // +0 and -0 are treated as not equal upon stores. + const PropertyConstness kExpectedFieldConstness = PropertyConstness::kMutable; + + TestStoreToConstantField(store_func_source, minus_zero, plus_zero, + Representation::Double(), kExpectedFieldConstness, + store_repetitions); +} + +void TestStoreToConstantField_NaN(const char* store_func_source, + int store_repetitions) { + Isolate* isolate = CcTest::i_isolate(); + CompileRun(store_func_source); + + uint64_t nan_bits = uint64_t{0x7FF8000000000001}; + double nan_double1 = bit_cast<double>(nan_bits); + double nan_double2 = bit_cast<double>(nan_bits | 0x12300); + CHECK(std::isnan(nan_double1)); + CHECK(std::isnan(nan_double2)); + CHECK_NE(nan_double1, nan_double2); + CHECK_NE(bit_cast<uint64_t>(nan_double1), bit_cast<uint64_t>(nan_double2)); + + Handle<Object> nan1 = isolate->factory()->NewNumber(nan_double1); + Handle<Object> nan2 = isolate->factory()->NewNumber(nan_double2); + + // NaNs with different bit patters are treated as equal upon stores. + const PropertyConstness kExpectedFieldConstness = + FLAG_track_constant_fields ? PropertyConstness::kConst + : PropertyConstness::kMutable; + + TestStoreToConstantField(store_func_source, nan1, nan2, + Representation::Double(), kExpectedFieldConstness, + store_repetitions); +} + +} // namespace + +TEST(StoreToConstantField_PlusMinusZero) { + FLAG_allow_natives_syntax = true; + CcTest::InitializeVM(); + v8::HandleScope scope(CcTest::isolate()); + + const char* store_func_source = + "function store(o, v) {" + " %SetNamedProperty(o, 'v', v);" + "}"; + + TestStoreToConstantField_PlusMinusZero(store_func_source, 1); + TestStoreToConstantField_PlusMinusZero(store_func_source, 3); + + TestStoreToConstantField_NaN(store_func_source, 1); + TestStoreToConstantField_NaN(store_func_source, 2); +} + +TEST(StoreToConstantField_ObjectDefineProperty) { + CcTest::InitializeVM(); + v8::HandleScope scope(CcTest::isolate()); + + const char* store_func_source = + "function store(o, v) {" + " Object.defineProperty(o, 'v', " + " {value: v, " + " writable: true, " + " configurable: true, " + " enumerable: true});" + "}"; + + TestStoreToConstantField_PlusMinusZero(store_func_source, 1); + TestStoreToConstantField_PlusMinusZero(store_func_source, 3); + + TestStoreToConstantField_NaN(store_func_source, 1); + TestStoreToConstantField_NaN(store_func_source, 2); +} + +TEST(StoreToConstantField_ReflectSet) { + CcTest::InitializeVM(); + v8::HandleScope scope(CcTest::isolate()); + + const char* store_func_source = + "function store(o, v) {" + " Reflect.set(o, 'v', v);" + "}"; + + TestStoreToConstantField_PlusMinusZero(store_func_source, 1); + TestStoreToConstantField_PlusMinusZero(store_func_source, 3); + + TestStoreToConstantField_NaN(store_func_source, 1); + TestStoreToConstantField_NaN(store_func_source, 2); +} + +TEST(StoreToConstantField_StoreIC) { + CcTest::InitializeVM(); + v8::HandleScope scope(CcTest::isolate()); + + const char* store_func_source = + "function store(o, v) {" + " o.v = v;" + "}"; + + TestStoreToConstantField_PlusMinusZero(store_func_source, 1); + TestStoreToConstantField_PlusMinusZero(store_func_source, 3); + + TestStoreToConstantField_NaN(store_func_source, 1); + TestStoreToConstantField_NaN(store_func_source, 2); +} + } // namespace test_field_type_tracking } // namespace compiler } // namespace internal |