@@ -779,6 +779,108 @@ TF_BUILTIN(ObjectKeys, ObjectBuiltinsAssembler) {
779779 }
780780}
781781
782+ // ES #sec-object.getOwnPropertyNames
783+ TF_BUILTIN (ObjectGetOwnPropertyNames, ObjectBuiltinsAssembler) {
784+ Node* object = Parameter (Descriptor::kObject );
785+ Node* context = Parameter (Descriptor::kContext );
786+
787+ VARIABLE (var_length, MachineRepresentation::kTagged );
788+ VARIABLE (var_elements, MachineRepresentation::kTagged );
789+ Label if_empty (this , Label::kDeferred ), if_empty_elements (this ),
790+ if_fast (this ), try_fast (this , Label::kDeferred ),
791+ if_slow (this , Label::kDeferred ), if_join (this );
792+
793+ // Check if the {object} has a usable enum cache.
794+ GotoIf (TaggedIsSmi (object), &if_slow);
795+ Node* object_map = LoadMap (object);
796+ Node* object_bit_field3 = LoadMapBitField3 (object_map);
797+ Node* object_enum_length =
798+ DecodeWordFromWord32<Map::EnumLengthBits>(object_bit_field3);
799+ GotoIf (
800+ WordEqual (object_enum_length, IntPtrConstant (kInvalidEnumCacheSentinel )),
801+ &try_fast);
802+
803+ // Ensure that the {object} doesn't have any elements.
804+ CSA_ASSERT (this , IsJSObjectMap (object_map));
805+ Node* object_elements = LoadElements (object);
806+ GotoIf (IsEmptyFixedArray (object_elements), &if_empty_elements);
807+ Branch (IsEmptySlowElementDictionary (object_elements), &if_empty_elements,
808+ &if_slow);
809+
810+ // Check whether all own properties are enumerable.
811+ BIND (&if_empty_elements);
812+ Node* number_descriptors =
813+ DecodeWordFromWord32<Map::NumberOfOwnDescriptorsBits>(object_bit_field3);
814+ GotoIfNot (WordEqual (object_enum_length, number_descriptors), &if_slow);
815+
816+ // Check whether there are enumerable properties.
817+ Branch (WordEqual (object_enum_length, IntPtrConstant (0 )), &if_empty, &if_fast);
818+
819+ BIND (&if_fast);
820+ {
821+ // The {object} has a usable enum cache and all own properties are
822+ // enumerable, use that.
823+ Node* object_descriptors = LoadMapDescriptors (object_map);
824+ Node* object_enum_cache =
825+ LoadObjectField (object_descriptors, DescriptorArray::kEnumCacheOffset );
826+ Node* object_enum_keys =
827+ LoadObjectField (object_enum_cache, EnumCache::kKeysOffset );
828+
829+ // Allocate a JSArray and copy the elements from the {object_enum_keys}.
830+ Node* array = nullptr ;
831+ Node* elements = nullptr ;
832+ Node* native_context = LoadNativeContext (context);
833+ Node* array_map = LoadJSArrayElementsMap (PACKED_ELEMENTS, native_context);
834+ Node* array_length = SmiTag (object_enum_length);
835+ std::tie (array, elements) = AllocateUninitializedJSArrayWithElements (
836+ PACKED_ELEMENTS, array_map, array_length, nullptr , object_enum_length,
837+ INTPTR_PARAMETERS);
838+ CopyFixedArrayElements (PACKED_ELEMENTS, object_enum_keys, elements,
839+ object_enum_length, SKIP_WRITE_BARRIER);
840+ Return (array);
841+ }
842+
843+ BIND (&try_fast);
844+ {
845+ // Let the runtime compute the elements and try initializing enum cache.
846+ Node* elements = CallRuntime (Runtime::kObjectGetOwnPropertyNamesTryFast ,
847+ context, object);
848+ var_length.Bind (LoadObjectField (elements, FixedArray::kLengthOffset ));
849+ var_elements.Bind (elements);
850+ Goto (&if_join);
851+ }
852+
853+ BIND (&if_empty);
854+ {
855+ // The {object} doesn't have any enumerable keys.
856+ var_length.Bind (SmiConstant (0 ));
857+ var_elements.Bind (EmptyFixedArrayConstant ());
858+ Goto (&if_join);
859+ }
860+
861+ BIND (&if_slow);
862+ {
863+ // Let the runtime compute the elements.
864+ Node* elements =
865+ CallRuntime (Runtime::kObjectGetOwnPropertyNames , context, object);
866+ var_length.Bind (LoadObjectField (elements, FixedArray::kLengthOffset ));
867+ var_elements.Bind (elements);
868+ Goto (&if_join);
869+ }
870+
871+ BIND (&if_join);
872+ {
873+ // Wrap the elements into a proper JSArray and return that.
874+ Node* native_context = LoadNativeContext (context);
875+ Node* array_map = LoadJSArrayElementsMap (PACKED_ELEMENTS, native_context);
876+ Node* array = AllocateUninitializedJSArrayWithoutElements (
877+ array_map, var_length.value (), nullptr );
878+ StoreObjectFieldNoWriteBarrier (array, JSArray::kElementsOffset ,
879+ var_elements.value ());
880+ Return (array);
881+ }
882+ }
883+
782884TF_BUILTIN (ObjectValues, ObjectEntriesValuesBuiltinsAssembler) {
783885 TNode<JSObject> object =
784886 TNode<JSObject>::UncheckedCast (Parameter (Descriptor::kObject ));
0 commit comments