}
bind(&done);
- // Check that the value is a normal property.
+ // Check that the value is a field property.
// t2: elements + (index * kPointerSize)
const int kDetailsOffset =
SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
ldr(t1, FieldMemOperand(t2, kDetailsOffset));
+ DCHECK_EQ(FIELD, 0);
tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask)));
b(ne, miss);
}
Bind(&done);
- // Check that the value is a normal property.
+ // Check that the value is a field property.
const int kDetailsOffset =
SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
Ldrsw(scratch1, UntagSmiFieldMemOperand(scratch2, kDetailsOffset));
+ DCHECK_EQ(FIELD, 0);
TestAndBranchIfAnySet(scratch1, PropertyDetails::TypeField::kMask, miss);
// Get the value at the masked, scaled index and return.
JSObject::SetNormalizedProperty(to, key, callbacks, d);
break;
}
- // Do not occur since the from object has fast properties.
- case NORMAL:
- UNREACHABLE();
- break;
}
}
} else {
js_obj, entry,
descs->GetKey(i), descs->GetValue(i));
break;
- case NORMAL: // only in slow mode
- UNREACHABLE();
- break;
}
}
} else {
}
bind(&done);
- // Check that the value is a normal propety.
+ // Check that the value is a field property.
const int kDetailsOffset =
SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
- DCHECK_EQ(NORMAL, 0);
+ DCHECK_EQ(FIELD, 0);
test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize));
j(not_zero, miss);
case LookupIterator::NOT_FOUND:
break;
case LookupIterator::DATA:
- inline_followup = it->property_details().type() == FIELD;
+ inline_followup =
+ it->property_details().type() == FIELD && !it->is_dictionary_holder();
break;
case LookupIterator::ACCESSOR: {
Handle<Object> accessors = it->GetAccessors();
switch (property_details_.type()) {
case v8::internal::CONSTANT:
case v8::internal::FIELD:
- case v8::internal::NORMAL:
return DATA;
case v8::internal::CALLBACKS:
return ACCESSOR;
DCHECK(HolderIsReceiverOrHiddenPrototype());
Handle<JSObject> holder = GetHolder<JSObject>();
if (holder_map_->is_dictionary_map()) {
- PropertyDetails details(attributes, NORMAL, 0);
+ PropertyDetails details(attributes, FIELD, 0);
JSObject::SetNormalizedProperty(holder, name(), value, details);
} else {
holder_map_ = Map::ReconfigureDataProperty(holder_map_, descriptor_number(),
Configuration configuration = PROTOTYPE_CHAIN)
: configuration_(ComputeConfiguration(configuration, name)),
state_(NOT_FOUND),
- property_details_(NONE, NORMAL, Representation::None()),
+ property_details_(NONE, FIELD, 0),
isolate_(name->GetIsolate()),
name_(name),
receiver_(receiver),
Configuration configuration = PROTOTYPE_CHAIN)
: configuration_(ComputeConfiguration(configuration, name)),
state_(NOT_FOUND),
- property_details_(NONE, NORMAL, Representation::None()),
+ property_details_(NONE, FIELD, 0),
isolate_(name->GetIsolate()),
name_(name),
holder_map_(holder->map(), isolate_),
}
bind(&done);
- // Check that the value is a normal property.
+ // Check that the value is a field property.
// reg2: elements + (index * kPointerSize).
const int kDetailsOffset =
SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
lw(reg1, FieldMemOperand(reg2, kDetailsOffset));
+ DCHECK_EQ(FIELD, 0);
And(at, reg1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask)));
Branch(miss, ne, at, Operand(zero_reg));
}
bind(&done);
- // Check that the value is a normal property.
+ // Check that the value is a field property.
// reg2: elements + (index * kPointerSize).
const int kDetailsOffset =
SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
ld(reg1, FieldMemOperand(reg2, kDetailsOffset));
+ DCHECK_EQ(FIELD, 0);
And(at, reg1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask)));
Branch(miss, ne, at, Operand(zero_reg));
// A copy of the PropertyType enum from property-details.h
var PropertyType = {};
-PropertyType.Normal = 0;
-PropertyType.Field = 1;
-PropertyType.Constant = 2;
-PropertyType.Callbacks = 3;
+PropertyType.Field = 0;
+PropertyType.Constant = 1;
+PropertyType.Callbacks = 2;
// Different attributes for a property.
* "ref":<number>}
*
* If the attribute for the property is PropertyAttribute.None it is not added.
- * If the propertyType for the property is PropertyType.Normal it is not added.
* Here are a couple of examples.
*
- * {"name":"hello","ref":1}
+ * {"name":"hello","propertyType":0,"ref":1}
* {"name":"length","attributes":7,"propertyType":3,"ref":2}
*
* @param {PropertyMirror} propertyMirror The property to serialize.
if (propertyMirror.attributes() != PropertyAttribute.None) {
result.attributes = propertyMirror.attributes();
}
- if (propertyMirror.propertyType() != PropertyType.Normal) {
- result.propertyType = propertyMirror.propertyType();
- }
+ result.propertyType = propertyMirror.propertyType();
result.ref = propertyValue.handle();
}
return result;
case CALLBACKS:
os << Brief(descs->GetCallbacksObject(i)) << " (callback)\n";
break;
- case NORMAL: // only in slow mode
- UNREACHABLE();
- break;
}
}
} else {
void DescriptorArray::PrintDescriptors(std::ostream& os) { // NOLINT
+ HandleScope scope(GetIsolate());
os << "Descriptor array " << number_of_descriptors() << "\n";
for (int i = 0; i < number_of_descriptors(); i++) {
Descriptor desc;
case CALLBACKS:
os << " (transition to callback " << Brief(GetTargetValue(i)) << ")";
break;
- // Values below are never in the target descriptor array.
- case NORMAL:
- UNREACHABLE();
- break;
}
os << ", attrs: " << details.attributes();
}
// Assign an enumeration index to the property and update
// SetNextEnumerationIndex.
int index = dict->NextEnumerationIndex();
- PropertyDetails details = PropertyDetails(attributes, NORMAL, index);
+ PropertyDetails details(attributes, FIELD, index);
dict->SetNextEnumerationIndex(index + 1);
dict->SetEntry(entry, name, cell, details);
return;
PropertyCell::SetValueInferType(cell, value);
value = cell;
}
- PropertyDetails details = PropertyDetails(attributes, NORMAL, 0);
+ PropertyDetails details(attributes, FIELD, 0);
Handle<NameDictionary> result =
NameDictionary::Add(dict, name, value, details);
if (*dict != *result) object->set_properties(*result);
return MaybeHandle<Map>();
}
break;
-
- case NORMAL:
- UNREACHABLE();
}
}
if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>();
case CONSTANT: {
Handle<Name> key(descs->GetKey(i));
Handle<Object> value(descs->GetConstant(i), isolate);
- PropertyDetails d = PropertyDetails(
- details.attributes(), NORMAL, i + 1);
+ PropertyDetails d(details.attributes(), FIELD, i + 1);
dictionary = NameDictionary::Add(dictionary, key, value, d);
break;
}
value = isolate->factory()->NewHeapNumber(old->value());
}
}
- PropertyDetails d =
- PropertyDetails(details.attributes(), NORMAL, i + 1);
+ PropertyDetails d(details.attributes(), FIELD, i + 1);
dictionary = NameDictionary::Add(dictionary, key, value, d);
break;
}
case CALLBACKS: {
Handle<Name> key(descs->GetKey(i));
Handle<Object> value(descs->GetCallbacksObject(i), isolate);
- PropertyDetails d = PropertyDetails(
- details.attributes(), CALLBACKS, i + 1);
+ PropertyDetails d(details.attributes(), CALLBACKS, i + 1);
dictionary = NameDictionary::Add(dictionary, key, value, d);
break;
}
- case NORMAL:
- UNREACHABLE();
- break;
}
}
Object* value = dictionary->ValueAt(index);
PropertyType type = dictionary->DetailsAt(index).type();
- DCHECK(type != FIELD);
- if (type == NORMAL && !value->IsJSFunction()) {
+ if (type == FIELD && !value->IsJSFunction()) {
number_of_fields += 1;
}
}
if (value->IsJSFunction()) {
ConstantDescriptor d(key, handle(value, isolate), details.attributes());
descriptors->Set(enumeration_index - 1, &d);
- } else if (type == NORMAL) {
+ } else if (type == FIELD) {
if (current_offset < inobject_props) {
object->InObjectPropertyAtPut(current_offset, value,
UPDATE_WRITE_BARRIER);
value = handle(Handle<FixedArray>::cast(array)->get(i), isolate);
}
if (!value->IsTheHole()) {
- PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
+ PropertyDetails details(NONE, FIELD, 0);
dictionary =
SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details);
}
case CALLBACKS:
return false;
-
- case NORMAL:
- UNREACHABLE();
- break;
}
UNREACHABLE();
// is read-only (a declared const that has not been initialized). If a
// value is being defined we skip attribute checks completely.
if (set_mode == DEFINE_PROPERTY) {
- details = PropertyDetails(
- attributes, NORMAL, details.dictionary_index());
+ details =
+ PropertyDetails(attributes, FIELD, details.dictionary_index());
dictionary->DetailsAtPut(entry, details);
} else if (details.IsReadOnly() && !element->IsTheHole()) {
if (strict_mode == SLOPPY) {
}
}
- PropertyDetails details = PropertyDetails(attributes, NORMAL, 0);
+ PropertyDetails details(attributes, FIELD, 0);
Handle<SeededNumberDictionary> new_dictionary =
SeededNumberDictionary::AddNumberEntry(dictionary, index, value,
details);
}
uint32_t result = pos;
- PropertyDetails no_details = PropertyDetails(NONE, NORMAL, 0);
+ PropertyDetails no_details(NONE, FIELD, 0);
while (undefs > 0) {
if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
// Adding an entry with the key beyond smi-range requires
Isolate* isolate = global->GetIsolate();
Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(
isolate->factory()->the_hole_value());
- PropertyDetails details(NONE, NORMAL, 0);
+ PropertyDetails details(NONE, FIELD, 0);
details = details.AsDeleted();
Handle<NameDictionary> dictionary = NameDictionary::Add(
handle(global->property_dictionary()), name, cell, details);
#ifdef DEBUG
USE(Shape::AsHandle(dictionary->GetIsolate(), key));
#endif
- PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
+ PropertyDetails details(NONE, FIELD, 0);
AddEntry(dictionary, key, value, details, dictionary->Hash(key));
return dictionary;
uint32_t key,
Handle<Object> value) {
SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
- return Add(dictionary, key, value, PropertyDetails(NONE, NORMAL, 0));
+ return Add(dictionary, key, value, PropertyDetails(NONE, FIELD, 0));
}
}
bind(&done);
- // Check that the value is a normal property.
+ // Check that the value is a field property.
// t2: elements + (index * kPointerSize)
const int kDetailsOffset =
SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
LoadP(t1, FieldMemOperand(t2, kDetailsOffset));
LoadSmiLiteral(ip, Smi::FromInt(PropertyDetails::TypeField::kMask));
+ DCHECK_EQ(FIELD, 0);
and_(r0, t1, ip, SetRC);
bne(miss, cr0);
// Order of properties is significant.
// Must fit in the BitField PropertyDetails::TypeField.
// A copy of this is in mirror-debugger.js.
-enum PropertyType {
- // Only in slow mode.
- NORMAL = 0,
- // Only in fast mode.
- FIELD = 1,
- CONSTANT = 2,
- CALLBACKS = 3
-};
+enum PropertyType { FIELD = 0, CONSTANT = 1, CALLBACKS = 2 };
class Representation {
}
Representation representation() const {
- DCHECK(type() != NORMAL);
return DecodeRepresentation(RepresentationField::decode(value_));
}
- int field_index() const {
- return FieldIndexField::decode(value_);
- }
+ int field_index() const { return FieldIndexField::decode(value_); }
inline int field_width_in_words() const;
bool IsReadOnly() const { return (attributes() & READ_ONLY) != 0; }
bool IsConfigurable() const { return (attributes() & DONT_DELETE) == 0; }
bool IsDontEnum() const { return (attributes() & DONT_ENUM) != 0; }
- bool IsDeleted() const { return DeletedField::decode(value_) != 0;}
+ bool IsDeleted() const { return DeletedField::decode(value_) != 0; }
// Bit fields in value_ (type, shift, size). Must be public so the
// constants can be embedded in generated code.
class FieldIndexField
: public BitField<uint32_t, 9 + kDescriptorIndexBitCount,
kDescriptorIndexBitCount> {}; // NOLINT
- // All bits for fast objects must fix in a smi.
- STATIC_ASSERT(9 + kDescriptorIndexBitCount + kDescriptorIndexBitCount <= 31);
+
+ // All bits for both fast and slow objects must fit in a smi.
+ STATIC_ASSERT(DictionaryStorageField::kNext <= 31);
+ STATIC_ASSERT(FieldIndexField::kNext <= 31);
static const int kInitialIndex = 1;
+#ifdef OBJECT_PRINT
+ // For our gdb macros, we should perhaps change these in the future.
+ void Print(bool dictionary_mode);
+#endif
+
private:
PropertyDetails(int value, int pointer) {
value_ = DescriptorPointer::update(value, pointer);
}
+struct FastPropertyDetails {
+ explicit FastPropertyDetails(const PropertyDetails& v) : details(v) {}
+ const PropertyDetails details;
+};
+
+
+// Outputs PropertyDetails as a dictionary details.
std::ostream& operator<<(std::ostream& os, const PropertyDetails& details) {
os << "(";
switch (details.type()) {
- case NORMAL:
- os << "normal: dictionary_index: " << details.dictionary_index();
+ case FIELD:
+ os << "normal: ";
break;
case CONSTANT:
+ os << "constant: ";
+ break;
+ case CALLBACKS:
+ UNREACHABLE();
+ break;
+ }
+ return os << " dictionary_index: " << details.dictionary_index()
+ << ", attrs: " << details.attributes() << ")";
+}
+
+
+// Outputs PropertyDetails as a descriptor array details.
+std::ostream& operator<<(std::ostream& os,
+ const FastPropertyDetails& details_fast) {
+ const PropertyDetails& details = details_fast.details;
+ os << "(";
+ switch (details.type()) {
+ case CONSTANT:
os << "constant: p: " << details.pointer();
break;
case FIELD:
os << "callbacks: p: " << details.pointer();
break;
}
- os << ", attrs: " << details.attributes() << ")";
- return os;
+ return os << ", attrs: " << details.attributes() << ")";
+}
+
+
+#ifdef OBJECT_PRINT
+void PropertyDetails::Print(bool dictionary_mode) {
+ OFStream os(stdout);
+ if (dictionary_mode) {
+ os << *this;
+ } else {
+ os << FastPropertyDetails(*this);
+ }
+ os << "\n" << std::flush;
}
+#endif
std::ostream& operator<<(std::ostream& os, const Descriptor& d) {
return os << "Descriptor " << Brief(*d.GetKey()) << " @ "
- << Brief(*d.GetValue()) << " " << d.GetDetails();
+ << Brief(*d.GetValue()) << " "
+ << FastPropertyDetails(d.GetDetails());
}
} } // namespace v8::internal
lookup_type_(NOT_FOUND),
holder_(NULL),
transition_(NULL),
- details_(NONE, NORMAL, Representation::None()) {
+ details_(NONE, FIELD, Representation::None()) {
isolate->set_top_lookup_result(this);
}
void NotFound() {
lookup_type_ = NOT_FOUND;
- details_ = PropertyDetails(NONE, NORMAL, Representation::None());
+ details_ = PropertyDetails(NONE, FIELD, 0);
holder_ = NULL;
transition_ = NULL;
}
// Property callbacks does not include transitions to callbacks.
bool IsPropertyCallbacks() const {
- DCHECK(!(details_.type() == CALLBACKS && !IsFound()));
return !IsTransition() && details_.type() == CALLBACKS;
}
}
bool IsField() const {
- DCHECK(!(details_.type() == FIELD && !IsFound()));
return lookup_type_ == DESCRIPTOR_TYPE && details_.type() == FIELD;
}
bool IsConstant() const {
- DCHECK(!(details_.type() == CONSTANT && !IsFound()));
return lookup_type_ == DESCRIPTOR_TYPE && details_.type() == CONSTANT;
}
isolate, element_or_char,
Runtime::GetElementOrCharAt(isolate, obj, index));
details->set(0, *element_or_char);
- details->set(1,
- PropertyDetails(NONE, NORMAL, Representation::None()).AsSmi());
+ details->set(1, PropertyDetails(NONE, FIELD, 0).AsSmi());
return *isolate->factory()->NewJSArrayWithElements(details);
}
details->set(0, *value);
// TODO(verwaest): Get rid of this random way of handling interceptors.
PropertyDetails d = it.state() == LookupIterator::INTERCEPTOR
- ? PropertyDetails(NONE, NORMAL, 0)
+ ? PropertyDetails(NONE, FIELD, 0)
: it.property_details();
details->set(1, d.AsSmi());
details->set(
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);
CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
- // TODO(verwaest): Depends on the type of details.
+ // TODO(verwaest): Works only for dictionary mode holders.
return Smi::FromInt(details.dictionary_index());
}
NameDictionary* dictionary = receiver->property_dictionary();
int entry = dictionary->FindEntry(key);
if ((entry != NameDictionary::kNotFound) &&
- (dictionary->DetailsAt(entry).type() == NORMAL)) {
+ (dictionary->DetailsAt(entry).type() == FIELD)) {
Object* value = dictionary->ValueAt(entry);
if (!receiver->IsGlobalObject()) return value;
value = PropertyCell::cast(value)->value();
if (name == NULL) continue;
Handle<NameDictionary> new_dict = NameDictionary::Add(
dict, isolate->factory()->InternalizeUtf8String(name),
- Handle<Smi>(Smi::FromInt(i), isolate),
- PropertyDetails(NONE, NORMAL, Representation::None()));
+ Handle<Smi>(Smi::FromInt(i), isolate), PropertyDetails(NONE, FIELD, 0));
// The dictionary does not need to grow.
CHECK(new_dict.is_identical_to(dict));
}
}
bind(&done);
- // Check that the value is a normal propety.
+ // Check that the value is a field property.
const int kDetailsOffset =
SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
- DCHECK_EQ(NORMAL, 0);
+ DCHECK_EQ(FIELD, 0);
Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
Smi::FromInt(PropertyDetails::TypeField::kMask));
j(not_zero, miss);
}
bind(&done);
- // Check that the value is a normal propety.
+ // Check that the value is a field property.
const int kDetailsOffset =
SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
- DCHECK_EQ(NORMAL, 0);
+ DCHECK_EQ(FIELD, 0);
test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize));
j(not_zero, miss);
// Check that serialized name is correct.
assertEquals(properties[i].name(), fromJSON.properties[i].name, 'Unexpected serialized name');
- // If property type is normal property type is not serialized.
- if (properties[i].propertyType() != debug.PropertyType.Normal) {
- assertEquals(properties[i].propertyType(), fromJSON.properties[i].propertyType, 'Unexpected serialized property type');
- } else {
- assertTrue(typeof(fromJSON.properties[i].propertyType) === 'undefined', 'Unexpected serialized property type');
- }
+ assertEquals(properties[i].propertyType(), fromJSON.properties[i].propertyType, 'Unexpected serialized property type');
// If there are no attributes attributes are not serialized.
if (properties[i].attributes() != debug.PropertyAttribute.None) {