// Copyright 2012 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "v8.h"
-
-#include "disassembler.h"
-#include "disasm.h"
-#include "jsregexp.h"
-#include "macro-assembler.h"
-#include "objects-visiting.h"
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#include "src/disasm.h"
+#include "src/disassembler.h"
+#include "src/heap/objects-visiting.h"
+#include "src/jsregexp.h"
+#include "src/macro-assembler.h"
+#include "src/ostreams.h"
namespace v8 {
namespace internal {
#ifdef VERIFY_HEAP
-void MaybeObject::Verify() {
- Object* this_as_object;
- if (ToObject(&this_as_object)) {
- if (this_as_object->IsSmi()) {
- Smi::cast(this_as_object)->SmiVerify();
- } else {
- HeapObject::cast(this_as_object)->HeapObjectVerify();
- }
+void Object::ObjectVerify() {
+ if (IsSmi()) {
+ Smi::cast(this)->SmiVerify();
} else {
- Failure::cast(this)->FailureVerify();
+ HeapObject::cast(this)->HeapObjectVerify();
}
}
}
-void Failure::FailureVerify() {
- CHECK(IsFailure());
-}
-
-
void HeapObject::HeapObjectVerify() {
InstanceType instance_type = map()->instance_type();
Map::cast(this)->MapVerify();
break;
case HEAP_NUMBER_TYPE:
+ case MUTABLE_HEAP_NUMBER_TYPE:
HeapNumber::cast(this)->HeapNumberVerify();
break;
case FLOAT32x4_TYPE:
Float32x4::cast(this)->Float32x4Verify();
break;
+ case FLOAT64x2_TYPE:
+ Float64x2::cast(this)->Float64x2Verify();
+ break;
case INT32x4_TYPE:
Int32x4::cast(this)->Int32x4Verify();
break;
case JS_MAP_TYPE:
JSMap::cast(this)->JSMapVerify();
break;
+ case JS_SET_ITERATOR_TYPE:
+ JSSetIterator::cast(this)->JSSetIteratorVerify();
+ break;
+ case JS_MAP_ITERATOR_TYPE:
+ JSMapIterator::cast(this)->JSMapIteratorVerify();
+ break;
case JS_WEAK_MAP_TYPE:
JSWeakMap::cast(this)->JSWeakMapVerify();
break;
void HeapNumber::HeapNumberVerify() {
- CHECK(IsHeapNumber());
+ CHECK(IsHeapNumber() || IsMutableHeapNumber());
}
}
+void Float64x2::Float64x2Verify() {
+ CHECK(IsFloat64x2());
+}
+
+
void Int32x4::Int32x4Verify() {
CHECK(IsInt32x4());
}
for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) {
if (descriptors->GetDetails(i).type() == FIELD) {
Representation r = descriptors->GetDetails(i).representation();
- int field = descriptors->GetFieldIndex(i);
- Object* value = RawFastPropertyAt(field);
- if (r.IsDouble()) ASSERT(value->IsHeapNumber());
+ FieldIndex index = FieldIndex::ForDescriptor(map(), i);
+ Object* value = RawFastPropertyAt(index);
+ if (r.IsDouble()) DCHECK(value->IsMutableHeapNumber());
if (value->IsUninitialized()) continue;
- if (r.IsSmi()) ASSERT(value->IsSmi());
- if (r.IsHeapObject()) ASSERT(value->IsHeapObject());
+ if (r.IsSmi()) DCHECK(value->IsSmi());
+ if (r.IsHeapObject()) DCHECK(value->IsHeapObject());
+ HeapType* field_type = descriptors->GetFieldType(i);
+ if (r.IsNone()) {
+ CHECK(field_type->Is(HeapType::None()));
+ } else if (!HeapType::Any()->Is(field_type)) {
+ CHECK(!field_type->NowStable() || field_type->NowContains(value));
+ }
}
}
}
instance_size() < heap->Capacity()));
VerifyHeapPointer(prototype());
VerifyHeapPointer(instance_descriptors());
- SLOW_ASSERT(instance_descriptors()->IsSortedNoDuplicates());
+ SLOW_DCHECK(instance_descriptors()->IsSortedNoDuplicates());
if (HasTransitionArray()) {
- SLOW_ASSERT(transitions()->IsSortedNoDuplicates());
- SLOW_ASSERT(transitions()->IsConsistentWithBackPointers(this));
+ SLOW_DCHECK(transitions()->IsSortedNoDuplicates());
+ SLOW_DCHECK(transitions()->IsConsistentWithBackPointers(this));
}
}
-void Map::SharedMapVerify() {
+void Map::DictionaryMapVerify() {
MapVerify();
- CHECK(is_shared());
+ CHECK(is_dictionary_map());
CHECK(instance_descriptors()->IsEmpty());
CHECK_EQ(0, pre_allocated_property_fields());
CHECK_EQ(0, unused_property_fields());
void TypeFeedbackInfo::TypeFeedbackInfoVerify() {
VerifyObjectField(kStorage1Offset);
VerifyObjectField(kStorage2Offset);
- VerifyHeapPointer(feedback_vector());
+ VerifyObjectField(kStorage3Offset);
}
void FixedArray::FixedArrayVerify() {
for (int i = 0; i < length(); i++) {
Object* e = get(i);
- if (e->IsHeapObject()) {
- VerifyHeapPointer(e);
- } else {
- e->Verify();
- }
+ VerifyPointer(e);
}
}
void ConstantPoolArray::ConstantPoolArrayVerify() {
CHECK(IsConstantPoolArray());
- for (int i = 0; i < count_of_code_ptr_entries(); i++) {
- Address code_entry = get_code_ptr_entry(first_code_ptr_index() + i);
+ ConstantPoolArray::Iterator code_iter(this, ConstantPoolArray::CODE_PTR);
+ while (!code_iter.is_finished()) {
+ Address code_entry = get_code_ptr_entry(code_iter.next_index());
VerifyPointer(Code::GetCodeFromTargetAddress(code_entry));
}
- for (int i = 0; i < count_of_heap_ptr_entries(); i++) {
- VerifyObjectField(OffsetOfElementAt(first_heap_ptr_index() + i));
+ ConstantPoolArray::Iterator heap_iter(this, ConstantPoolArray::HEAP_PTR);
+ while (!heap_iter.is_finished()) {
+ VerifyObjectField(OffsetOfElementAt(heap_iter.next_index()));
}
}
CHECK(this->second() == GetHeap()->empty_string() ||
this->second()->IsString());
CHECK(this->length() >= ConsString::kMinLength);
+ CHECK(this->length() == this->first()->length() + this->second()->length());
if (this->IsFlat()) {
// A flat cons can only be created by String::SlowTryFlatten.
// Afterwards, the first part may be externalized.
VerifyObjectField(kNameOffset);
VerifyObjectField(kCodeOffset);
VerifyObjectField(kOptimizedCodeMapOffset);
+ VerifyObjectField(kFeedbackVectorOffset);
VerifyObjectField(kScopeInfoOffset);
VerifyObjectField(kInstanceClassNameOffset);
VerifyObjectField(kFunctionDataOffset);
VerifyObjectField(JSGlobalProxy::kNativeContextOffset);
// Make sure that this object has no properties, elements.
CHECK_EQ(0, properties()->length());
- CHECK(HasFastObjectElements());
+ CHECK(HasFastSmiElements());
CHECK_EQ(0, FixedArray::cast(elements())->length());
}
void Oddball::OddballVerify() {
CHECK(IsOddball());
+ Heap* heap = GetHeap();
VerifyHeapPointer(to_string());
Object* number = to_number();
if (number->IsHeapObject()) {
- CHECK(number == HeapObject::cast(number)->GetHeap()->nan_value());
+ CHECK(number == heap->nan_value());
} else {
CHECK(number->IsSmi());
int value = Smi::cast(number)->value();
// Hidden oddballs have negative smis.
- const int kLeastHiddenOddballNumber = -4;
+ const int kLeastHiddenOddballNumber = -5;
CHECK_LE(value, 1);
CHECK(value >= kLeastHiddenOddballNumber);
}
+ if (map() == heap->undefined_map()) {
+ CHECK(this == heap->undefined_value());
+ } else if (map() == heap->the_hole_map()) {
+ CHECK(this == heap->the_hole_value());
+ } else if (map() == heap->null_map()) {
+ CHECK(this == heap->null_value());
+ } else if (map() == heap->boolean_map()) {
+ CHECK(this == heap->true_value() ||
+ this == heap->false_value());
+ } else if (map() == heap->uninitialized_map()) {
+ CHECK(this == heap->uninitialized_value());
+ } else if (map() == heap->no_interceptor_result_sentinel_map()) {
+ CHECK(this == heap->no_interceptor_result_sentinel());
+ } else if (map() == heap->arguments_marker_map()) {
+ CHECK(this == heap->arguments_marker());
+ } else if (map() == heap->termination_exception_map()) {
+ CHECK(this == heap->termination_exception());
+ } else if (map() == heap->exception_map()) {
+ CHECK(this == heap->exception());
+ } else {
+ UNREACHABLE();
+ }
}
void Code::CodeVerify() {
CHECK(IsAligned(reinterpret_cast<intptr_t>(instruction_start()),
kCodeAlignment));
- relocation_info()->Verify();
+ relocation_info()->ObjectVerify();
Address last_gc_pc = NULL;
+ Isolate* isolate = GetIsolate();
for (RelocIterator it(this); !it.done(); it.next()) {
- it.rinfo()->Verify();
+ it.rinfo()->Verify(isolate);
// Ensure that GC will not iterate twice over the same pointer.
if (RelocInfo::IsGCRelocMode(it.rinfo()->rmode())) {
CHECK(it.rinfo()->pc() != last_gc_pc);
last_gc_pc = it.rinfo()->pc();
}
}
+ CHECK(raw_type_feedback_info() == Smi::FromInt(0) ||
+ raw_type_feedback_info()->IsSmi() == IsCodeStubOrIC());
}
void Code::VerifyEmbeddedObjectsDependency() {
+ if (!CanContainWeakObjects()) return;
+ DisallowHeapAllocation no_gc;
+ Isolate* isolate = GetIsolate();
+ HandleScope scope(isolate);
int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
Object* obj = it.rinfo()->target_object();
if (IsWeakObject(obj)) {
if (obj->IsMap()) {
Map* map = Map::cast(obj);
- CHECK(map->dependent_code()->Contains(
- DependentCode::kWeaklyEmbeddedGroup, this));
+ DependentCode::DependencyGroup group = is_optimized_code() ?
+ DependentCode::kWeakCodeGroup : DependentCode::kWeakICGroup;
+ CHECK(map->dependent_code()->Contains(group, this));
} else if (obj->IsJSObject()) {
Object* raw_table = GetIsolate()->heap()->weak_object_to_code_table();
WeakHashTable* table = WeakHashTable::cast(raw_table);
- CHECK(DependentCode::cast(table->Lookup(obj))->Contains(
- DependentCode::kWeaklyEmbeddedGroup, this));
+ Handle<Object> key_obj(obj, isolate);
+ CHECK(DependentCode::cast(table->Lookup(key_obj))->Contains(
+ DependentCode::kWeakCodeGroup, this));
}
}
}
CHECK(IsJSSet());
JSObjectVerify();
VerifyHeapPointer(table());
- CHECK(table()->IsHashTable() || table()->IsUndefined());
+ CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
+ // TODO(arv): Verify OrderedHashTable too.
}
CHECK(IsJSMap());
JSObjectVerify();
VerifyHeapPointer(table());
- CHECK(table()->IsHashTable() || table()->IsUndefined());
+ CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
+ // TODO(arv): Verify OrderedHashTable too.
+}
+
+
+void JSSetIterator::JSSetIteratorVerify() {
+ CHECK(IsJSSetIterator());
+ JSObjectVerify();
+ VerifyHeapPointer(table());
+ CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
+ CHECK(index()->IsSmi() || index()->IsUndefined());
+ CHECK(kind()->IsSmi() || kind()->IsUndefined());
+}
+
+
+void JSMapIterator::JSMapIteratorVerify() {
+ CHECK(IsJSMapIterator());
+ JSObjectVerify();
+ VerifyHeapPointer(table());
+ CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
+ CHECK(index()->IsSmi() || index()->IsUndefined());
+ CHECK(kind()->IsSmi() || kind()->IsUndefined());
}
void Box::BoxVerify() {
CHECK(IsBox());
- value()->Verify();
+ value()->ObjectVerify();
}
CHECK(IsAccessorPair());
VerifyPointer(getter());
VerifyPointer(setter());
- VerifySmiField(kAccessFlagsOffset);
}
void JSFunctionResultCache::JSFunctionResultCacheVerify() {
- JSFunction::cast(get(kFactoryIndex))->Verify();
+ JSFunction::cast(get(kFactoryIndex))->ObjectVerify();
int size = Smi::cast(get(kCacheSizeIndex))->value();
CHECK(kEntriesIndex <= size);
if (FLAG_enable_slow_asserts) {
for (int i = kEntriesIndex; i < size; i++) {
CHECK(!get(i)->IsTheHole());
- get(i)->Verify();
+ get(i)->ObjectVerify();
}
for (int i = size; i < length(); i++) {
CHECK(get(i)->IsTheHole());
- get(i)->Verify();
+ get(i)->ObjectVerify();
}
}
}
void NormalizedMapCache::NormalizedMapCacheVerify() {
- FixedArray::cast(this)->Verify();
+ FixedArray::cast(this)->FixedArrayVerify();
if (FLAG_enable_slow_asserts) {
for (int i = 0; i < length(); i++) {
- Object* e = get(i);
+ Object* e = FixedArray::get(i);
if (e->IsMap()) {
- Map::cast(e)->SharedMapVerify();
+ Map::cast(e)->DictionaryMapVerify();
} else {
CHECK(e->IsUndefined());
}
}
-#ifdef ENABLE_DEBUGGER_SUPPORT
void DebugInfo::DebugInfoVerify() {
CHECK(IsDebugInfo());
VerifyPointer(shared());
statement_position()->SmiVerify();
VerifyPointer(break_point_objects());
}
-#endif // ENABLE_DEBUGGER_SUPPORT
#endif // VERIFY_HEAP
#ifdef DEBUG
for (int i = 0; i < number_of_descriptors(); i++) {
Name* key = GetSortedKey(i);
if (key == current_key) {
- PrintDescriptors();
+ OFStream os(stdout);
+ PrintDescriptors(os);
return false;
}
current_key = key;
uint32_t hash = GetSortedKey(i)->Hash();
if (hash < current) {
- PrintDescriptors();
+ OFStream os(stdout);
+ PrintDescriptors(os);
return false;
}
current = hash;
bool TransitionArray::IsSortedNoDuplicates(int valid_entries) {
- ASSERT(valid_entries == -1);
+ DCHECK(valid_entries == -1);
Name* current_key = NULL;
uint32_t current = 0;
for (int i = 0; i < number_of_transitions(); i++) {
Name* key = GetSortedKey(i);
if (key == current_key) {
- PrintTransitions();
+ OFStream os(stdout);
+ PrintTransitions(os);
return false;
}
current_key = key;
uint32_t hash = GetSortedKey(i)->Hash();
if (hash < current) {
- PrintTransitions();
+ OFStream os(stdout);
+ PrintTransitions(os);
return false;
}
current = hash;