Commit 779e87b8 authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

Track up to 5 stable maps as field type.

R=svenpanne@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20831 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 556aea63
......@@ -430,13 +430,22 @@ void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
} else if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
HeapType* field_type = descriptors->GetFieldType(descriptor);
if (field_type->IsClass()) {
__ CheckMap(value_reg, scratch1, field_type->AsClass()->Map(),
miss_label, DO_SMI_CHECK);
} else {
ASSERT(HeapType::Any()->Is(field_type));
__ JumpIfSmi(value_reg, miss_label);
HeapType* field_type = descriptors->GetFieldType(descriptor);
HeapType::Iterator<Map> it = field_type->Classes();
if (!it.Done()) {
__ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
Label do_store;
while (true) {
__ CompareMap(scratch1, it.Current(), &do_store);
it.Advance();
if (it.Done()) {
__ b(ne, miss_label);
break;
}
__ b(eq, &do_store);
}
__ bind(&do_store);
}
} else if (representation.IsDouble()) {
Label do_store, heap_number;
......@@ -599,13 +608,22 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
HeapType* field_type = lookup->GetFieldType();
if (field_type->IsClass()) {
__ CheckMap(value_reg, scratch1, field_type->AsClass()->Map(),
miss_label, DO_SMI_CHECK);
} else {
ASSERT(HeapType::Any()->Is(field_type));
__ JumpIfSmi(value_reg, miss_label);
HeapType* field_type = lookup->GetFieldType();
HeapType::Iterator<Map> it = field_type->Classes();
if (!it.Done()) {
__ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
Label do_store;
while (true) {
__ CompareMap(scratch1, it.Current(), &do_store);
it.Advance();
if (it.Done()) {
__ b(ne, miss_label);
break;
}
__ b(eq, &do_store);
}
__ bind(&do_store);
}
} else if (representation.IsDouble()) {
// Load the double storage.
......
......@@ -392,13 +392,22 @@ void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
} else if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
HeapType* field_type = descriptors->GetFieldType(descriptor);
if (field_type->IsClass()) {
__ CheckMap(value_reg, scratch1, field_type->AsClass()->Map(),
miss_label, DO_SMI_CHECK);
} else {
ASSERT(HeapType::Any()->Is(field_type));
__ JumpIfSmi(value_reg, miss_label);
HeapType* field_type = descriptors->GetFieldType(descriptor);
HeapType::Iterator<Map> it = field_type->Classes();
if (!it.Done()) {
__ Ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
Label do_store;
while (true) {
__ CompareMap(scratch1, it.Current());
it.Advance();
if (it.Done()) {
__ B(ne, miss_label);
break;
}
__ B(eq, &do_store);
}
__ Bind(&do_store);
}
} else if (representation.IsDouble()) {
UseScratchRegisterScope temps(masm);
......@@ -548,13 +557,22 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
HeapType* field_type = lookup->GetFieldType();
if (field_type->IsClass()) {
__ CheckMap(value_reg, scratch1, field_type->AsClass()->Map(),
miss_label, DO_SMI_CHECK);
} else {
ASSERT(HeapType::Any()->Is(field_type));
__ JumpIfSmi(value_reg, miss_label);
HeapType* field_type = lookup->GetFieldType();
HeapType::Iterator<Map> it = field_type->Classes();
if (!it.Done()) {
__ Ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
Label do_store;
while (true) {
__ CompareMap(scratch1, it.Current());
it.Advance();
if (it.Done()) {
__ B(ne, miss_label);
break;
}
__ B(eq, &do_store);
}
__ Bind(&do_store);
}
} else if (representation.IsDouble()) {
UseScratchRegisterScope temps(masm);
......
......@@ -528,13 +528,21 @@ void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
} else if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
HeapType* field_type = descriptors->GetFieldType(descriptor);
if (field_type->IsClass()) {
__ CheckMap(value_reg, field_type->AsClass()->Map(),
miss_label, DO_SMI_CHECK);
} else {
ASSERT(HeapType::Any()->Is(field_type));
__ JumpIfSmi(value_reg, miss_label);
HeapType* field_type = descriptors->GetFieldType(descriptor);
HeapType::Iterator<Map> it = field_type->Classes();
if (!it.Done()) {
Label do_store;
while (true) {
__ CompareMap(value_reg, it.Current());
it.Advance();
if (it.Done()) {
__ j(not_equal, miss_label);
break;
}
__ j(equal, &do_store, Label::kNear);
}
__ bind(&do_store);
}
} else if (representation.IsDouble()) {
Label do_store, heap_number;
......@@ -705,13 +713,21 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
HeapType* field_type = lookup->GetFieldType();
if (field_type->IsClass()) {
__ CheckMap(value_reg, field_type->AsClass()->Map(),
miss_label, DO_SMI_CHECK);
} else {
ASSERT(HeapType::Any()->Is(field_type));
__ JumpIfSmi(value_reg, miss_label);
HeapType* field_type = lookup->GetFieldType();
HeapType::Iterator<Map> it = field_type->Classes();
if (!it.Done()) {
Label do_store;
while (true) {
__ CompareMap(value_reg, it.Current());
it.Advance();
if (it.Done()) {
__ j(not_equal, miss_label);
break;
}
__ j(equal, &do_store, Label::kNear);
}
__ bind(&do_store);
}
} else if (representation.IsDouble()) {
// Load the double storage.
......
......@@ -300,13 +300,10 @@ void JSObject::JSObjectVerify() {
if (r.IsSmi()) ASSERT(value->IsSmi());
if (r.IsHeapObject()) ASSERT(value->IsHeapObject());
HeapType* field_type = descriptors->GetFieldType(i);
if (field_type->IsClass()) {
Map* map = *field_type->AsClass()->Map();
CHECK(!map->is_stable() || HeapObject::cast(value)->map() == map);
} else if (r.IsNone()) {
if (r.IsNone()) {
CHECK(field_type->Is(HeapType::None()));
} else {
CHECK(HeapType::Any()->Is(field_type));
} else if (!HeapType::Any()->Is(field_type)) {
CHECK(!field_type->NowStable() || field_type->NowContains(value));
}
}
}
......
......@@ -63,7 +63,7 @@ namespace internal {
Handle<HeapType> Object::OptimalType(Isolate* isolate,
Representation representation) {
if (!FLAG_track_field_types) return HeapType::Any(isolate);
if (FLAG_track_field_types) {
if (representation.IsNone()) return HeapType::None(isolate);
if (representation.IsHeapObject() && IsHeapObject()) {
// We can track only JavaScript objects with stable maps.
......@@ -74,6 +74,7 @@ Handle<HeapType> Object::OptimalType(Isolate* isolate,
return HeapType::Class(map, isolate);
}
}
}
return HeapType::Any(isolate);
}
......@@ -2526,11 +2527,21 @@ void Map::UpdateDescriptor(int descriptor_number, Descriptor* desc) {
// static
Handle<HeapType> Map::GeneralizeFieldType(Handle<HeapType> old_field_type,
Handle<HeapType> new_field_type,
Handle<HeapType> Map::GeneralizeFieldType(Handle<HeapType> type1,
Handle<HeapType> type2,
Isolate* isolate) {
if (new_field_type->NowIs(old_field_type)) return old_field_type;
if (old_field_type->NowIs(new_field_type)) return new_field_type;
static const int kMaxClassesPerFieldType = 5;
if (type1->NowIs(type2)) return type2;
if (type2->NowIs(type1)) return type1;
if (type1->NowStable() && type2->NowStable()) {
Handle<HeapType> type = HeapType::Union(type1, type2, isolate);
if (type->NumClasses() <= kMaxClassesPerFieldType) {
ASSERT(type->NowStable());
ASSERT(type1->NowIs(type));
ASSERT(type2->NowIs(type));
return type;
}
}
return HeapType::Any(isolate);
}
......
......@@ -6252,8 +6252,8 @@ class Map: public HeapObject {
int target_inobject,
int target_unused);
static Handle<Map> GeneralizeAllFieldRepresentations(Handle<Map> map);
static Handle<HeapType> GeneralizeFieldType(Handle<HeapType> old_field_type,
Handle<HeapType> new_field_type,
static Handle<HeapType> GeneralizeFieldType(Handle<HeapType> type1,
Handle<HeapType> type2,
Isolate* isolate)
V8_WARN_UNUSED_RESULT;
static void GeneralizeFieldType(Handle<Map> map,
......
......@@ -359,6 +359,17 @@ bool TypeImpl<Config>::NowIs(TypeImpl* that) {
}
// Check if this contains only (currently) stable classes.
template<class Config>
bool TypeImpl<Config>::NowStable() {
DisallowHeapAllocation no_allocation;
for (Iterator<i::Map> it = this->Classes(); !it.Done(); it.Advance()) {
if (!it.Current()->is_stable()) return false;
}
return true;
}
// Check this overlaps that.
template<class Config>
bool TypeImpl<Config>::Maybe(TypeImpl* that) {
......
......@@ -321,6 +321,8 @@ class TypeImpl : public Config::Base {
inline bool NowContains(i::Object* val);
bool NowContains(i::Handle<i::Object> val) { return this->NowContains(*val); }
bool NowStable();
bool IsClass() { return Config::is_class(this); }
bool IsConstant() { return Config::is_constant(this); }
bool IsArray() { return Config::is_struct(this, StructuralType::kArrayTag); }
......
......@@ -494,13 +494,21 @@ void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
} else if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
HeapType* field_type = descriptors->GetFieldType(descriptor);
if (field_type->IsClass()) {
__ CheckMap(value_reg, field_type->AsClass()->Map(),
miss_label, DO_SMI_CHECK);
} else {
ASSERT(HeapType::Any()->Is(field_type));
__ JumpIfSmi(value_reg, miss_label);
HeapType* field_type = descriptors->GetFieldType(descriptor);
HeapType::Iterator<Map> it = field_type->Classes();
if (!it.Done()) {
Label do_store;
while (true) {
__ CompareMap(value_reg, it.Current());
it.Advance();
if (it.Done()) {
__ j(not_equal, miss_label);
break;
}
__ j(equal, &do_store, Label::kNear);
}
__ bind(&do_store);
}
} else if (representation.IsDouble()) {
Label do_store, heap_number;
......@@ -645,13 +653,21 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
HeapType* field_type = lookup->GetFieldType();
if (field_type->IsClass()) {
__ CheckMap(value_reg, field_type->AsClass()->Map(),
miss_label, DO_SMI_CHECK);
} else {
ASSERT(HeapType::Any()->Is(field_type));
__ JumpIfSmi(value_reg, miss_label);
HeapType* field_type = lookup->GetFieldType();
HeapType::Iterator<Map> it = field_type->Classes();
if (!it.Done()) {
Label do_store;
while (true) {
__ CompareMap(value_reg, it.Current());
it.Advance();
if (it.Done()) {
__ j(not_equal, miss_label);
break;
}
__ j(equal, &do_store, Label::kNear);
}
__ bind(&do_store);
}
} else if (representation.IsDouble()) {
// Load the double storage.
......
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