@@ -16,8 +16,6 @@ namespace internal {
1616// ES6 section 19.1 Object Objects
1717
1818typedef compiler::Node Node;
19- template <class T >
20- using TNode = CodeStubAssembler::TNode<T>;
2119
2220class ObjectBuiltinsAssembler : public CodeStubAssembler {
2321 public:
@@ -36,46 +34,6 @@ class ObjectBuiltinsAssembler : public CodeStubAssembler {
3634 Node* ConstructDataDescriptor (Node* context, Node* value, Node* writable,
3735 Node* enumerable, Node* configurable);
3836 Node* GetAccessorOrUndefined (Node* accessor, Label* if_bailout);
39-
40- Node* IsSpecialReceiverMap (SloppyTNode<Map> map);
41- };
42-
43- class ObjectEntriesValuesBuiltinsAssembler : public ObjectBuiltinsAssembler {
44- public:
45- explicit ObjectEntriesValuesBuiltinsAssembler (
46- compiler::CodeAssemblerState* state)
47- : ObjectBuiltinsAssembler(state) {}
48-
49- protected:
50- enum CollectType { kEntries , kValues };
51-
52- TNode<Word32T> IsStringWrapperElementsKind (TNode<Map> map);
53-
54- TNode<BoolT> IsPropertyEnumerable (TNode<Uint32T> details);
55-
56- TNode<BoolT> IsPropertyKindAccessor (TNode<Uint32T> kind);
57-
58- TNode<BoolT> IsPropertyKindData (TNode<Uint32T> kind);
59-
60- TNode<Uint32T> HasHiddenPrototype (TNode<Map> map);
61-
62- TNode<Uint32T> LoadPropertyKind (TNode<Uint32T> details) {
63- return DecodeWord32<PropertyDetails::KindField>(details);
64- }
65-
66- void GetOwnValuesOrEntries (TNode<Context> context, TNode<Object> maybe_object,
67- CollectType collect_type);
68-
69- void GotoIfMapHasSlowProperties (TNode<Map> map, Label* if_slow);
70-
71- TNode<JSArray> FastGetOwnValuesOrEntries (
72- TNode<Context> context, TNode<JSObject> object,
73- Label* if_call_runtime_with_fast_path, Label* if_no_properties,
74- CollectType collect_type);
75-
76- TNode<JSArray> FinalizeValuesOrEntriesJSArray (
77- TNode<Context> context, TNode<FixedArray> values_or_entries,
78- TNode<IntPtrT> size, TNode<Map> array_map, Label* if_empty);
7937};
8038
8139void ObjectBuiltinsAssembler::ReturnToStringFormat (Node* context,
@@ -139,249 +97,6 @@ Node* ObjectBuiltinsAssembler::ConstructDataDescriptor(Node* context,
13997 return js_desc;
14098}
14199
142- Node* ObjectBuiltinsAssembler::IsSpecialReceiverMap (SloppyTNode<Map> map) {
143- CSA_SLOW_ASSERT (this , IsMap (map));
144- Node* is_special = IsSpecialReceiverInstanceType (LoadMapInstanceType (map));
145- uint32_t mask =
146- Map::HasNamedInterceptorBit::kMask | Map::IsAccessCheckNeededBit::kMask ;
147- USE (mask);
148- // Interceptors or access checks imply special receiver.
149- CSA_ASSERT (this ,
150- SelectConstant (IsSetWord32 (LoadMapBitField (map), mask), is_special,
151- Int32Constant (1 ), MachineRepresentation::kWord32 ));
152- return is_special;
153- }
154-
155- TNode<Word32T>
156- ObjectEntriesValuesBuiltinsAssembler::IsStringWrapperElementsKind (
157- TNode<Map> map) {
158- Node* kind = LoadMapElementsKind (map);
159- return Word32Or (
160- Word32Equal (kind, Int32Constant (FAST_STRING_WRAPPER_ELEMENTS)),
161- Word32Equal (kind, Int32Constant (SLOW_STRING_WRAPPER_ELEMENTS)));
162- }
163-
164- TNode<BoolT> ObjectEntriesValuesBuiltinsAssembler::IsPropertyEnumerable (
165- TNode<Uint32T> details) {
166- TNode<Uint32T> attributes =
167- DecodeWord32<PropertyDetails::AttributesField>(details);
168- return IsNotSetWord32 (attributes, PropertyAttributes::DONT_ENUM);
169- }
170-
171- TNode<BoolT> ObjectEntriesValuesBuiltinsAssembler::IsPropertyKindAccessor (
172- TNode<Uint32T> kind) {
173- return Word32Equal (kind, Int32Constant (PropertyKind::kAccessor ));
174- }
175-
176- TNode<BoolT> ObjectEntriesValuesBuiltinsAssembler::IsPropertyKindData (
177- TNode<Uint32T> kind) {
178- return Word32Equal (kind, Int32Constant (PropertyKind::kData ));
179- }
180-
181- TNode<Uint32T> ObjectEntriesValuesBuiltinsAssembler::HasHiddenPrototype (
182- TNode<Map> map) {
183- TNode<Uint32T> bit_field3 = LoadMapBitField3 (map);
184- return DecodeWord32<Map::HasHiddenPrototypeBit>(bit_field3);
185- }
186-
187- void ObjectEntriesValuesBuiltinsAssembler::GetOwnValuesOrEntries (
188- TNode<Context> context, TNode<Object> maybe_object,
189- CollectType collect_type) {
190- TNode<JSObject> object = TNode<JSObject>::UncheckedCast (
191- CallBuiltin (Builtins::kToObject , context, maybe_object));
192-
193- Label if_call_runtime_with_fast_path (this , Label::kDeferred ),
194- if_call_runtime (this , Label::kDeferred ),
195- if_no_properties (this , Label::kDeferred );
196-
197- TNode<Map> map = LoadMap (object);
198- GotoIfNot (IsJSObjectMap (map), &if_call_runtime);
199- GotoIfMapHasSlowProperties (map, &if_call_runtime);
200-
201- TNode<FixedArrayBase> elements = LoadElements (object);
202- // If the object has elements, we treat it as slow case.
203- // So, we go to runtime call.
204- GotoIfNot (IsEmptyFixedArray (elements), &if_call_runtime_with_fast_path);
205-
206- TNode<JSArray> result = FastGetOwnValuesOrEntries (
207- context, object, &if_call_runtime_with_fast_path, &if_no_properties,
208- collect_type);
209- Return (result);
210-
211- BIND (&if_no_properties);
212- {
213- Node* native_context = LoadNativeContext (context);
214- Node* array_map = LoadJSArrayElementsMap (PACKED_ELEMENTS, native_context);
215- Node* empty_array = AllocateJSArray (PACKED_ELEMENTS, array_map,
216- IntPtrConstant (0 ), SmiConstant (0 ));
217- Return (empty_array);
218- }
219-
220- BIND (&if_call_runtime_with_fast_path);
221- {
222- // In slow case, we simply call runtime.
223- if (collect_type == CollectType::kEntries ) {
224- Return (CallRuntime (Runtime::kObjectEntries , context, object));
225- } else {
226- DCHECK (collect_type == CollectType::kValues );
227- Return (CallRuntime (Runtime::kObjectValues , context, object));
228- }
229- }
230-
231- BIND (&if_call_runtime);
232- {
233- // In slow case, we simply call runtime.
234- if (collect_type == CollectType::kEntries ) {
235- Return (CallRuntime (Runtime::kObjectEntriesSkipFastPath , context, object));
236- } else {
237- DCHECK (collect_type == CollectType::kValues );
238- Return (CallRuntime (Runtime::kObjectValuesSkipFastPath , context, object));
239- }
240- }
241- }
242-
243- void ObjectEntriesValuesBuiltinsAssembler::GotoIfMapHasSlowProperties (
244- TNode<Map> map, Label* if_slow) {
245- GotoIf (IsStringWrapperElementsKind (map), if_slow);
246- GotoIf (IsSpecialReceiverMap (map), if_slow);
247- GotoIf (HasHiddenPrototype (map), if_slow);
248- GotoIf (IsDictionaryMap (map), if_slow);
249- }
250-
251- TNode<JSArray> ObjectEntriesValuesBuiltinsAssembler::FastGetOwnValuesOrEntries (
252- TNode<Context> context, TNode<JSObject> object,
253- Label* if_call_runtime_with_fast_path, Label* if_no_properties,
254- CollectType collect_type) {
255- Node* native_context = LoadNativeContext (context);
256- TNode<Map> array_map =
257- LoadJSArrayElementsMap (PACKED_ELEMENTS, native_context);
258- TNode<Map> map = LoadMap (object);
259- TNode<Uint32T> bit_field3 = LoadMapBitField3 (map);
260-
261- Label if_has_enum_cache (this ), if_not_has_enum_cache (this ),
262- collect_entries (this );
263- Node* object_enum_length =
264- DecodeWordFromWord32<Map::EnumLengthBits>(bit_field3);
265- Node* has_enum_cache = WordNotEqual (
266- object_enum_length, IntPtrConstant (kInvalidEnumCacheSentinel ));
267-
268- // In case, we found enum_cache in object,
269- // we use it as array_length becuase it has same size for
270- // Object.(entries/values) result array object length.
271- // So object_enum_length use less memory space than
272- // NumberOfOwnDescriptorsBits value.
273- // And in case, if enum_cache_not_found,
274- // we call runtime and initialize enum_cache for subsequent call of
275- // CSA fast path.
276- Branch (has_enum_cache, &if_has_enum_cache, if_call_runtime_with_fast_path);
277-
278- BIND (&if_has_enum_cache);
279- {
280- GotoIf (WordEqual (object_enum_length, IntPtrConstant (0 )), if_no_properties);
281- TNode<FixedArray> values_or_entries = TNode<FixedArray>::UncheckedCast (
282- AllocateFixedArray (PACKED_ELEMENTS, object_enum_length,
283- INTPTR_PARAMETERS, kAllowLargeObjectAllocation ));
284-
285- // If in case we have enum_cache,
286- // we can't detect accessor of object until loop through descritpros.
287- // So if object might have accessor,
288- // we will remain invalid addresses of FixedArray.
289- // Because in that case, we need to jump to runtime call.
290- // So the array filled by the-hole even if enum_cache exists.
291- FillFixedArrayWithValue (PACKED_ELEMENTS, values_or_entries,
292- IntPtrConstant (0 ), object_enum_length,
293- Heap::kTheHoleValueRootIndex );
294-
295- TVARIABLE (IntPtrT, var_result_index, IntPtrConstant (0 ));
296- TVARIABLE (IntPtrT, var_descriptor_index, IntPtrConstant (0 ));
297- Variable* vars[] = {&var_descriptor_index, &var_result_index};
298- // Let desc be ? O.[[GetOwnProperty]](key).
299- TNode<DescriptorArray> descriptors = LoadMapDescriptors (map);
300- Label loop (this , 2 , vars), after_loop (this ), loop_condition (this );
301- Branch (IntPtrEqual (var_descriptor_index, object_enum_length), &after_loop,
302- &loop);
303-
304- // We dont use BuildFastLoop.
305- // Instead, we use hand-written loop
306- // because of we need to use 'continue' functionality.
307- BIND (&loop);
308- {
309- // Currently, we will not invoke getters,
310- // so, map will not be changed.
311- CSA_ASSERT (this , WordEqual (map, LoadMap (object)));
312- TNode<Uint32T> descriptor_index = TNode<Uint32T>::UncheckedCast (
313- TruncateWordToWord32 (var_descriptor_index));
314- Node* next_key = DescriptorArrayGetKey (descriptors, descriptor_index);
315-
316- // Skip Symbols.
317- GotoIf (IsSymbol (next_key), &loop_condition);
318-
319- TNode<Uint32T> details = TNode<Uint32T>::UncheckedCast (
320- DescriptorArrayGetDetails (descriptors, descriptor_index));
321- TNode<Uint32T> kind = LoadPropertyKind (details);
322-
323- // If property is accessor, we escape fast path and call runtime.
324- GotoIf (IsPropertyKindAccessor (kind), if_call_runtime_with_fast_path);
325- CSA_ASSERT (this , IsPropertyKindData (kind));
326-
327- // If desc is not undefined and desc.[[Enumerable]] is true, then
328- GotoIfNot (IsPropertyEnumerable (details), &loop_condition);
329-
330- VARIABLE (var_property_value, MachineRepresentation::kTagged ,
331- UndefinedConstant ());
332- Node* descriptor_name_index = DescriptorNumberToIndex (descriptor_index);
333-
334- // Let value be ? Get(O, key).
335- LoadPropertyFromFastObject (object, map, descriptors,
336- descriptor_name_index, details,
337- &var_property_value);
338-
339- // If kind is "value", append value to properties.
340- Node* value = var_property_value.value ();
341-
342- if (collect_type == CollectType::kEntries ) {
343- // Let entry be CreateArrayFromList(« key, value »).
344- Node* array = nullptr ;
345- Node* elements = nullptr ;
346- std::tie (array, elements) = AllocateUninitializedJSArrayWithElements (
347- PACKED_ELEMENTS, array_map, SmiConstant (2 ), nullptr ,
348- IntPtrConstant (2 ));
349- StoreFixedArrayElement (elements, 0 , next_key, SKIP_WRITE_BARRIER);
350- StoreFixedArrayElement (elements, 1 , value, SKIP_WRITE_BARRIER);
351- value = array;
352- }
353-
354- StoreFixedArrayElement (values_or_entries, var_result_index, value);
355- Increment (&var_result_index, 1 );
356- Goto (&loop_condition);
357-
358- BIND (&loop_condition);
359- {
360- Increment (&var_descriptor_index, 1 );
361- Branch (IntPtrEqual (var_descriptor_index, object_enum_length),
362- &after_loop, &loop);
363- }
364- }
365- BIND (&after_loop);
366- return FinalizeValuesOrEntriesJSArray (context, values_or_entries,
367- var_result_index, array_map,
368- if_no_properties);
369- }
370- }
371-
372- TNode<JSArray>
373- ObjectEntriesValuesBuiltinsAssembler::FinalizeValuesOrEntriesJSArray (
374- TNode<Context> context, TNode<FixedArray> result, TNode<IntPtrT> size,
375- TNode<Map> array_map, Label* if_empty) {
376- CSA_ASSERT (this , IsJSArrayMap (array_map));
377-
378- GotoIf (IntPtrEqual (size, IntPtrConstant (0 )), if_empty);
379- Node* array = AllocateUninitializedJSArrayWithoutElements (
380- array_map, SmiTag (size), nullptr );
381- StoreObjectField (array, JSArray::kElementsOffset , result);
382- return TNode<JSArray>::UncheckedCast (array);
383- }
384-
385100TF_BUILTIN (ObjectPrototypeToLocaleString, CodeStubAssembler) {
386101 TNode<Context> context = CAST (Parameter (Descriptor::kContext ));
387102 TNode<Object> receiver = CAST (Parameter (Descriptor::kReceiver ));
@@ -551,22 +266,6 @@ TF_BUILTIN(ObjectKeys, ObjectBuiltinsAssembler) {
551266 }
552267}
553268
554- TF_BUILTIN (ObjectValues, ObjectEntriesValuesBuiltinsAssembler) {
555- TNode<JSObject> object =
556- TNode<JSObject>::UncheckedCast (Parameter (Descriptor::kObject ));
557- TNode<Context> context =
558- TNode<Context>::UncheckedCast (Parameter (Descriptor::kContext ));
559- GetOwnValuesOrEntries (context, object, CollectType::kValues );
560- }
561-
562- TF_BUILTIN (ObjectEntries, ObjectEntriesValuesBuiltinsAssembler) {
563- TNode<JSObject> object =
564- TNode<JSObject>::UncheckedCast (Parameter (Descriptor::kObject ));
565- TNode<Context> context =
566- TNode<Context>::UncheckedCast (Parameter (Descriptor::kContext ));
567- GetOwnValuesOrEntries (context, object, CollectType::kEntries );
568- }
569-
570269// ES #sec-object.prototype.isprototypeof
571270TF_BUILTIN (ObjectPrototypeIsPrototypeOf, ObjectBuiltinsAssembler) {
572271 Node* receiver = Parameter (Descriptor::kReceiver );
0 commit comments