Commit 23332fe8 authored by ishell's avatar ishell Committed by Commit bot

[stubs] Implementing CodeStubAssembler::GetOwnProperty().

This is a building block for GetPropertyStub. It supports querying fast,
slow and global objects without native accessors and interceptors.

BUG=v8:4911
LOG=Y

Review-Url: https://codereview.chromium.org/2079823002
Cr-Commit-Position: refs/heads/master@{#37291}
parent 70557497
......@@ -368,7 +368,7 @@ void Builtins::Generate_ObjectHasOwnProperty(CodeStubAssembler* assembler) {
&call_runtime);
assembler->Bind(&if_iskeyunique);
assembler->TryLookupProperty(object, map, instance_type, key, &return_true,
assembler->TryHasOwnProperty(object, map, instance_type, key, &return_true,
&return_false, &call_runtime);
assembler->Bind(&keyisindex);
......
This diff is collapsed.
......@@ -117,6 +117,10 @@ class CodeStubAssembler : public compiler::CodeAssembler {
// Load a field from an object on the heap.
compiler::Node* LoadObjectField(compiler::Node* object, int offset,
MachineType rep = MachineType::AnyTagged());
compiler::Node* LoadObjectField(compiler::Node* object,
compiler::Node* offset,
MachineType rep = MachineType::AnyTagged());
// Load the floating point value of a HeapNumber.
compiler::Node* LoadHeapNumberValue(compiler::Node* object);
// Load the Map of an HeapObject.
......@@ -145,6 +149,8 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* LoadMapPrototype(compiler::Node* map);
// Load the instance size of a Map.
compiler::Node* LoadMapInstanceSize(compiler::Node* map);
// Load the inobject properties count of a Map (valid only for JSObjects).
compiler::Node* LoadMapInobjectProperties(compiler::Node* map);
// Load the hash field of a name.
compiler::Node* LoadNameHashField(compiler::Node* name);
......@@ -268,11 +274,24 @@ class CodeStubAssembler : public compiler::CodeAssembler {
void TryToName(compiler::Node* key, Label* if_keyisindex, Variable* var_index,
Label* if_keyisunique, Label* if_bailout);
// Calculates array index for given dictionary entry and entry field.
// See Dictionary::EntryToIndex().
template <typename Dictionary>
compiler::Node* EntryToIndex(compiler::Node* entry, int field_index);
template <typename Dictionary>
compiler::Node* EntryToIndex(compiler::Node* entry) {
return EntryToIndex<Dictionary>(entry, Dictionary::kEntryKeyIndex);
}
// Looks up an entry in a NameDictionaryBase successor. If the entry is found
// control goes to {if_found} and {var_name_index} contains an index of the
// key field of the entry found. If the key is not found control goes to
// {if_not_found}.
static const int kInlinedDictionaryProbes = 4;
template <typename Dictionary>
void NameDictionaryLookup(compiler::Node* dictionary,
compiler::Node* unique_name, Label* if_found,
Variable* var_entry, Label* if_not_found,
Variable* var_name_index, Label* if_not_found,
int inlined_probes = kInlinedDictionaryProbes);
compiler::Node* ComputeIntegerHash(compiler::Node* key, compiler::Node* seed);
......@@ -282,11 +301,56 @@ class CodeStubAssembler : public compiler::CodeAssembler {
Label* if_found, Variable* var_entry,
Label* if_not_found);
void TryLookupProperty(compiler::Node* object, compiler::Node* map,
// Tries to check if {object} has own {unique_name} property.
void TryHasOwnProperty(compiler::Node* object, compiler::Node* map,
compiler::Node* instance_type,
compiler::Node* unique_name, Label* if_found,
Label* if_not_found, Label* if_bailout);
// Tries to get {object}'s own {unique_name} property value. If the property
// is an accessor then it also calls a getter. If the property is a double
// field it re-wraps value in an immutable heap number.
void TryGetOwnProperty(compiler::Node* context, compiler::Node* receiver,
compiler::Node* object, compiler::Node* map,
compiler::Node* instance_type,
compiler::Node* unique_name, Label* if_found,
Variable* var_value, Label* if_not_found,
Label* if_bailout);
void LoadPropertyFromFastObject(compiler::Node* object, compiler::Node* map,
compiler::Node* descriptors,
compiler::Node* name_index,
Variable* var_details, Variable* var_value);
void LoadPropertyFromNameDictionary(compiler::Node* dictionary,
compiler::Node* entry,
Variable* var_details,
Variable* var_value);
void LoadPropertyFromGlobalDictionary(compiler::Node* dictionary,
compiler::Node* entry,
Variable* var_details,
Variable* var_value, Label* if_deleted);
// Generic property lookup generator. If the {object} is fast and
// {unique_name} property is found then the control goes to {if_found_fast}
// label and {var_meta_storage} and {var_name_index} will contain
// DescriptorArray and an index of the descriptor's name respectively.
// If the {object} is slow or global then the control goes to {if_found_dict}
// or {if_found_global} and the {var_meta_storage} and {var_name_index} will
// contain a dictionary and an index of the key field of the found entry.
// If property is not found or given lookup is not supported then
// the control goes to {if_not_found} or {if_bailout} respectively.
//
// Note: this code does not check if the global dictionary points to deleted
// entry! This has to be done by the caller.
void TryLookupProperty(compiler::Node* object, compiler::Node* map,
compiler::Node* instance_type,
compiler::Node* unique_name, Label* if_found_fast,
Label* if_found_dict, Label* if_found_global,
Variable* var_meta_storage, Variable* var_name_index,
Label* if_not_found, Label* if_bailout);
void TryLookupElement(compiler::Node* object, compiler::Node* map,
compiler::Node* instance_type, compiler::Node* index,
Label* if_found, Label* if_not_found,
......
......@@ -4343,7 +4343,7 @@ compiler::Node* HasPropertyStub::Generate(CodeStubAssembler* assembler,
assembler->Bind(&loop);
{
Label next_proto(assembler);
assembler->TryLookupProperty(var_object.value(), var_map.value(),
assembler->TryHasOwnProperty(var_object.value(), var_map.value(),
var_instance_type.value(), key, &return_true,
&next_proto, &call_runtime);
assembler->Bind(&next_proto);
......
......@@ -7424,9 +7424,9 @@ void BaseDictionaryShape<Key>::SetEntry(Dictionary* dict, int entry,
int index = dict->EntryToIndex(entry);
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = dict->GetWriteBarrierMode(no_gc);
dict->set(index, *key, mode);
dict->set(index + 1, *value, mode);
dict->set(index + 2, details.AsSmi());
dict->set(index + Dictionary::kEntryKeyIndex, *key, mode);
dict->set(index + Dictionary::kEntryValueIndex, *value, mode);
dict->set(index + Dictionary::kEntryDetailsIndex, details.AsSmi());
}
......@@ -7440,8 +7440,8 @@ void GlobalDictionaryShape::SetEntry(Dictionary* dict, int entry,
int index = dict->EntryToIndex(entry);
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = dict->GetWriteBarrierMode(no_gc);
dict->set(index, *key, mode);
dict->set(index + 1, *value, mode);
dict->set(index + Dictionary::kEntryKeyIndex, *key, mode);
dict->set(index + Dictionary::kEntryValueIndex, *value, mode);
PropertyCell::cast(*value)->set_property_details(details);
}
......
......@@ -16202,8 +16202,7 @@ int NameDictionaryBase<Derived, Shape>::FindEntry(Handle<Name> key) {
uint32_t count = 1;
Isolate* isolate = this->GetIsolate();
while (true) {
int index = Derived::EntryToIndex(entry);
Object* element = this->get(index);
Object* element = this->KeyAt(entry);
if (element->IsUndefined(isolate)) break; // Empty entry.
if (*key == element) return entry;
DCHECK(element->IsTheHole(isolate) || element->IsUniqueName());
......@@ -16299,11 +16298,11 @@ void HashTable<Derived, Shape, Key>::Rehash(Key key) {
// are placed correctly. Other elements might need to be moved.
done = true;
for (uint32_t current = 0; current < capacity; current++) {
Object* current_key = get(EntryToIndex(current));
Object* current_key = KeyAt(current);
if (IsKey(isolate, current_key)) {
uint32_t target = EntryForProbe(key, current_key, probe, current);
if (current == target) continue;
Object* target_key = get(EntryToIndex(target));
Object* target_key = KeyAt(target);
if (!IsKey(target_key) ||
EntryForProbe(key, target_key, probe, target) != target) {
// Put the current element into the correct position.
......@@ -16322,8 +16321,8 @@ void HashTable<Derived, Shape, Key>::Rehash(Key key) {
Object* the_hole = isolate->heap()->the_hole_value();
Object* undefined = isolate->heap()->undefined_value();
for (uint32_t current = 0; current < capacity; current++) {
if (get(EntryToIndex(current)) == the_hole) {
set(EntryToIndex(current), undefined);
if (KeyAt(current) == the_hole) {
set(EntryToIndex(current) + Derived::kEntryKeyIndex, undefined);
}
}
SetNumberOfDeletedElements(0);
......
......@@ -3236,10 +3236,12 @@ class HashTable : public HashTableBase {
void Rehash(Key key);
// Returns the key at entry.
Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
Object* KeyAt(int entry) { return get(EntryToIndex(entry) + kEntryKeyIndex); }
static const int kElementsStartIndex = kPrefixStartIndex + Shape::kPrefixSize;
static const int kEntrySize = Shape::kEntrySize;
STATIC_ASSERT(kEntrySize > 0);
static const int kEntryKeyIndex = 0;
static const int kElementsStartOffset =
kHeaderSize + kElementsStartIndex * kPointerSize;
static const int kCapacityOffset =
......@@ -3554,15 +3556,16 @@ class BaseDictionaryShape : public BaseShape<Key> {
static inline PropertyDetails DetailsAt(Dictionary* dict, int entry) {
STATIC_ASSERT(Dictionary::kEntrySize == 3);
DCHECK(entry >= 0); // Not found is -1, which is not caught by get().
return PropertyDetails(
Smi::cast(dict->get(Dictionary::EntryToIndex(entry) + 2)));
return PropertyDetails(Smi::cast(dict->get(
Dictionary::EntryToIndex(entry) + Dictionary::kEntryDetailsIndex)));
}
template <typename Dictionary>
static inline void DetailsAtPut(Dictionary* dict, int entry,
PropertyDetails value) {
STATIC_ASSERT(Dictionary::kEntrySize == 3);
dict->set(Dictionary::EntryToIndex(entry) + 2, value.AsSmi());
dict->set(Dictionary::EntryToIndex(entry) + Dictionary::kEntryDetailsIndex,
value.AsSmi());
}
template <typename Dictionary>
......@@ -3584,6 +3587,8 @@ class NameDictionaryShape : public BaseDictionaryShape<Handle<Name> > {
static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Name> key);
static const int kPrefixSize = 2;
static const int kEntrySize = 3;
static const int kEntryValueIndex = 1;
static const int kEntryDetailsIndex = 2;
static const bool kIsEnumerable = true;
};
......@@ -3598,6 +3603,9 @@ class NameDictionary
inline static Handle<FixedArray> DoGenerateNewEnumerationIndices(
Handle<NameDictionary> dictionary);
static const int kEntryValueIndex = 1;
static const int kEntryDetailsIndex = 2;
};
......@@ -3625,6 +3633,8 @@ class GlobalDictionary
: public NameDictionaryBase<GlobalDictionary, GlobalDictionaryShape> {
public:
DECLARE_CAST(GlobalDictionary)
static const int kEntryValueIndex = 1;
};
......@@ -3698,6 +3708,9 @@ class SeededNumberDictionary
// requires_slow_elements returns false.
inline uint32_t max_number_key();
static const int kEntryValueIndex = 1;
static const int kEntryDetailsIndex = 2;
// Bit masks.
static const int kRequiresSlowElementsMask = 1;
static const int kRequiresSlowElementsTagSize = 1;
......@@ -3728,6 +3741,9 @@ class UnseededNumberDictionary
Handle<UnseededNumberDictionary> dictionary,
uint32_t key,
Handle<Object> value);
static const int kEntryValueIndex = 1;
static const int kEntryDetailsIndex = 2;
};
......
This diff is collapsed.
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