} else if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
+ __ JumpIfSmi(value_reg, miss_label);
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::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;
if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
+ __ JumpIfSmi(value_reg, miss_label);
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::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.
} else if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
+ __ JumpIfSmi(value_reg, miss_label);
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::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);
if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
+ __ JumpIfSmi(value_reg, miss_label);
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::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);
} else if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
+ __ JumpIfSmi(value_reg, miss_label);
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::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;
if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
+ __ JumpIfSmi(value_reg, miss_label);
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::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.
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));
}
}
}
Handle<HeapType> Object::OptimalType(Isolate* isolate,
Representation representation) {
- if (!FLAG_track_field_types) return HeapType::Any(isolate);
- if (representation.IsNone()) return HeapType::None(isolate);
- if (representation.IsHeapObject() && IsHeapObject()) {
- // We can track only JavaScript objects with stable maps.
- Handle<Map> map(HeapObject::cast(this)->map(), isolate);
- if (map->is_stable() &&
- map->instance_type() >= FIRST_NONCALLABLE_SPEC_OBJECT_TYPE &&
- map->instance_type() <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE) {
- return HeapType::Class(map, 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.
+ Handle<Map> map(HeapObject::cast(this)->map(), isolate);
+ if (map->is_stable() &&
+ map->instance_type() >= FIRST_NONCALLABLE_SPEC_OBJECT_TYPE &&
+ map->instance_type() <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE) {
+ return HeapType::Class(map, isolate);
+ }
}
}
return HeapType::Any(isolate);
// 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);
}
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,
}
+// 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) {
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); }
} else if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
+ __ JumpIfSmi(value_reg, miss_label);
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::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;
if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
+ __ JumpIfSmi(value_reg, miss_label);
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::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.