Upgrade V8 to version 4.9.385.28
https://chromium.googlesource.com/v8/v8/+/4.9.385.28
FPIIM-449
Change-Id: I4b2e74289d4bf3667f2f3dc8aa2e541f63e26eb4
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index e990559..b6dd425 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -2,14 +2,14 @@
// 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/objects.h"
+#include "src/bootstrapper.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"
+#include "src/regexp/jsregexp.h"
namespace v8 {
namespace internal {
@@ -22,6 +22,7 @@
} else {
HeapObject::cast(this)->HeapObjectVerify();
}
+ CHECK(!IsConstructor() || IsCallable());
}
@@ -36,6 +37,8 @@
void Smi::SmiVerify() {
CHECK(IsSmi());
+ CHECK(!IsCallable());
+ CHECK(!IsConstructor());
}
@@ -47,10 +50,6 @@
return;
}
- // TODO(yangguo): Use this check once crbug/436911 has been fixed.
- // DCHECK(!NeedsToEnsureDoubleAlignment() ||
- // IsAligned(OffsetFrom(address()), kDoubleAlignment));
-
switch (instance_type) {
case SYMBOL_TYPE:
Symbol::cast(this)->SymbolVerify();
@@ -62,26 +61,29 @@
case MUTABLE_HEAP_NUMBER_TYPE:
HeapNumber::cast(this)->HeapNumberVerify();
break;
+ case SIMD128_VALUE_TYPE:
+ Simd128Value::cast(this)->Simd128ValueVerify();
+ break;
case FIXED_ARRAY_TYPE:
FixedArray::cast(this)->FixedArrayVerify();
break;
case FIXED_DOUBLE_ARRAY_TYPE:
FixedDoubleArray::cast(this)->FixedDoubleArrayVerify();
break;
- case CONSTANT_POOL_ARRAY_TYPE:
- ConstantPoolArray::cast(this)->ConstantPoolArrayVerify();
- break;
case BYTE_ARRAY_TYPE:
ByteArray::cast(this)->ByteArrayVerify();
break;
+ case BYTECODE_ARRAY_TYPE:
+ BytecodeArray::cast(this)->BytecodeArrayVerify();
+ break;
+ case TRANSITION_ARRAY_TYPE:
+ TransitionArray::cast(this)->TransitionArrayVerify();
+ break;
case FREE_SPACE_TYPE:
FreeSpace::cast(this)->FreeSpaceVerify();
break;
#define VERIFY_TYPED_ARRAY(Type, type, TYPE, ctype, size) \
- case EXTERNAL_##TYPE##_ARRAY_TYPE: \
- External##Type##Array::cast(this)->External##Type##ArrayVerify(); \
- break; \
case FIXED_##TYPE##_ARRAY_TYPE: \
Fixed##Type##Array::cast(this)->FixedTypedArrayVerify(); \
break;
@@ -97,6 +99,7 @@
break;
case JS_OBJECT_TYPE:
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
+ case JS_PROMISE_TYPE:
JSObject::cast(this)->JSObjectVerify();
break;
case JS_GENERATOR_OBJECT_TYPE:
@@ -111,6 +114,9 @@
case JS_DATE_TYPE:
JSDate::cast(this)->JSDateVerify();
break;
+ case JS_BOUND_FUNCTION_TYPE:
+ JSBoundFunction::cast(this)->JSBoundFunctionVerify();
+ break;
case JS_FUNCTION_TYPE:
JSFunction::cast(this)->JSFunctionVerify();
break;
@@ -120,9 +126,6 @@
case JS_GLOBAL_OBJECT_TYPE:
JSGlobalObject::cast(this)->JSGlobalObjectVerify();
break;
- case JS_BUILTINS_OBJECT_TYPE:
- JSBuiltinsObject::cast(this)->JSBuiltinsObjectVerify();
- break;
case CELL_TYPE:
Cell::cast(this)->CellVerify();
break;
@@ -147,6 +150,9 @@
case JS_MAP_ITERATOR_TYPE:
JSMapIterator::cast(this)->JSMapIteratorVerify();
break;
+ case JS_ITERATOR_RESULT_TYPE:
+ JSIteratorResult::cast(this)->JSIteratorResultVerify();
+ break;
case JS_WEAK_MAP_TYPE:
JSWeakMap::cast(this)->JSWeakMapVerify();
break;
@@ -161,9 +167,6 @@
case JS_PROXY_TYPE:
JSProxy::cast(this)->JSProxyVerify();
break;
- case JS_FUNCTION_PROXY_TYPE:
- JSFunctionProxy::cast(this)->JSFunctionProxyVerify();
- break;
case FOREIGN_TYPE:
Foreign::cast(this)->ForeignVerify();
break;
@@ -207,9 +210,8 @@
void Symbol::SymbolVerify() {
CHECK(IsSymbol());
CHECK(HasHashCode());
- CHECK_GT(Hash(), 0);
+ CHECK_GT(Hash(), 0u);
CHECK(name()->IsUndefined() || name()->IsString());
- CHECK(flags()->IsSmi());
}
@@ -218,30 +220,38 @@
}
+void Simd128Value::Simd128ValueVerify() { CHECK(IsSimd128Value()); }
+
+
void ByteArray::ByteArrayVerify() {
CHECK(IsByteArray());
}
+void BytecodeArray::BytecodeArrayVerify() {
+ // TODO(oth): Walk bytecodes and immediate values to validate sanity.
+ CHECK(IsBytecodeArray());
+ CHECK(constant_pool()->IsFixedArray());
+ VerifyHeapPointer(constant_pool());
+}
+
+
void FreeSpace::FreeSpaceVerify() {
CHECK(IsFreeSpace());
}
-#define EXTERNAL_ARRAY_VERIFY(Type, type, TYPE, ctype, size) \
- void External##Type##Array::External##Type##ArrayVerify() { \
- CHECK(IsExternal##Type##Array()); \
- }
-
-TYPED_ARRAYS(EXTERNAL_ARRAY_VERIFY)
-#undef EXTERNAL_ARRAY_VERIFY
-
-
template <class Traits>
void FixedTypedArray<Traits>::FixedTypedArrayVerify() {
CHECK(IsHeapObject() &&
HeapObject::cast(this)->map()->instance_type() ==
Traits::kInstanceType);
+ if (base_pointer() == this) {
+ CHECK(external_pointer() ==
+ ExternalReference::fixed_typed_array_base_data_offset().address());
+ } else {
+ CHECK(base_pointer() == nullptr);
+ }
}
@@ -257,13 +267,13 @@
VerifyHeapPointer(properties());
VerifyHeapPointer(elements());
- if (GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS) {
+ if (HasSloppyArgumentsElements()) {
CHECK(this->elements()->IsFixedArray());
CHECK_GE(this->elements()->length(), 2);
}
if (HasFastProperties()) {
- int actual_unused_property_fields = map()->inobject_properties() +
+ int actual_unused_property_fields = map()->GetInObjectProperties() +
properties()->length() -
map()->NextFreePropertyIndex();
if (map()->unused_property_fields() != actual_unused_property_fields) {
@@ -276,7 +286,7 @@
}
DescriptorArray* descriptors = map()->instance_descriptors();
for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) {
- if (descriptors->GetDetails(i).type() == FIELD) {
+ if (descriptors->GetDetails(i).type() == DATA) {
Representation r = descriptors->GetDetails(i).representation();
FieldIndex index = FieldIndex::ForDescriptor(map(), i);
if (IsUnboxedDoubleField(index)) {
@@ -289,10 +299,16 @@
if (r.IsSmi()) DCHECK(value->IsSmi());
if (r.IsHeapObject()) DCHECK(value->IsHeapObject());
HeapType* field_type = descriptors->GetFieldType(i);
+ bool type_is_none = field_type->Is(HeapType::None());
+ bool type_is_any = HeapType::Any()->Is(field_type);
if (r.IsNone()) {
- CHECK(field_type->Is(HeapType::None()));
- } else if (!HeapType::Any()->Is(field_type)) {
- CHECK(!field_type->NowStable() || field_type->NowContains(value));
+ CHECK(type_is_none);
+ } else if (!type_is_any && !(type_is_none && r.IsHeapObject())) {
+ // If allocation folding is off then GC could happen during inner
+ // object literal creation and we will end up having and undefined
+ // value that does not match the field type.
+ CHECK(!field_type->NowStable() || field_type->NowContains(value) ||
+ (!FLAG_use_allocation_folding && value->IsUndefined()));
}
}
}
@@ -317,15 +333,16 @@
CHECK(instance_size() == kVariableSizeSentinel ||
(kPointerSize <= instance_size() &&
instance_size() < heap->Capacity()));
+ CHECK(GetBackPointer()->IsUndefined() ||
+ !Map::cast(GetBackPointer())->is_stable());
VerifyHeapPointer(prototype());
VerifyHeapPointer(instance_descriptors());
SLOW_DCHECK(instance_descriptors()->IsSortedNoDuplicates());
- if (HasTransitionArray()) {
- SLOW_DCHECK(transitions()->IsSortedNoDuplicates());
- SLOW_DCHECK(transitions()->IsConsistentWithBackPointers(this));
- }
- SLOW_DCHECK(!FLAG_unbox_double_fields ||
- layout_descriptor()->IsConsistentWithMap(this));
+ SLOW_DCHECK(TransitionArray::IsSortedNoDuplicates(this));
+ SLOW_DCHECK(TransitionArray::IsConsistentWithBackPointers(this));
+ // TODO(ishell): turn it back to SLOW_DCHECK.
+ CHECK(!FLAG_unbox_double_fields ||
+ layout_descriptor()->IsConsistentWithMap(this));
}
@@ -333,9 +350,8 @@
MapVerify();
CHECK(is_dictionary_map());
CHECK(instance_descriptors()->IsEmpty());
- CHECK_EQ(0, pre_allocated_property_fields());
CHECK_EQ(0, unused_property_fields());
- CHECK_EQ(StaticVisitorBase::GetVisitorId(this), visitor_id());
+ CHECK_EQ(Heap::GetStaticVisitorIdForMap(this), visitor_id());
}
@@ -343,10 +359,8 @@
if (!FLAG_omit_map_checks_for_leaf_maps) return;
if (!is_stable() ||
is_deprecated() ||
- HasTransitionArray() ||
is_dictionary_map()) {
- CHECK_EQ(0, dependent_code()->number_of_entries(
- DependentCode::kPrototypeCheckGroup));
+ CHECK(dependent_code()->IsEmpty(DependentCode::kPrototypeCheckGroup));
}
}
@@ -389,27 +403,27 @@
void FixedDoubleArray::FixedDoubleArrayVerify() {
for (int i = 0; i < length(); i++) {
if (!is_the_hole(i)) {
- double value = get_scalar(i);
- CHECK(!std::isnan(value) ||
- (bit_cast<uint64_t>(value) ==
- bit_cast<uint64_t>(canonical_not_the_hole_nan_as_double())) ||
- ((bit_cast<uint64_t>(value) & Double::kSignMask) != 0));
+ uint64_t value = get_representation(i);
+ uint64_t unexpected =
+ bit_cast<uint64_t>(std::numeric_limits<double>::quiet_NaN()) &
+ V8_UINT64_C(0x7FF8000000000000);
+ // Create implementation specific sNaN by inverting relevant bit.
+ unexpected ^= V8_UINT64_C(0x0008000000000000);
+ CHECK((value & V8_UINT64_C(0x7FF8000000000000)) != unexpected ||
+ (value & V8_UINT64_C(0x0007FFFFFFFFFFFF)) == V8_UINT64_C(0));
}
}
}
-void ConstantPoolArray::ConstantPoolArrayVerify() {
- CHECK(IsConstantPoolArray());
- 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));
+void TransitionArray::TransitionArrayVerify() {
+ for (int i = 0; i < length(); i++) {
+ Object* e = get(i);
+ VerifyPointer(e);
}
- ConstantPoolArray::Iterator heap_iter(this, ConstantPoolArray::HEAP_PTR);
- while (!heap_iter.is_finished()) {
- VerifyObjectField(OffsetOfElementAt(heap_iter.next_index()));
- }
+ CHECK_LE(LengthFor(number_of_transitions()), length());
+ CHECK(next_link()->IsUndefined() || next_link()->IsSmi() ||
+ next_link()->IsTransitionArray());
}
@@ -422,7 +436,6 @@
VerifyObjectField(kReceiverOffset);
VerifyObjectField(kOperandStackOffset);
VerifyObjectField(kContinuationOffset);
- VerifyObjectField(kStackHandlerIndexOffset);
}
@@ -491,8 +504,6 @@
void JSMessageObject::JSMessageObjectVerify() {
CHECK(IsJSMessageObject());
- CHECK(type()->IsString());
- CHECK(arguments()->IsJSArray());
VerifyObjectField(kStartPositionOffset);
VerifyObjectField(kEndPositionOffset);
VerifyObjectField(kArgumentsOffset);
@@ -536,6 +547,20 @@
}
+void JSBoundFunction::JSBoundFunctionVerify() {
+ CHECK(IsJSBoundFunction());
+ JSObjectVerify();
+ VerifyObjectField(kBoundThisOffset);
+ VerifyObjectField(kBoundTargetFunctionOffset);
+ VerifyObjectField(kBoundArgumentsOffset);
+ VerifyObjectField(kCreationContextOffset);
+ CHECK(bound_target_function()->IsCallable());
+ CHECK(creation_context()->IsNativeContext());
+ CHECK(IsCallable());
+ CHECK_EQ(IsConstructor(), bound_target_function()->IsConstructor());
+}
+
+
void JSFunction::JSFunctionVerify() {
CHECK(IsJSFunction());
VerifyObjectField(kPrototypeOrInitialMapOffset);
@@ -544,6 +569,7 @@
CHECK(next_function_link() == NULL ||
next_function_link()->IsUndefined() ||
next_function_link()->IsJSFunction());
+ CHECK(map()->is_callable());
}
@@ -555,6 +581,8 @@
VerifyObjectField(kFeedbackVectorOffset);
VerifyObjectField(kScopeInfoOffset);
VerifyObjectField(kInstanceClassNameOffset);
+ CHECK(function_data()->IsUndefined() || IsApiFunction() ||
+ HasBuiltinFunctionId() || HasBytecodeArray());
VerifyObjectField(kFunctionDataOffset);
VerifyObjectField(kScriptOffset);
VerifyObjectField(kDebugInfoOffset);
@@ -567,30 +595,18 @@
VerifyObjectField(JSGlobalProxy::kNativeContextOffset);
// Make sure that this object has no properties, elements.
CHECK_EQ(0, properties()->length());
- CHECK_EQ(FAST_HOLEY_SMI_ELEMENTS, GetElementsKind());
CHECK_EQ(0, FixedArray::cast(elements())->length());
}
void JSGlobalObject::JSGlobalObjectVerify() {
CHECK(IsJSGlobalObject());
- JSObjectVerify();
- for (int i = GlobalObject::kBuiltinsOffset;
- i < JSGlobalObject::kSize;
- i += kPointerSize) {
- VerifyObjectField(i);
+ // Do not check the dummy global object for the builtins.
+ if (GlobalDictionary::cast(properties())->NumberOfElements() == 0 &&
+ elements()->length() == 0) {
+ return;
}
-}
-
-
-void JSBuiltinsObject::JSBuiltinsObjectVerify() {
- CHECK(IsJSBuiltinsObject());
JSObjectVerify();
- for (int i = GlobalObject::kBuiltinsOffset;
- i < JSBuiltinsObject::kSize;
- i += kPointerSize) {
- VerifyObjectField(i);
- }
}
@@ -643,7 +659,6 @@
void PropertyCell::PropertyCellVerify() {
CHECK(IsPropertyCell());
VerifyObjectField(kValueOffset);
- VerifyObjectField(kTypeOffset);
}
@@ -675,6 +690,7 @@
void Code::VerifyEmbeddedObjectsDependency() {
if (!CanContainWeakObjects()) return;
+ WeakCell* cell = CachedWeakCell();
DisallowHeapAllocation no_gc;
Isolate* isolate = GetIsolate();
HandleScope scope(isolate);
@@ -685,13 +701,13 @@
if (obj->IsMap()) {
Map* map = Map::cast(obj);
CHECK(map->dependent_code()->Contains(DependentCode::kWeakCodeGroup,
- this));
+ cell));
} else if (obj->IsJSObject()) {
- Object* raw_table = GetIsolate()->heap()->weak_object_to_code_table();
- WeakHashTable* table = WeakHashTable::cast(raw_table);
- Handle<Object> key_obj(obj, isolate);
- CHECK(DependentCode::cast(table->Lookup(key_obj))->Contains(
- DependentCode::kWeakCodeGroup, this));
+ WeakHashTable* table =
+ GetIsolate()->heap()->weak_object_to_code_table();
+ Handle<HeapObject> key_obj(HeapObject::cast(obj), isolate);
+ CHECK(DependentCode::cast(table->Lookup(key_obj))
+ ->Contains(DependentCode::kWeakCodeGroup, cell));
}
}
}
@@ -749,6 +765,14 @@
}
+void JSIteratorResult::JSIteratorResultVerify() {
+ CHECK(IsJSIteratorResult());
+ JSObjectVerify();
+ VerifyPointer(done());
+ VerifyPointer(value());
+}
+
+
void JSWeakMap::JSWeakMapVerify() {
CHECK(IsJSWeakMap());
JSObjectVerify();
@@ -811,16 +835,14 @@
void JSProxy::JSProxyVerify() {
CHECK(IsJSProxy());
+ VerifyPointer(target());
VerifyPointer(handler());
+ CHECK_EQ(target()->IsCallable(), map()->is_callable());
+ CHECK_EQ(target()->IsConstructor(), map()->is_constructor());
CHECK(hash()->IsSmi() || hash()->IsUndefined());
-}
-
-
-void JSFunctionProxy::JSFunctionProxyVerify() {
- CHECK(IsJSFunctionProxy());
- JSProxyVerify();
- VerifyPointer(call_trap());
- VerifyPointer(construct_trap());
+ CHECK(map()->prototype()->IsNull());
+ // There should be no properties on a Proxy.
+ CHECK_EQ(0, map()->NumberOfOwnDescriptors());
}
@@ -840,22 +862,22 @@
CHECK(buffer()->IsJSArrayBuffer() || buffer()->IsUndefined()
|| buffer() == Smi::FromInt(0));
- VerifyPointer(byte_offset());
- CHECK(byte_offset()->IsSmi() || byte_offset()->IsHeapNumber()
- || byte_offset()->IsUndefined());
+ VerifyPointer(raw_byte_offset());
+ CHECK(raw_byte_offset()->IsSmi() || raw_byte_offset()->IsHeapNumber() ||
+ raw_byte_offset()->IsUndefined());
- VerifyPointer(byte_length());
- CHECK(byte_length()->IsSmi() || byte_length()->IsHeapNumber()
- || byte_length()->IsUndefined());
+ VerifyPointer(raw_byte_length());
+ CHECK(raw_byte_length()->IsSmi() || raw_byte_length()->IsHeapNumber() ||
+ raw_byte_length()->IsUndefined());
}
void JSTypedArray::JSTypedArrayVerify() {
CHECK(IsJSTypedArray());
JSArrayBufferViewVerify();
- VerifyPointer(length());
- CHECK(length()->IsSmi() || length()->IsHeapNumber()
- || length()->IsUndefined());
+ VerifyPointer(raw_length());
+ CHECK(raw_length()->IsSmi() || raw_length()->IsHeapNumber() ||
+ raw_length()->IsUndefined());
VerifyPointer(elements());
}
@@ -878,13 +900,31 @@
}
+void PrototypeInfo::PrototypeInfoVerify() {
+ CHECK(IsPrototypeInfo());
+ if (prototype_users()->IsWeakFixedArray()) {
+ WeakFixedArray::cast(prototype_users())->FixedArrayVerify();
+ } else {
+ CHECK(prototype_users()->IsSmi());
+ }
+ CHECK(validity_cell()->IsCell() || validity_cell()->IsSmi());
+}
+
+
void AccessorInfo::AccessorInfoVerify() {
VerifyPointer(name());
- VerifyPointer(flag());
VerifyPointer(expected_receiver_type());
}
+void SloppyBlockWithEvalContextExtension::
+ SloppyBlockWithEvalContextExtensionVerify() {
+ CHECK(IsSloppyBlockWithEvalContextExtension());
+ VerifyObjectField(kScopeInfoOffset);
+ VerifyObjectField(kExtensionOffset);
+}
+
+
void ExecutableAccessorInfo::ExecutableAccessorInfoVerify() {
CHECK(IsExecutableAccessorInfo());
AccessorInfoVerify();
@@ -894,19 +934,6 @@
}
-void DeclaredAccessorDescriptor::DeclaredAccessorDescriptorVerify() {
- CHECK(IsDeclaredAccessorDescriptor());
- VerifyPointer(serialized_data());
-}
-
-
-void DeclaredAccessorInfo::DeclaredAccessorInfoVerify() {
- CHECK(IsDeclaredAccessorInfo());
- AccessorInfoVerify();
- VerifyPointer(descriptor());
-}
-
-
void AccessorPair::AccessorPairVerify() {
CHECK(IsAccessorPair());
VerifyPointer(getter());
@@ -918,6 +945,7 @@
CHECK(IsAccessCheckInfo());
VerifyPointer(named_callback());
VerifyPointer(indexed_callback());
+ VerifyPointer(callback());
VerifyPointer(data());
}
@@ -971,19 +999,6 @@
}
-void SignatureInfo::SignatureInfoVerify() {
- CHECK(IsSignatureInfo());
- VerifyPointer(receiver());
- VerifyPointer(args());
-}
-
-
-void TypeSwitchInfo::TypeSwitchInfoVerify() {
- CHECK(IsTypeSwitchInfo());
- VerifyPointer(types());
-}
-
-
void AllocationSite::AllocationSiteVerify() {
CHECK(IsAllocationSite());
}
@@ -1000,38 +1015,8 @@
CHECK(IsScript());
VerifyPointer(source());
VerifyPointer(name());
- line_offset()->SmiVerify();
- column_offset()->SmiVerify();
VerifyPointer(wrapper());
- type()->SmiVerify();
VerifyPointer(line_ends());
- VerifyPointer(id());
-}
-
-
-void JSFunctionResultCache::JSFunctionResultCacheVerify() {
- JSFunction::cast(get(kFactoryIndex))->ObjectVerify();
-
- int size = Smi::cast(get(kCacheSizeIndex))->value();
- CHECK(kEntriesIndex <= size);
- CHECK(size <= length());
- CHECK_EQ(0, size % kEntrySize);
-
- int finger = Smi::cast(get(kFingerIndex))->value();
- CHECK(kEntriesIndex <= finger);
- CHECK((finger < size) || (finger == kEntriesIndex && finger == size));
- CHECK_EQ(0, finger % kEntrySize);
-
- if (FLAG_enable_slow_asserts) {
- for (int i = kEntriesIndex; i < size; i++) {
- CHECK(!get(i)->IsTheHole());
- get(i)->ObjectVerify();
- }
- for (int i = size; i < length(); i++) {
- CHECK(get(i)->IsTheHole());
- get(i)->ObjectVerify();
- }
- }
}
@@ -1053,7 +1038,6 @@
void DebugInfo::DebugInfoVerify() {
CHECK(IsDebugInfo());
VerifyPointer(shared());
- VerifyPointer(original_code());
VerifyPointer(code());
VerifyPointer(break_points());
}
@@ -1061,9 +1045,6 @@
void BreakPointInfo::BreakPointInfoVerify() {
CHECK(IsBreakPointInfo());
- code_position()->SmiVerify();
- source_position()->SmiVerify();
- statement_position()->SmiVerify();
VerifyPointer(break_point_objects());
}
#endif // VERIFY_HEAP
@@ -1077,6 +1058,11 @@
info->number_of_objects_with_fast_properties_++;
info->number_of_fast_used_fields_ += map()->NextFreePropertyIndex();
info->number_of_fast_unused_fields_ += map()->unused_property_fields();
+ } else if (IsJSGlobalObject()) {
+ GlobalDictionary* dict = global_dictionary();
+ info->number_of_slow_used_properties_ += dict->NumberOfElements();
+ info->number_of_slow_unused_properties_ +=
+ dict->Capacity() - dict->NumberOfElements();
} else {
NameDictionary* dict = property_dictionary();
info->number_of_slow_used_properties_ += dict->NumberOfElements();
@@ -1105,7 +1091,6 @@
}
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
- case EXTERNAL_##TYPE##_ELEMENTS: \
case TYPE##_ELEMENTS:
TYPED_ARRAYS(TYPED_ARRAY_CASE)
@@ -1122,7 +1107,8 @@
dict->Capacity() - dict->NumberOfElements();
break;
}
- case SLOPPY_ARGUMENTS_ELEMENTS:
+ case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
+ case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
break;
}
}
@@ -1188,37 +1174,16 @@
}
-bool LayoutDescriptor::IsConsistentWithMap(Map* map) {
- if (FLAG_unbox_double_fields) {
- DescriptorArray* descriptors = map->instance_descriptors();
- int nof_descriptors = map->NumberOfOwnDescriptors();
- for (int i = 0; i < nof_descriptors; i++) {
- PropertyDetails details = descriptors->GetDetails(i);
- if (details.type() != FIELD) continue;
- FieldIndex field_index = FieldIndex::ForDescriptor(map, i);
- bool tagged_expected =
- !field_index.is_inobject() || !details.representation().IsDouble();
- for (int bit = 0; bit < details.field_width_in_words(); bit++) {
- bool tagged_actual = IsTagged(details.field_index() + bit);
- DCHECK_EQ(tagged_expected, tagged_actual);
- if (tagged_actual != tagged_expected) return false;
- }
- }
- }
- return true;
-}
-
-
bool TransitionArray::IsSortedNoDuplicates(int valid_entries) {
DCHECK(valid_entries == -1);
Name* prev_key = NULL;
- PropertyKind prev_kind = DATA;
+ PropertyKind prev_kind = kData;
PropertyAttributes prev_attributes = NONE;
uint32_t prev_hash = 0;
for (int i = 0; i < number_of_transitions(); i++) {
Name* key = GetSortedKey(i);
uint32_t hash = key->Hash();
- PropertyKind kind = DATA;
+ PropertyKind kind = kData;
PropertyAttributes attributes = NONE;
if (!IsSpecialTransition(key)) {
Map* target = GetTarget(i);
@@ -1245,37 +1210,133 @@
}
+// static
+bool TransitionArray::IsSortedNoDuplicates(Map* map) {
+ Object* raw_transitions = map->raw_transitions();
+ if (IsFullTransitionArray(raw_transitions)) {
+ return TransitionArray::cast(raw_transitions)->IsSortedNoDuplicates();
+ }
+ // Simple and non-existent transitions are always sorted.
+ return true;
+}
+
+
static bool CheckOneBackPointer(Map* current_map, Object* target) {
return !target->IsMap() || Map::cast(target)->GetBackPointer() == current_map;
}
-bool TransitionArray::IsConsistentWithBackPointers(Map* current_map) {
- for (int i = 0; i < number_of_transitions(); ++i) {
- if (!CheckOneBackPointer(current_map, GetTarget(i))) return false;
+// static
+bool TransitionArray::IsConsistentWithBackPointers(Map* map) {
+ Object* transitions = map->raw_transitions();
+ for (int i = 0; i < TransitionArray::NumberOfTransitions(transitions); ++i) {
+ Map* target = TransitionArray::GetTarget(transitions, i);
+ if (!CheckOneBackPointer(map, target)) return false;
}
return true;
}
-void Code::VerifyEmbeddedObjectsInFullCode() {
- // Check that no context-specific object has been embedded.
- Heap* heap = GetIsolate()->heap();
- int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
- for (RelocIterator it(this, mask); !it.done(); it.next()) {
- Object* obj = it.rinfo()->target_object();
- if (obj->IsCell()) obj = Cell::cast(obj)->value();
- if (obj->IsPropertyCell()) obj = PropertyCell::cast(obj)->value();
- if (!obj->IsHeapObject()) continue;
- Map* map = obj->IsMap() ? Map::cast(obj) : HeapObject::cast(obj)->map();
- int i = 0;
- while (map != heap->roots_array_start()[i++]) {
- CHECK_LT(i, Heap::kStrongRootListLength);
- }
+// Estimates if there is a path from the object to a context.
+// This function is not precise, and can return false even if
+// there is a path to a context.
+bool CanLeak(Object* obj, Heap* heap, bool skip_weak_cell) {
+ if (!obj->IsHeapObject()) return false;
+ if (obj->IsWeakCell()) {
+ if (skip_weak_cell) return false;
+ return CanLeak(WeakCell::cast(obj)->value(), heap, skip_weak_cell);
}
+ if (obj->IsCell()) {
+ return CanLeak(Cell::cast(obj)->value(), heap, skip_weak_cell);
+ }
+ if (obj->IsPropertyCell()) {
+ return CanLeak(PropertyCell::cast(obj)->value(), heap, skip_weak_cell);
+ }
+ if (obj->IsContext()) return true;
+ if (obj->IsMap()) {
+ Map* map = Map::cast(obj);
+ for (int i = 0; i < Heap::kStrongRootListLength; i++) {
+ Heap::RootListIndex root_index = static_cast<Heap::RootListIndex>(i);
+ if (map == heap->root(root_index)) return false;
+ }
+ return true;
+ }
+ return CanLeak(HeapObject::cast(obj)->map(), heap, skip_weak_cell);
+}
+
+
+void Code::VerifyEmbeddedObjects(VerifyMode mode) {
+ if (kind() == OPTIMIZED_FUNCTION) return;
+ Heap* heap = GetIsolate()->heap();
+ int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
+ RelocInfo::ModeMask(RelocInfo::CELL);
+ bool skip_weak_cell = (mode == kNoContextSpecificPointers) ? false : true;
+ for (RelocIterator it(this, mask); !it.done(); it.next()) {
+ Object* target = it.rinfo()->rmode() == RelocInfo::CELL
+ ? it.rinfo()->target_cell()
+ : it.rinfo()->target_object();
+ CHECK(!CanLeak(target, heap, skip_weak_cell));
+ }
+}
+
+
+// Verify that the debugger can redirect old code to the new code.
+void Code::VerifyRecompiledCode(Code* old_code, Code* new_code) {
+ if (old_code->kind() != FUNCTION) return;
+ if (new_code->kind() != FUNCTION) return;
+ Isolate* isolate = old_code->GetIsolate();
+ // Do not verify during bootstrapping. We may replace code using %SetCode.
+ if (isolate->bootstrapper()->IsActive()) return;
+
+ static const int mask = RelocInfo::kCodeTargetMask;
+ RelocIterator old_it(old_code, mask);
+ RelocIterator new_it(new_code, mask);
+ Code* stack_check = isolate->builtins()->builtin(Builtins::kStackCheck);
+
+ while (!old_it.done()) {
+ RelocInfo* rinfo = old_it.rinfo();
+ Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
+ CHECK(!target->is_handler() && !target->is_inline_cache_stub());
+ if (target == stack_check) break;
+ old_it.next();
+ }
+
+ while (!new_it.done()) {
+ RelocInfo* rinfo = new_it.rinfo();
+ Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
+ CHECK(!target->is_handler() && !target->is_inline_cache_stub());
+ if (target == stack_check) break;
+ new_it.next();
+ }
+
+ // Either both are done because there is no stack check.
+ // Or we are past the prologue for both.
+ CHECK_EQ(new_it.done(), old_it.done());
+
+ // After the prologue, each call in the old code has a corresponding call
+ // in the new code.
+ while (!old_it.done() && !new_it.done()) {
+ Code* old_target =
+ Code::GetCodeFromTargetAddress(old_it.rinfo()->target_address());
+ Code* new_target =
+ Code::GetCodeFromTargetAddress(new_it.rinfo()->target_address());
+ CHECK_EQ(old_target->kind(), new_target->kind());
+ // Check call target for equality unless it's an IC or an interrupt check.
+ // In both cases they may be patched to be something else.
+ if (!old_target->is_handler() && !old_target->is_inline_cache_stub() &&
+ new_target != isolate->builtins()->builtin(Builtins::kInterruptCheck)) {
+ CHECK_EQ(old_target, new_target);
+ }
+ old_it.next();
+ new_it.next();
+ }
+
+ // Both are done at the same time.
+ CHECK_EQ(new_it.done(), old_it.done());
}
#endif // DEBUG
-} } // namespace v8::internal
+} // namespace internal
+} // namespace v8