Commit 9285ac92 authored by cbruni's avatar cbruni Committed by Commit bot

Improve elements validation and object printing

Make sure we check that packed elements do not containt TheHole.
%DebugPrint:
- Only print the transition arrays for maps
- Print more detailed instance types directly for objects
- directly print the array length for JS_ARRAY objects

BUG=

Review URL: https://codereview.chromium.org/1870433003

Cr-Commit-Position: refs/heads/master@{#35338}
parent 75b03d0c
......@@ -41,12 +41,12 @@ class BuiltinArguments : public Arguments {
}
Object*& operator[] (int index) {
DCHECK(index < length());
DCHECK_LT(index, length());
return Arguments::operator[](index);
}
template <class S> Handle<S> at(int index) {
DCHECK(index < length());
DCHECK_LT(index, length());
return Arguments::at<S>(index);
}
......
......@@ -1572,16 +1572,20 @@ class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> {
static void ValidateContents(Handle<JSObject> holder, int length) {
#if DEBUG
Isolate* isolate = holder->GetIsolate();
Heap* heap = isolate->heap();
HandleScope scope(isolate);
Handle<FixedArrayBase> elements(holder->elements(), isolate);
Map* map = elements->map();
DCHECK((IsFastSmiOrObjectElementsKind(KindTraits::Kind) &&
(map == isolate->heap()->fixed_array_map() ||
map == isolate->heap()->fixed_cow_array_map())) ||
(IsFastDoubleElementsKind(KindTraits::Kind) ==
((map == isolate->heap()->fixed_array_map() && length == 0) ||
map == isolate->heap()->fixed_double_array_map())));
if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) {
DCHECK_NE(map, heap->fixed_double_array_map());
} else if (IsFastDoubleElementsKind(KindTraits::Kind)) {
DCHECK_NE(map, heap->fixed_cow_array_map());
if (map == heap->fixed_array_map()) DCHECK_EQ(0, length);
} else {
UNREACHABLE();
}
if (length == 0) return; // nothing to do!
#if ENABLE_SLOW_DCHECKS
DisallowHeapAllocation no_gc;
Handle<BackingStore> backing_store = Handle<BackingStore>::cast(elements);
if (IsFastSmiElementsKind(KindTraits::Kind)) {
......@@ -1590,7 +1594,15 @@ class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> {
(IsFastHoleyElementsKind(KindTraits::Kind) &&
backing_store->is_the_hole(i)));
}
} else if (KindTraits::Kind == FAST_ELEMENTS ||
KindTraits::Kind == FAST_DOUBLE_ELEMENTS) {
for (int i = 0; i < length; i++) {
DCHECK(!backing_store->is_the_hole(i));
}
} else {
DCHECK(IsFastHoleyElementsKind(KindTraits::Kind));
}
#endif
#endif
}
......@@ -1805,7 +1817,7 @@ class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> {
static uint32_t AddArguments(Handle<JSArray> receiver,
Handle<FixedArrayBase> backing_store,
Arguments* args, uint32_t add_size,
Where remove_position) {
Where add_position) {
uint32_t length = Smi::cast(receiver->length())->value();
DCHECK(0 < add_size);
uint32_t elms_len = backing_store->length();
......@@ -1817,13 +1829,13 @@ class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> {
// New backing storage is needed.
uint32_t capacity = JSObject::NewElementsCapacity(new_length);
// If we add arguments to the start we have to shift the existing objects.
int copy_dst_index = remove_position == AT_START ? add_size : 0;
int copy_dst_index = add_position == AT_START ? add_size : 0;
// Copy over all objects to a new backing_store.
backing_store = Subclass::ConvertElementsWithCapacity(
receiver, backing_store, KindTraits::Kind, capacity, 0,
copy_dst_index, ElementsAccessor::kCopyToEndAndInitializeToHole);
receiver->set_elements(*backing_store);
} else if (remove_position == AT_START) {
} else if (add_position == AT_START) {
// If the backing store has enough capacity and we add elements to the
// start we have to shift the existing objects.
Isolate* isolate = receiver->GetIsolate();
......@@ -1831,7 +1843,7 @@ class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> {
length, 0, 0);
}
int insertion_index = remove_position == AT_START ? 0 : length;
int insertion_index = add_position == AT_START ? 0 : length;
// Copy the arguments to the start.
Subclass::CopyArguments(args, backing_store, add_size, 1, insertion_index);
// Set the length.
......@@ -1847,8 +1859,9 @@ class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> {
FixedArrayBase* raw_backing_store = *dst_store;
WriteBarrierMode mode = raw_backing_store->GetWriteBarrierMode(no_gc);
for (uint32_t i = 0; i < copy_size; i++) {
Object* argument = (*args)[i + src_index];
Subclass::SetImpl(raw_backing_store, i + dst_index, argument, mode);
Object* argument = (*args)[src_index + i];
DCHECK(!argument->IsTheHole());
Subclass::SetImpl(raw_backing_store, dst_index + i, argument, mode);
}
}
};
......@@ -2916,7 +2929,7 @@ MaybeHandle<Object> ArrayConstructInitializeElements(Handle<JSArray> array,
}
// Fill in the content
switch (array->GetElementsKind()) {
switch (elements_kind) {
case FAST_HOLEY_SMI_ELEMENTS:
case FAST_SMI_ELEMENTS: {
Handle<FixedArray> smi_elms = Handle<FixedArray>::cast(elms);
......
......@@ -1779,7 +1779,7 @@ void JSObject::EnsureCanContainElements(Handle<JSObject> object,
Object** objects,
uint32_t count,
EnsureElementsMode mode) {
ElementsKind current_kind = object->map()->elements_kind();
ElementsKind current_kind = object->GetElementsKind();
ElementsKind target_kind = current_kind;
{
DisallowHeapAllocation no_allocation;
......
......@@ -33,7 +33,13 @@ void Object::Print(std::ostream& os) { // NOLINT
void HeapObject::PrintHeader(std::ostream& os, const char* id) { // NOLINT
os << reinterpret_cast<void*>(this) << ": [" << id << "]";
os << reinterpret_cast<void*>(this) << ": [";
if (id != nullptr) {
os << id;
} else {
os << map()->instance_type();
}
os << "]";
}
......@@ -97,11 +103,13 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
case JS_OBJECT_TYPE: // fall through
case JS_SPECIAL_API_OBJECT_TYPE:
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
case JS_ARRAY_TYPE:
case JS_GENERATOR_OBJECT_TYPE:
case JS_PROMISE_TYPE:
JSObject::cast(this)->JSObjectPrint(os);
break;
case JS_ARRAY_TYPE:
JSArray::cast(this)->JSArrayPrint(os);
break;
case JS_REGEXP_TYPE:
JSRegExp::cast(this)->JSRegExpPrint(os);
break;
......@@ -396,16 +404,20 @@ static void JSObjectPrintHeader(std::ostream& os, JSObject* obj,
obj->PrintHeader(os, id);
// Don't call GetElementsKind, its validation code can cause the printer to
// fail when debugging.
os << "\n - map = " << reinterpret_cast<void*>(obj->map()) << " ["
<< ElementsKindToString(obj->map()->elements_kind());
if (obj->elements()->map() == obj->GetHeap()->fixed_cow_array_map()) {
os << " (COW)";
os << "\n - map = " << reinterpret_cast<void*>(obj->map()) << " [";
if (obj->HasFastProperties()) {
os << "FastProperties";
} else {
os << "DictionaryProperties";
}
PrototypeIterator iter(obj->GetIsolate(), obj);
os << "]\n - prototype = " << reinterpret_cast<void*>(iter.GetCurrent());
if (obj->elements()->length() > 0) {
os << "\n - elements = " << Brief(obj->elements());
os << "\n - elements = " << Brief(obj->elements()) << " ["
<< ElementsKindToString(obj->map()->elements_kind());
if (obj->elements()->map() == obj->GetHeap()->fixed_cow_array_map()) {
os << " (COW)";
}
os << "]";
}
......@@ -413,14 +425,19 @@ static void JSObjectPrintBody(std::ostream& os, JSObject* obj, // NOLINT
bool print_elements = true) {
os << "\n {";
obj->PrintProperties(os);
obj->PrintTransitions(os);
if (print_elements) obj->PrintElements(os);
os << "\n }\n";
}
void JSObject::JSObjectPrint(std::ostream& os) { // NOLINT
JSObjectPrintHeader(os, this, "JSObject");
JSObjectPrintHeader(os, this, nullptr);
JSObjectPrintBody(os, this);
}
void JSArray::JSArrayPrint(std::ostream& os) { // NOLINT
JSObjectPrintHeader(os, this, "JSArray");
os << "\n - length = " << Brief(this->length());
JSObjectPrintBody(os, this);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment