@@ -16,8 +16,6 @@ namespace internal {
16
16
// ES6 section 19.1 Object Objects
17
17
18
18
typedef compiler::Node Node;
19
- template <class T >
20
- using TNode = CodeStubAssembler::TNode<T>;
21
19
22
20
class ObjectBuiltinsAssembler : public CodeStubAssembler {
23
21
public:
@@ -36,46 +34,6 @@ class ObjectBuiltinsAssembler : public CodeStubAssembler {
36
34
Node* ConstructDataDescriptor (Node* context, Node* value, Node* writable,
37
35
Node* enumerable, Node* configurable);
38
36
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);
79
37
};
80
38
81
39
void ObjectBuiltinsAssembler::ReturnToStringFormat (Node* context,
@@ -139,249 +97,6 @@ Node* ObjectBuiltinsAssembler::ConstructDataDescriptor(Node* context,
139
97
return js_desc;
140
98
}
141
99
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
-
385
100
TF_BUILTIN (ObjectPrototypeToLocaleString, CodeStubAssembler) {
386
101
TNode<Context> context = CAST (Parameter (Descriptor::kContext ));
387
102
TNode<Object> receiver = CAST (Parameter (Descriptor::kReceiver ));
@@ -551,22 +266,6 @@ TF_BUILTIN(ObjectKeys, ObjectBuiltinsAssembler) {
551
266
}
552
267
}
553
268
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
-
570
269
// ES #sec-object.prototype.isprototypeof
571
270
TF_BUILTIN (ObjectPrototypeIsPrototypeOf, ObjectBuiltinsAssembler) {
572
271
Node* receiver = Parameter (Descriptor::kReceiver );
0 commit comments