[cctest] adding tests for elements kind map migrations
R=mvstanton@chromium.org BUG= Review URL: https://codereview.chromium.org/1368403003 Cr-Commit-Position: refs/heads/master@{#31080}
This commit is contained in:
parent
6d13610374
commit
a9b84c1b2c
@ -122,8 +122,10 @@
|
||||
'test-diy-fp.cc',
|
||||
'test-double.cc',
|
||||
'test-dtoa.cc',
|
||||
'test-elements-kind.cc',
|
||||
'test-fast-dtoa.cc',
|
||||
'test-feedback-vector.cc',
|
||||
'test-field-type-tracking.cc',
|
||||
'test-fixed-dtoa.cc',
|
||||
'test-flags.cc',
|
||||
'test-func-name-inference.cc',
|
||||
@ -144,7 +146,6 @@
|
||||
'test-microtask-delivery.cc',
|
||||
'test-mark-compact.cc',
|
||||
'test-mementos.cc',
|
||||
'test-migrations.cc',
|
||||
'test-object-observe.cc',
|
||||
'test-parsing.cc',
|
||||
'test-platform.cc',
|
||||
|
475
test/cctest/test-elements-kind.cc
Normal file
475
test/cctest/test-elements-kind.cc
Normal file
@ -0,0 +1,475 @@
|
||||
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <utility>
|
||||
|
||||
#include "test/cctest/test-api.h"
|
||||
|
||||
#include "src/v8.h"
|
||||
|
||||
#include "src/compilation-cache.h"
|
||||
#include "src/execution.h"
|
||||
#include "src/factory.h"
|
||||
#include "src/global-handles.h"
|
||||
#include "src/ic/stub-cache.h"
|
||||
#include "src/objects.h"
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
|
||||
//
|
||||
// Helper functions.
|
||||
//
|
||||
|
||||
namespace {
|
||||
|
||||
Handle<String> MakeString(const char* str) {
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
Factory* factory = isolate->factory();
|
||||
return factory->InternalizeUtf8String(str);
|
||||
}
|
||||
|
||||
|
||||
Handle<String> MakeName(const char* str, int suffix) {
|
||||
EmbeddedVector<char, 128> buffer;
|
||||
SNPrintF(buffer, "%s%d", str, suffix);
|
||||
return MakeString(buffer.start());
|
||||
}
|
||||
|
||||
|
||||
template <typename T, typename M>
|
||||
bool EQUALS(Handle<T> left, Handle<M> right) {
|
||||
if (*left == *right) return true;
|
||||
return JSObject::Equals(Handle<Object>::cast(left),
|
||||
Handle<Object>::cast(right))
|
||||
.FromJust();
|
||||
}
|
||||
|
||||
|
||||
template <typename T, typename M>
|
||||
bool EQUALS(Handle<T> left, M right) {
|
||||
return EQUALS(left, handle(right));
|
||||
}
|
||||
|
||||
|
||||
template <typename T, typename M>
|
||||
bool EQUALS(T left, Handle<M> right) {
|
||||
return EQUALS(handle(left), right);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
//
|
||||
// Tests
|
||||
//
|
||||
|
||||
TEST(JSObjectAddingProperties) {
|
||||
CcTest::InitializeVM();
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
Factory* factory = isolate->factory();
|
||||
v8::HandleScope scope(CcTest::isolate());
|
||||
|
||||
Handle<FixedArray> empty_fixed_array(factory->empty_fixed_array());
|
||||
Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
|
||||
Handle<Object> value(Smi::FromInt(42), isolate);
|
||||
|
||||
Handle<JSObject> object = factory->NewJSObject(function);
|
||||
Handle<Map> previous_map(object->map());
|
||||
CHECK_EQ(previous_map->elements_kind(), FAST_HOLEY_ELEMENTS);
|
||||
CHECK(EQUALS(object->properties(), empty_fixed_array));
|
||||
CHECK(EQUALS(object->elements(), empty_fixed_array));
|
||||
|
||||
// for the default constructor function no in-object properties are reserved
|
||||
// hence adding a single property will initialize the property-array
|
||||
Handle<String> name = MakeName("property", 0);
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(object, name, value, NONE)
|
||||
.Check();
|
||||
CHECK_NE(object->map(), *previous_map);
|
||||
CHECK_EQ(object->map()->elements_kind(), FAST_HOLEY_ELEMENTS);
|
||||
CHECK_LE(1, object->properties()->length());
|
||||
CHECK(EQUALS(object->elements(), empty_fixed_array));
|
||||
}
|
||||
|
||||
|
||||
TEST(JSObjectInObjectAddingProperties) {
|
||||
CcTest::InitializeVM();
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
Factory* factory = isolate->factory();
|
||||
v8::HandleScope scope(CcTest::isolate());
|
||||
|
||||
Handle<FixedArray> empty_fixed_array(factory->empty_fixed_array());
|
||||
Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
|
||||
int nof_inobject_properties = 10;
|
||||
// force in object properties by changing the expected_nof_properties
|
||||
function->shared()->set_expected_nof_properties(nof_inobject_properties);
|
||||
Handle<Object> value(Smi::FromInt(42), isolate);
|
||||
|
||||
Handle<JSObject> object = factory->NewJSObject(function);
|
||||
Handle<Map> previous_map(object->map());
|
||||
CHECK_EQ(previous_map->elements_kind(), FAST_HOLEY_ELEMENTS);
|
||||
CHECK(EQUALS(object->properties(), empty_fixed_array));
|
||||
CHECK(EQUALS(object->elements(), empty_fixed_array));
|
||||
|
||||
// we have reserved space for in-object properties, hence adding up to
|
||||
// |nof_inobject_properties| will not create a property store
|
||||
for (int i = 0; i < nof_inobject_properties; i++) {
|
||||
Handle<String> name = MakeName("property", i);
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(object, name, value, NONE)
|
||||
.Check();
|
||||
}
|
||||
CHECK_NE(object->map(), *previous_map);
|
||||
CHECK_EQ(object->map()->elements_kind(), FAST_HOLEY_ELEMENTS);
|
||||
CHECK(EQUALS(object->properties(), empty_fixed_array));
|
||||
CHECK(EQUALS(object->elements(), empty_fixed_array));
|
||||
|
||||
// adding one more property will not fit in the in-object properties, thus
|
||||
// creating a property store
|
||||
int index = nof_inobject_properties + 1;
|
||||
Handle<String> name = MakeName("property", index);
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(object, name, value, NONE)
|
||||
.Check();
|
||||
CHECK_NE(object->map(), *previous_map);
|
||||
CHECK_EQ(object->map()->elements_kind(), FAST_HOLEY_ELEMENTS);
|
||||
// there must be at least 1 element in the properies store
|
||||
CHECK_LE(1, object->properties()->length());
|
||||
CHECK(EQUALS(object->elements(), empty_fixed_array));
|
||||
}
|
||||
|
||||
|
||||
TEST(JSObjectAddingElements) {
|
||||
CcTest::InitializeVM();
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
Factory* factory = isolate->factory();
|
||||
v8::HandleScope scope(CcTest::isolate());
|
||||
|
||||
Handle<String> name;
|
||||
Handle<FixedArray> empty_fixed_array(factory->empty_fixed_array());
|
||||
Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
|
||||
Handle<Object> value(Smi::FromInt(42), isolate);
|
||||
|
||||
Handle<JSObject> object = factory->NewJSObject(function);
|
||||
Handle<Map> previous_map(object->map());
|
||||
CHECK_EQ(previous_map->elements_kind(), FAST_HOLEY_ELEMENTS);
|
||||
CHECK(EQUALS(object->properties(), empty_fixed_array));
|
||||
CHECK(EQUALS(object->elements(), empty_fixed_array));
|
||||
|
||||
// Adding an indexed element initializes the elements array
|
||||
name = MakeString("0");
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(object, name, value, NONE)
|
||||
.Check();
|
||||
// no change in elements_kind => no map transition
|
||||
CHECK_EQ(object->map(), *previous_map);
|
||||
CHECK_EQ(object->map()->elements_kind(), FAST_HOLEY_ELEMENTS);
|
||||
CHECK(EQUALS(object->properties(), empty_fixed_array));
|
||||
CHECK_LE(1, object->elements()->length());
|
||||
|
||||
// Adding more consecutive elements without a change in the backing store
|
||||
int non_dict_backing_store_limit = 100;
|
||||
for (int i = 1; i < non_dict_backing_store_limit; i++) {
|
||||
name = MakeName("", i);
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(object, name, value, NONE)
|
||||
.Check();
|
||||
}
|
||||
// no change in elements_kind => no map transition
|
||||
CHECK_EQ(object->map(), *previous_map);
|
||||
CHECK_EQ(object->map()->elements_kind(), FAST_HOLEY_ELEMENTS);
|
||||
CHECK(EQUALS(object->properties(), empty_fixed_array));
|
||||
CHECK_LE(non_dict_backing_store_limit, object->elements()->length());
|
||||
|
||||
// Adding an element at an very large index causes a change to
|
||||
// DICTIONARY_ELEMENTS
|
||||
name = MakeString("100000000");
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(object, name, value, NONE)
|
||||
.Check();
|
||||
// change in elements_kind => map transition
|
||||
CHECK_NE(object->map(), *previous_map);
|
||||
CHECK_EQ(object->map()->elements_kind(), DICTIONARY_ELEMENTS);
|
||||
CHECK(EQUALS(object->properties(), empty_fixed_array));
|
||||
CHECK_LE(non_dict_backing_store_limit, object->elements()->length());
|
||||
}
|
||||
|
||||
|
||||
TEST(JSArrayAddingProperties) {
|
||||
CcTest::InitializeVM();
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
Factory* factory = isolate->factory();
|
||||
v8::HandleScope scope(CcTest::isolate());
|
||||
|
||||
Handle<FixedArray> empty_fixed_array(factory->empty_fixed_array());
|
||||
Handle<Object> value(Smi::FromInt(42), isolate);
|
||||
|
||||
Handle<JSArray> array =
|
||||
factory->NewJSArray(ElementsKind::FAST_SMI_ELEMENTS, 0, 0);
|
||||
Handle<Map> previous_map(array->map());
|
||||
CHECK_EQ(previous_map->elements_kind(), FAST_SMI_ELEMENTS);
|
||||
CHECK(EQUALS(array->properties(), empty_fixed_array));
|
||||
CHECK(EQUALS(array->elements(), empty_fixed_array));
|
||||
CHECK_EQ(Smi::cast(array->length())->value(), 0);
|
||||
|
||||
// for the default constructor function no in-object properties are reserved
|
||||
// hence adding a single property will initialize the property-array
|
||||
Handle<String> name = MakeName("property", 0);
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value, NONE)
|
||||
.Check();
|
||||
// No change in elements_kind but added property => new map
|
||||
CHECK_NE(array->map(), *previous_map);
|
||||
CHECK_EQ(array->map()->elements_kind(), FAST_SMI_ELEMENTS);
|
||||
CHECK_LE(1, array->properties()->length());
|
||||
CHECK(EQUALS(array->elements(), empty_fixed_array));
|
||||
CHECK_EQ(Smi::cast(array->length())->value(), 0);
|
||||
}
|
||||
|
||||
|
||||
TEST(JSArrayAddingElements) {
|
||||
CcTest::InitializeVM();
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
Factory* factory = isolate->factory();
|
||||
v8::HandleScope scope(CcTest::isolate());
|
||||
|
||||
Handle<String> name;
|
||||
Handle<FixedArray> empty_fixed_array(factory->empty_fixed_array());
|
||||
Handle<Object> value(Smi::FromInt(42), isolate);
|
||||
|
||||
Handle<JSArray> array =
|
||||
factory->NewJSArray(ElementsKind::FAST_SMI_ELEMENTS, 0, 0);
|
||||
Handle<Map> previous_map(array->map());
|
||||
CHECK_EQ(previous_map->elements_kind(), FAST_SMI_ELEMENTS);
|
||||
CHECK(EQUALS(array->properties(), empty_fixed_array));
|
||||
CHECK(EQUALS(array->elements(), empty_fixed_array));
|
||||
CHECK_EQ(Smi::cast(array->length())->value(), 0);
|
||||
|
||||
// Adding an indexed element initializes the elements array
|
||||
name = MakeString("0");
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value, NONE)
|
||||
.Check();
|
||||
// no change in elements_kind => no map transition
|
||||
CHECK_EQ(array->map(), *previous_map);
|
||||
CHECK_EQ(array->map()->elements_kind(), FAST_SMI_ELEMENTS);
|
||||
CHECK(EQUALS(array->properties(), empty_fixed_array));
|
||||
CHECK_LE(1, array->elements()->length());
|
||||
CHECK_EQ(1, Smi::cast(array->length())->value());
|
||||
|
||||
// Adding more consecutive elements without a change in the backing store
|
||||
int non_dict_backing_store_limit = 100;
|
||||
for (int i = 1; i < non_dict_backing_store_limit; i++) {
|
||||
name = MakeName("", i);
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value, NONE)
|
||||
.Check();
|
||||
}
|
||||
// no change in elements_kind => no map transition
|
||||
CHECK_EQ(array->map(), *previous_map);
|
||||
CHECK_EQ(array->map()->elements_kind(), FAST_SMI_ELEMENTS);
|
||||
CHECK(EQUALS(array->properties(), empty_fixed_array));
|
||||
CHECK_LE(non_dict_backing_store_limit, array->elements()->length());
|
||||
CHECK_EQ(non_dict_backing_store_limit, Smi::cast(array->length())->value());
|
||||
|
||||
// Adding an element at an very large index causes a change to
|
||||
// DICTIONARY_ELEMENTS
|
||||
int index = 100000000;
|
||||
name = MakeName("", index);
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value, NONE)
|
||||
.Check();
|
||||
// change in elements_kind => map transition
|
||||
CHECK_NE(array->map(), *previous_map);
|
||||
CHECK_EQ(array->map()->elements_kind(), DICTIONARY_ELEMENTS);
|
||||
CHECK(EQUALS(array->properties(), empty_fixed_array));
|
||||
CHECK_LE(non_dict_backing_store_limit, array->elements()->length());
|
||||
CHECK_LE(array->elements()->length(), index);
|
||||
CHECK_EQ(index + 1, Smi::cast(array->length())->value());
|
||||
}
|
||||
|
||||
|
||||
TEST(JSArrayAddingElementsGeneralizingiFastSmiElements) {
|
||||
CcTest::InitializeVM();
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
Factory* factory = isolate->factory();
|
||||
v8::HandleScope scope(CcTest::isolate());
|
||||
|
||||
Handle<String> name;
|
||||
Handle<Object> value_smi(Smi::FromInt(42), isolate);
|
||||
Handle<Object> value_string(MakeString("value"));
|
||||
Handle<Object> value_double = factory->NewNumber(3.1415);
|
||||
|
||||
Handle<JSArray> array =
|
||||
factory->NewJSArray(ElementsKind::FAST_SMI_ELEMENTS, 0, 0);
|
||||
Handle<Map> previous_map(array->map());
|
||||
CHECK_EQ(previous_map->elements_kind(), FAST_SMI_ELEMENTS);
|
||||
CHECK_EQ(Smi::cast(array->length())->value(), 0);
|
||||
|
||||
// `array[0] = smi_value` doesn't change the elements_kind
|
||||
name = MakeString("0");
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
|
||||
NONE)
|
||||
.Check();
|
||||
// no change in elements_kind => no map transition
|
||||
CHECK_EQ(array->map(), *previous_map);
|
||||
CHECK_EQ(array->map()->elements_kind(), FAST_SMI_ELEMENTS);
|
||||
CHECK_EQ(1, Smi::cast(array->length())->value());
|
||||
|
||||
// `delete array[0]` does not alter length, but changes the elments_kind
|
||||
name = MakeString("0");
|
||||
JSReceiver::DeletePropertyOrElement(array, name).Check();
|
||||
CHECK_NE(array->map(), *previous_map);
|
||||
CHECK_EQ(array->map()->elements_kind(), FAST_HOLEY_SMI_ELEMENTS);
|
||||
CHECK_EQ(1, Smi::cast(array->length())->value());
|
||||
previous_map = handle(array->map());
|
||||
|
||||
// add a couple of elements again
|
||||
name = MakeString("0");
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
|
||||
NONE)
|
||||
.Check();
|
||||
name = MakeString("1");
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
|
||||
NONE)
|
||||
.Check();
|
||||
CHECK_EQ(array->map(), *previous_map);
|
||||
CHECK_EQ(array->map()->elements_kind(), FAST_HOLEY_SMI_ELEMENTS);
|
||||
CHECK_EQ(2, Smi::cast(array->length())->value());
|
||||
|
||||
// Adding a string to the array changes from FAST_HOLEY_SMI to FAST_HOLEY
|
||||
name = MakeString("0");
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_string,
|
||||
NONE)
|
||||
.Check();
|
||||
CHECK_NE(array->map(), *previous_map);
|
||||
CHECK_EQ(array->map()->elements_kind(), FAST_HOLEY_ELEMENTS);
|
||||
CHECK_EQ(2, Smi::cast(array->length())->value());
|
||||
previous_map = handle(array->map());
|
||||
|
||||
// We don't transition back to FAST_SMI even if we remove the string
|
||||
name = MakeString("0");
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
|
||||
NONE)
|
||||
.Check();
|
||||
CHECK_EQ(array->map(), *previous_map);
|
||||
|
||||
// Adding a double doesn't change the map either
|
||||
name = MakeString("0");
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_double,
|
||||
NONE)
|
||||
.Check();
|
||||
CHECK_EQ(array->map(), *previous_map);
|
||||
}
|
||||
|
||||
|
||||
TEST(JSArrayAddingElementsGeneralizingFastElements) {
|
||||
CcTest::InitializeVM();
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
Factory* factory = isolate->factory();
|
||||
v8::HandleScope scope(CcTest::isolate());
|
||||
|
||||
Handle<String> name;
|
||||
Handle<Object> value_smi(Smi::FromInt(42), isolate);
|
||||
Handle<Object> value_string(MakeString("value"));
|
||||
|
||||
Handle<JSArray> array =
|
||||
factory->NewJSArray(ElementsKind::FAST_ELEMENTS, 0, 0);
|
||||
Handle<Map> previous_map(array->map());
|
||||
CHECK_EQ(previous_map->elements_kind(), FAST_ELEMENTS);
|
||||
CHECK_EQ(Smi::cast(array->length())->value(), 0);
|
||||
|
||||
// `array[0] = smi_value` doesn't change the elements_kind
|
||||
name = MakeString("0");
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
|
||||
NONE)
|
||||
.Check();
|
||||
// no change in elements_kind => no map transition
|
||||
CHECK_EQ(array->map(), *previous_map);
|
||||
CHECK_EQ(array->map()->elements_kind(), FAST_ELEMENTS);
|
||||
CHECK_EQ(1, Smi::cast(array->length())->value());
|
||||
|
||||
// `delete array[0]` does not alter length, but changes the elments_kind
|
||||
name = MakeString("0");
|
||||
JSReceiver::DeletePropertyOrElement(array, name).Check();
|
||||
CHECK_NE(array->map(), *previous_map);
|
||||
CHECK_EQ(array->map()->elements_kind(), FAST_HOLEY_ELEMENTS);
|
||||
CHECK_EQ(1, Smi::cast(array->length())->value());
|
||||
previous_map = handle(array->map());
|
||||
|
||||
// add a couple of elements, elements_kind stays HOLEY
|
||||
name = MakeString("0");
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_string,
|
||||
NONE)
|
||||
.Check();
|
||||
name = MakeString("1");
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
|
||||
NONE)
|
||||
.Check();
|
||||
CHECK_EQ(array->map(), *previous_map);
|
||||
CHECK_EQ(array->map()->elements_kind(), FAST_HOLEY_ELEMENTS);
|
||||
CHECK_EQ(2, Smi::cast(array->length())->value());
|
||||
}
|
||||
|
||||
|
||||
TEST(JSArrayAddingElementsGeneralizingiFastDoubleElements) {
|
||||
CcTest::InitializeVM();
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
Factory* factory = isolate->factory();
|
||||
v8::HandleScope scope(CcTest::isolate());
|
||||
|
||||
Handle<String> name;
|
||||
Handle<Object> value_smi(Smi::FromInt(42), isolate);
|
||||
Handle<Object> value_string(MakeString("value"));
|
||||
Handle<Object> value_double = factory->NewNumber(3.1415);
|
||||
|
||||
Handle<JSArray> array =
|
||||
factory->NewJSArray(ElementsKind::FAST_SMI_ELEMENTS, 0, 0);
|
||||
Handle<Map> previous_map(array->map());
|
||||
|
||||
// `array[0] = value_double` changes |elements_kind| to FAST_DOUBLE_ELEMENTS
|
||||
name = MakeString("0");
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_double,
|
||||
NONE)
|
||||
.Check();
|
||||
CHECK_NE(array->map(), *previous_map);
|
||||
CHECK_EQ(array->map()->elements_kind(), FAST_DOUBLE_ELEMENTS);
|
||||
CHECK_EQ(1, Smi::cast(array->length())->value());
|
||||
previous_map = handle(array->map());
|
||||
|
||||
// `array[1] = value_smi` doesn't alter the |elements_kind|
|
||||
name = MakeString("1");
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_smi,
|
||||
NONE)
|
||||
.Check();
|
||||
CHECK_EQ(array->map(), *previous_map);
|
||||
CHECK_EQ(array->map()->elements_kind(), FAST_DOUBLE_ELEMENTS);
|
||||
CHECK_EQ(2, Smi::cast(array->length())->value());
|
||||
|
||||
// `delete array[0]` does not alter length, but changes the elments_kind
|
||||
name = MakeString("0");
|
||||
JSReceiver::DeletePropertyOrElement(array, name).Check();
|
||||
CHECK_NE(array->map(), *previous_map);
|
||||
CHECK_EQ(array->map()->elements_kind(), FAST_HOLEY_DOUBLE_ELEMENTS);
|
||||
CHECK_EQ(2, Smi::cast(array->length())->value());
|
||||
previous_map = handle(array->map());
|
||||
|
||||
// filling the hole `array[0] = value_smi` again doesn't transition back
|
||||
name = MakeString("0");
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_double,
|
||||
NONE)
|
||||
.Check();
|
||||
CHECK_EQ(array->map(), *previous_map);
|
||||
CHECK_EQ(array->map()->elements_kind(), FAST_HOLEY_DOUBLE_ELEMENTS);
|
||||
CHECK_EQ(2, Smi::cast(array->length())->value());
|
||||
|
||||
// Adding a string to the array changes to elements_kind FAST_ELEMENTS
|
||||
name = MakeString("1");
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_string,
|
||||
NONE)
|
||||
.Check();
|
||||
CHECK_NE(array->map(), *previous_map);
|
||||
CHECK_EQ(array->map()->elements_kind(), FAST_HOLEY_ELEMENTS);
|
||||
CHECK_EQ(2, Smi::cast(array->length())->value());
|
||||
previous_map = handle(array->map());
|
||||
|
||||
// Adding a double doesn't change the map
|
||||
name = MakeString("0");
|
||||
JSObject::DefinePropertyOrElementIgnoreAttributes(array, name, value_double,
|
||||
NONE)
|
||||
.Check();
|
||||
CHECK_EQ(array->map(), *previous_map);
|
||||
}
|
@ -5,6 +5,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <utility>
|
||||
|
||||
#include "test/cctest/test-api.h"
|
||||
|
||||
#include "src/v8.h"
|
||||
|
||||
#include "src/compilation-cache.h"
|
||||
@ -13,7 +15,6 @@
|
||||
#include "src/global-handles.h"
|
||||
#include "src/ic/stub-cache.h"
|
||||
#include "src/macro-assembler.h"
|
||||
#include "test/cctest/cctest.h"
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
@ -286,7 +287,8 @@ class Expectations {
|
||||
|
||||
Handle<String> name = MakeName("prop", property_index);
|
||||
return Map::CopyWithField(map, name, heap_type, attributes, representation,
|
||||
INSERT_TRANSITION).ToHandleChecked();
|
||||
INSERT_TRANSITION)
|
||||
.ToHandleChecked();
|
||||
}
|
||||
|
||||
Handle<Map> AddDataConstant(Handle<Map> map, PropertyAttributes attributes,
|
||||
@ -297,7 +299,8 @@ class Expectations {
|
||||
|
||||
Handle<String> name = MakeName("prop", property_index);
|
||||
return Map::CopyWithConstant(map, name, value, attributes,
|
||||
INSERT_TRANSITION).ToHandleChecked();
|
||||
INSERT_TRANSITION)
|
||||
.ToHandleChecked();
|
||||
}
|
||||
|
||||
Handle<Map> TransitionToDataField(Handle<Map> map,
|
||||
@ -1583,7 +1586,8 @@ TEST(ReconfigurePropertySplitMapTransitionsOverflow) {
|
||||
CHECK(TransitionArray::CanHaveMoreTransitions(map2));
|
||||
Handle<String> name = MakeName("foo", i);
|
||||
Map::CopyWithField(map2, name, any_type, NONE, Representation::Smi(),
|
||||
INSERT_TRANSITION).ToHandleChecked();
|
||||
INSERT_TRANSITION)
|
||||
.ToHandleChecked();
|
||||
}
|
||||
CHECK(!TransitionArray::CanHaveMoreTransitions(map2));
|
||||
|
||||
@ -1751,8 +1755,8 @@ TEST(ElementsKindTransitionFromMapNotOwningDescriptor) {
|
||||
// ownership.
|
||||
CHECK(map->owns_descriptors());
|
||||
Map::CopyWithField(map, MakeString("foo"), any_type, NONE,
|
||||
Representation::Smi(),
|
||||
INSERT_TRANSITION).ToHandleChecked();
|
||||
Representation::Smi(), INSERT_TRANSITION)
|
||||
.ToHandleChecked();
|
||||
CHECK(!map->owns_descriptors());
|
||||
|
||||
return Map::CopyAsElementsKind(map, DICTIONARY_ELEMENTS,
|
||||
@ -1809,8 +1813,8 @@ TEST(ForObservedTransitionFromMapNotOwningDescriptor) {
|
||||
// ownership.
|
||||
CHECK(map->owns_descriptors());
|
||||
Map::CopyWithField(map, MakeString("foo"), any_type, NONE,
|
||||
Representation::Smi(),
|
||||
INSERT_TRANSITION).ToHandleChecked();
|
||||
Representation::Smi(), INSERT_TRANSITION)
|
||||
.ToHandleChecked();
|
||||
CHECK(!map->owns_descriptors());
|
||||
|
||||
return Map::CopyForObserved(map);
|
||||
@ -1886,8 +1890,8 @@ TEST(PrototypeTransitionFromMapNotOwningDescriptor) {
|
||||
// ownership.
|
||||
CHECK(map->owns_descriptors());
|
||||
Map::CopyWithField(map, MakeString("foo"), any_type, NONE,
|
||||
Representation::Smi(),
|
||||
INSERT_TRANSITION).ToHandleChecked();
|
||||
Representation::Smi(), INSERT_TRANSITION)
|
||||
.ToHandleChecked();
|
||||
CHECK(!map->owns_descriptors());
|
||||
|
||||
return Map::TransitionToPrototype(map, prototype_, REGULAR_PROTOTYPE);
|
Loading…
Reference in New Issue
Block a user