OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/key-accumulator.h" | 5 #include "src/key-accumulator.h" |
6 | 6 |
7 #include "src/elements.h" | 7 #include "src/elements.h" |
8 #include "src/factory.h" | 8 #include "src/factory.h" |
9 #include "src/isolate-inl.h" | 9 #include "src/isolate-inl.h" |
10 #include "src/objects-inl.h" | 10 #include "src/objects-inl.h" |
11 #include "src/property-descriptor.h" | 11 #include "src/property-descriptor.h" |
12 | 12 |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 | 16 |
17 | 17 |
18 KeyAccumulator::~KeyAccumulator() { | 18 KeyAccumulator::~KeyAccumulator() { |
19 for (size_t i = 0; i < elements_.size(); i++) { | 19 for (size_t i = 0; i < elements_.size(); i++) { |
20 delete elements_[i]; | 20 delete elements_[i]; |
21 } | 21 } |
22 } | 22 } |
23 | 23 |
24 | 24 template <typename F> |
25 Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) { | 25 MaybeHandle<FixedArray> KeyAccumulator::GetKeys_Internal( |
26 GetKeysConversion convert, bool trivial, F& accumulate) { | |
26 if (length_ == 0) { | 27 if (length_ == 0) { |
27 return isolate_->factory()->empty_fixed_array(); | 28 return isolate_->factory()->empty_fixed_array(); |
28 } | 29 } |
29 // Make sure we have all the lengths collected. | 30 // Make sure we have all the lengths collected. |
30 NextPrototype(); | 31 NextPrototype(); |
31 | 32 |
32 // Assemble the result array by first adding the element keys and then the | 33 // Assemble the result array by first adding the element keys and then the |
33 // property keys. We use the total number of String + Symbol keys per level in | 34 // property keys. We use the total number of String + Symbol keys per level in |
34 // |level_lengths_| and the available element keys in the corresponding bucket | 35 // |level_lengths_| and the available element keys in the corresponding bucket |
35 // in |elements_| to deduce the number of keys to take from the | 36 // in |elements_| to deduce the number of keys to take from the |
(...skipping 16 matching lines...) Expand all Loading... | |
52 // Add the element indices for this prototype level. | 53 // Add the element indices for this prototype level. |
53 std::vector<uint32_t>* elements = elements_[level]; | 54 std::vector<uint32_t>* elements = elements_[level]; |
54 int num_elements = static_cast<int>(elements->size()); | 55 int num_elements = static_cast<int>(elements->size()); |
55 for (int i = 0; i < num_elements; i++) { | 56 for (int i = 0; i < num_elements; i++) { |
56 Handle<Object> key; | 57 Handle<Object> key; |
57 if (convert == KEEP_NUMBERS) { | 58 if (convert == KEEP_NUMBERS) { |
58 key = isolate_->factory()->NewNumberFromUint(elements->at(i)); | 59 key = isolate_->factory()->NewNumberFromUint(elements->at(i)); |
59 } else { | 60 } else { |
60 key = isolate_->factory()->Uint32ToString(elements->at(i)); | 61 key = isolate_->factory()->Uint32ToString(elements->at(i)); |
61 } | 62 } |
62 result->set(insertion_index, *key); | 63 auto did_accumulate = accumulate(result, insertion_index, *key); |
Camillo Bruni
2016/02/03 12:03:48
auto => Maybe<bool>
| |
63 insertion_index++; | 64 MAYBE_RETURN(did_accumulate, Handle<FixedArray>()); |
65 if (did_accumulate.FromJust()) insertion_index++; | |
64 } | 66 } |
65 } | 67 } |
66 // Add the string property keys for this prototype level. | 68 // Add the string property keys for this prototype level. |
67 for (int i = 0; i < num_string_properties; i++) { | 69 for (int i = 0; i < num_string_properties; i++) { |
68 Object* key = string_properties_->KeyAt(string_properties_index); | 70 Object* key = string_properties_->KeyAt(string_properties_index); |
69 result->set(insertion_index, key); | 71 auto did_accumulate = accumulate(result, insertion_index, key); |
70 insertion_index++; | 72 MAYBE_RETURN(did_accumulate, Handle<FixedArray>()); |
73 if (did_accumulate.FromJust()) insertion_index++; | |
71 string_properties_index++; | 74 string_properties_index++; |
72 } | 75 } |
73 // Add the symbol property keys for this prototype level. | 76 // Add the symbol property keys for this prototype level. |
74 for (int i = 0; i < num_symbol_properties; i++) { | 77 for (int i = 0; i < num_symbol_properties; i++) { |
75 Object* key = symbol_properties_->KeyAt(symbol_properties_index); | 78 Object* key = symbol_properties_->KeyAt(symbol_properties_index); |
76 result->set(insertion_index, key); | 79 auto did_accumulate = accumulate(result, insertion_index, key); |
77 insertion_index++; | 80 MAYBE_RETURN(did_accumulate, Handle<FixedArray>()); |
81 if (did_accumulate.FromJust()) insertion_index++; | |
78 symbol_properties_index++; | 82 symbol_properties_index++; |
79 } | 83 } |
80 } | 84 } |
81 | 85 |
82 DCHECK_EQ(insertion_index, length_); | 86 if (trivial) { |
87 DCHECK_EQ(insertion_index, length_); | |
88 } else if (insertion_index < length_) { | |
89 result->Shrink(insertion_index); | |
90 } | |
83 return result; | 91 return result; |
84 } | 92 } |
85 | 93 |
94 Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) { | |
95 auto add_key = [](Handle<FixedArray> result, int i, Object* key) { | |
96 result->set(i, key); | |
97 return Just(true); | |
98 }; | |
99 return GetKeys_Internal(convert, true, add_key).ToHandleChecked(); | |
100 } | |
101 | |
102 MaybeHandle<FixedArray> KeyAccumulator::GetValues(Handle<JSReceiver> receiver, | |
103 GetKeysConversion convert) { | |
104 Isolate* isolate = isolate_; | |
105 auto add_value = [receiver, isolate](Handle<FixedArray> result, int i, | |
Camillo Bruni
2016/02/03 12:03:48
I'm fine with the "auto" type for the accumulate l
caitp (gmail)
2016/02/03 12:57:30
replaced all non-lambda's with proper types
| |
106 Object* key) { | |
107 Handle<Object> value; | |
108 Handle<Name> name = Handle<Name>::cast(handle(key, isolate)); | |
109 | |
110 PropertyDescriptor descriptor; | |
111 auto owned = JSReceiver::GetOwnPropertyDescriptor(isolate, receiver, name, | |
112 &descriptor); | |
113 MAYBE_RETURN(owned, Nothing<bool>()); | |
114 if (!owned.FromJust() || !descriptor.enumerable()) return Just(false); | |
115 | |
116 if (Object::GetPropertyOrElement(receiver, name, STRICT).ToHandle(&value)) { | |
117 result->set(i, *value); | |
118 return Just(true); | |
119 } | |
120 return Nothing<bool>(); | |
121 }; | |
122 | |
123 return GetKeys_Internal(convert, false, add_value); | |
124 } | |
125 | |
126 MaybeHandle<FixedArray> KeyAccumulator::GetEntries(Handle<JSReceiver> receiver, | |
127 GetKeysConversion convert) { | |
128 Isolate* isolate = isolate_; | |
129 auto add_entry = [receiver, isolate](Handle<FixedArray> result, int i, | |
130 Object* key) { | |
131 Handle<Object> value; | |
132 Handle<Name> name = Handle<Name>::cast(handle(key, isolate)); | |
133 | |
134 PropertyDescriptor descriptor; | |
135 auto owned = JSReceiver::GetOwnPropertyDescriptor(isolate, receiver, name, | |
136 &descriptor); | |
137 MAYBE_RETURN(owned, Nothing<bool>()); | |
138 if (!owned.FromJust() || !descriptor.enumerable()) return Just(false); | |
139 | |
140 if (Object::GetPropertyOrElement(receiver, name, STRICT).ToHandle(&value)) { | |
141 auto entry_storage = isolate->factory()->NewUninitializedFixedArray(2); | |
142 entry_storage->set(0, key); | |
143 entry_storage->set(1, *value); | |
144 auto entry = isolate->factory()->NewJSArrayWithElements(entry_storage); | |
145 result->set(i, *entry); | |
146 return Just(true); | |
147 } | |
148 return Nothing<bool>(); | |
149 }; | |
150 | |
151 return GetKeys_Internal(convert, false, add_entry); | |
152 } | |
86 | 153 |
87 namespace { | 154 namespace { |
88 | 155 |
89 bool AccumulatorHasKey(std::vector<uint32_t>* sub_elements, uint32_t key) { | 156 bool AccumulatorHasKey(std::vector<uint32_t>* sub_elements, uint32_t key) { |
90 return std::binary_search(sub_elements->begin(), sub_elements->end(), key); | 157 return std::binary_search(sub_elements->begin(), sub_elements->end(), key); |
91 } | 158 } |
92 | 159 |
93 } // namespace | 160 } // namespace |
94 | 161 |
95 bool KeyAccumulator::AddKey(Object* key, AddKeyConversion convert) { | 162 bool KeyAccumulator::AddKey(Object* key, AddKeyConversion convert) { |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
306 level_lengths_.push_back(level_symbol_length_); | 373 level_lengths_.push_back(level_symbol_length_); |
307 } | 374 } |
308 elements_.push_back(new std::vector<uint32_t>()); | 375 elements_.push_back(new std::vector<uint32_t>()); |
309 level_string_length_ = 0; | 376 level_string_length_ = 0; |
310 level_symbol_length_ = 0; | 377 level_symbol_length_ = 0; |
311 } | 378 } |
312 | 379 |
313 | 380 |
314 } // namespace internal | 381 } // namespace internal |
315 } // namespace v8 | 382 } // namespace v8 |
OLD | NEW |