summaryrefslogtreecommitdiff
path: root/deps/v8/src/builtins/builtins-object-gen.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/builtins/builtins-object-gen.cc')
-rw-r--r--deps/v8/src/builtins/builtins-object-gen.cc182
1 files changed, 144 insertions, 38 deletions
diff --git a/deps/v8/src/builtins/builtins-object-gen.cc b/deps/v8/src/builtins/builtins-object-gen.cc
index 6d397952d2..fb89694c31 100644
--- a/deps/v8/src/builtins/builtins-object-gen.cc
+++ b/deps/v8/src/builtins/builtins-object-gen.cc
@@ -266,7 +266,7 @@ TNode<JSArray> ObjectEntriesValuesBuiltinsAssembler::FastGetOwnValuesOrEntries(
TNode<Context> context, TNode<JSObject> object,
Label* if_call_runtime_with_fast_path, Label* if_no_properties,
CollectType collect_type) {
- Node* native_context = LoadNativeContext(context);
+ TNode<Context> native_context = LoadNativeContext(context);
TNode<Map> array_map =
LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context);
TNode<Map> map = LoadMap(object);
@@ -274,9 +274,9 @@ TNode<JSArray> ObjectEntriesValuesBuiltinsAssembler::FastGetOwnValuesOrEntries(
Label if_has_enum_cache(this), if_not_has_enum_cache(this),
collect_entries(this);
- Node* object_enum_length =
- DecodeWordFromWord32<Map::EnumLengthBits>(bit_field3);
- Node* has_enum_cache = WordNotEqual(
+ TNode<IntPtrT> object_enum_length =
+ Signed(DecodeWordFromWord32<Map::EnumLengthBits>(bit_field3));
+ TNode<BoolT> has_enum_cache = WordNotEqual(
object_enum_length, IntPtrConstant(kInvalidEnumCacheSentinel));
// In case, we found enum_cache in object,
@@ -292,9 +292,8 @@ TNode<JSArray> ObjectEntriesValuesBuiltinsAssembler::FastGetOwnValuesOrEntries(
BIND(&if_has_enum_cache);
{
GotoIf(WordEqual(object_enum_length, IntPtrConstant(0)), if_no_properties);
- TNode<FixedArray> values_or_entries = TNode<FixedArray>::UncheckedCast(
- AllocateFixedArray(PACKED_ELEMENTS, object_enum_length,
- INTPTR_PARAMETERS, kAllowLargeObjectAllocation));
+ TNode<FixedArray> values_or_entries = AllocateFixedArray(
+ PACKED_ELEMENTS, object_enum_length, kAllowLargeObjectAllocation);
// If in case we have enum_cache,
// we can't detect accessor of object until loop through descriptors.
@@ -342,8 +341,7 @@ TNode<JSArray> ObjectEntriesValuesBuiltinsAssembler::FastGetOwnValuesOrEntries(
// the next descriptor.
GotoIfNot(IsPropertyEnumerable(details), &next_descriptor);
- VARIABLE(var_property_value, MachineRepresentation::kTagged,
- UndefinedConstant());
+ TVARIABLE(Object, var_property_value, UndefinedConstant());
TNode<IntPtrT> descriptor_name_index = ToKeyIndex<DescriptorArray>(
Unsigned(TruncateIntPtrToInt32(var_descriptor_number.value())));
@@ -353,7 +351,7 @@ TNode<JSArray> ObjectEntriesValuesBuiltinsAssembler::FastGetOwnValuesOrEntries(
&var_property_value);
// If kind is "value", append value to properties.
- Node* value = var_property_value.value();
+ TNode<Object> value = var_property_value.value();
if (collect_type == CollectType::kEntries) {
// Let entry be CreateArrayFromList(« key, value »).
@@ -364,7 +362,7 @@ TNode<JSArray> ObjectEntriesValuesBuiltinsAssembler::FastGetOwnValuesOrEntries(
IntPtrConstant(2));
StoreFixedArrayElement(elements, 0, next_key, SKIP_WRITE_BARRIER);
StoreFixedArrayElement(elements, 1, value, SKIP_WRITE_BARRIER);
- value = array;
+ value = TNode<JSArray>::UncheckedCast(array);
}
StoreFixedArrayElement(values_or_entries, var_result_index.value(),
@@ -487,10 +485,10 @@ TF_BUILTIN(ObjectPrototypeHasOwnProperty, ObjectBuiltinsAssembler) {
// ES #sec-object.assign
TF_BUILTIN(ObjectAssign, ObjectBuiltinsAssembler) {
TNode<IntPtrT> argc =
- ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
+ ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
CodeStubArguments args(this, argc);
- TNode<Context> context = CAST(Parameter(BuiltinDescriptor::kContext));
+ TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> target = args.GetOptionalArgumentValue(0);
// 1. Let to be ? ToObject(target).
@@ -583,8 +581,8 @@ void ObjectBuiltinsAssembler::ObjectAssignFast(TNode<Context> context,
DescriptorArrayForEach(
list, Unsigned(Int32Constant(0)), nof_descriptors,
[=, &var_stable](TNode<UintPtrT> descriptor_key_index) {
- TNode<Name> next_key =
- CAST(LoadFixedArrayElement(from_descriptors, descriptor_key_index));
+ TNode<Name> next_key = CAST(
+ LoadWeakFixedArrayElement(from_descriptors, descriptor_key_index));
TVARIABLE(Object, var_value, SmiConstant(0));
Label do_store(this), next_iteration(this);
@@ -622,12 +620,11 @@ void ObjectBuiltinsAssembler::ObjectAssignFast(TNode<Context> context,
BIND(&if_found_fast);
{
- Node* descriptors = var_meta_storage.value();
- Node* name_index = var_entry.value();
+ TNode<DescriptorArray> descriptors = CAST(var_meta_storage.value());
+ TNode<IntPtrT> name_index = var_entry.value();
// Skip non-enumerable properties.
- var_details =
- LoadDetailsByKeyIndex<DescriptorArray>(descriptors, name_index);
+ var_details = LoadDetailsByKeyIndex(descriptors, name_index);
GotoIf(IsSetWord32(var_details.value(),
PropertyDetails::kAttributesDontEnumMask),
&next_iteration);
@@ -782,6 +779,108 @@ TF_BUILTIN(ObjectKeys, ObjectBuiltinsAssembler) {
}
}
+// ES #sec-object.getOwnPropertyNames
+TF_BUILTIN(ObjectGetOwnPropertyNames, ObjectBuiltinsAssembler) {
+ Node* object = Parameter(Descriptor::kObject);
+ Node* context = Parameter(Descriptor::kContext);
+
+ VARIABLE(var_length, MachineRepresentation::kTagged);
+ VARIABLE(var_elements, MachineRepresentation::kTagged);
+ Label if_empty(this, Label::kDeferred), if_empty_elements(this),
+ if_fast(this), try_fast(this, Label::kDeferred),
+ if_slow(this, Label::kDeferred), if_join(this);
+
+ // Check if the {object} has a usable enum cache.
+ GotoIf(TaggedIsSmi(object), &if_slow);
+ Node* object_map = LoadMap(object);
+ Node* object_bit_field3 = LoadMapBitField3(object_map);
+ Node* object_enum_length =
+ DecodeWordFromWord32<Map::EnumLengthBits>(object_bit_field3);
+ GotoIf(
+ WordEqual(object_enum_length, IntPtrConstant(kInvalidEnumCacheSentinel)),
+ &try_fast);
+
+ // Ensure that the {object} doesn't have any elements.
+ CSA_ASSERT(this, IsJSObjectMap(object_map));
+ Node* object_elements = LoadElements(object);
+ GotoIf(IsEmptyFixedArray(object_elements), &if_empty_elements);
+ Branch(IsEmptySlowElementDictionary(object_elements), &if_empty_elements,
+ &if_slow);
+
+ // Check whether all own properties are enumerable.
+ BIND(&if_empty_elements);
+ Node* number_descriptors =
+ DecodeWordFromWord32<Map::NumberOfOwnDescriptorsBits>(object_bit_field3);
+ GotoIfNot(WordEqual(object_enum_length, number_descriptors), &if_slow);
+
+ // Check whether there are enumerable properties.
+ Branch(WordEqual(object_enum_length, IntPtrConstant(0)), &if_empty, &if_fast);
+
+ BIND(&if_fast);
+ {
+ // The {object} has a usable enum cache and all own properties are
+ // enumerable, use that.
+ Node* object_descriptors = LoadMapDescriptors(object_map);
+ Node* object_enum_cache =
+ LoadObjectField(object_descriptors, DescriptorArray::kEnumCacheOffset);
+ Node* object_enum_keys =
+ LoadObjectField(object_enum_cache, EnumCache::kKeysOffset);
+
+ // Allocate a JSArray and copy the elements from the {object_enum_keys}.
+ Node* array = nullptr;
+ Node* elements = nullptr;
+ Node* native_context = LoadNativeContext(context);
+ Node* array_map = LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context);
+ Node* array_length = SmiTag(object_enum_length);
+ std::tie(array, elements) = AllocateUninitializedJSArrayWithElements(
+ PACKED_ELEMENTS, array_map, array_length, nullptr, object_enum_length,
+ INTPTR_PARAMETERS);
+ CopyFixedArrayElements(PACKED_ELEMENTS, object_enum_keys, elements,
+ object_enum_length, SKIP_WRITE_BARRIER);
+ Return(array);
+ }
+
+ BIND(&try_fast);
+ {
+ // Let the runtime compute the elements and try initializing enum cache.
+ Node* elements = CallRuntime(Runtime::kObjectGetOwnPropertyNamesTryFast,
+ context, object);
+ var_length.Bind(LoadObjectField(elements, FixedArray::kLengthOffset));
+ var_elements.Bind(elements);
+ Goto(&if_join);
+ }
+
+ BIND(&if_empty);
+ {
+ // The {object} doesn't have any enumerable keys.
+ var_length.Bind(SmiConstant(0));
+ var_elements.Bind(EmptyFixedArrayConstant());
+ Goto(&if_join);
+ }
+
+ BIND(&if_slow);
+ {
+ // Let the runtime compute the elements.
+ Node* elements =
+ CallRuntime(Runtime::kObjectGetOwnPropertyNames, context, object);
+ var_length.Bind(LoadObjectField(elements, FixedArray::kLengthOffset));
+ var_elements.Bind(elements);
+ Goto(&if_join);
+ }
+
+ BIND(&if_join);
+ {
+ // Wrap the elements into a proper JSArray and return that.
+ Node* native_context = LoadNativeContext(context);
+ Node* array_map = LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context);
+ Node* array = AllocateUninitializedJSArrayWithoutElements(
+ array_map, var_length.value(), nullptr);
+ StoreObjectFieldNoWriteBarrier(array, JSArray::kElementsOffset,
+ var_elements.value());
+ Return(array);
+ }
+}
+
TF_BUILTIN(ObjectValues, ObjectEntriesValuesBuiltinsAssembler) {
TNode<JSObject> object =
TNode<JSObject>::UncheckedCast(Parameter(Descriptor::kObject));
@@ -1168,10 +1267,10 @@ TF_BUILTIN(CreateObjectWithoutProperties, ObjectBuiltinsAssembler) {
Comment("Try loading the prototype info");
Node* prototype_info =
LoadMapPrototypeInfo(LoadMap(prototype), &call_runtime);
- Node* weak_cell =
- LoadObjectField(prototype_info, PrototypeInfo::kObjectCreateMap);
- GotoIf(IsUndefined(weak_cell), &call_runtime);
- map.Bind(LoadWeakCellValue(weak_cell, &call_runtime));
+ TNode<MaybeObject> maybe_map = LoadMaybeWeakObjectField(
+ prototype_info, PrototypeInfo::kObjectCreateMapOffset);
+ GotoIf(IsStrongReferenceTo(maybe_map, UndefinedConstant()), &call_runtime);
+ map.Bind(ToWeakHeapObject(maybe_map, &call_runtime));
Goto(&instantiate_map);
}
@@ -1197,12 +1296,12 @@ TF_BUILTIN(ObjectCreate, ObjectBuiltinsAssembler) {
int const kPropertiesArg = 1;
Node* argc =
- ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
+ ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
CodeStubArguments args(this, argc);
Node* prototype = args.GetOptionalArgumentValue(kPrototypeArg);
Node* properties = args.GetOptionalArgumentValue(kPropertiesArg);
- Node* context = Parameter(BuiltinDescriptor::kContext);
+ Node* context = Parameter(Descriptor::kContext);
Label call_runtime(this, Label::kDeferred), prototype_valid(this),
no_properties(this);
@@ -1263,10 +1362,11 @@ TF_BUILTIN(ObjectCreate, ObjectBuiltinsAssembler) {
Node* prototype_info =
LoadMapPrototypeInfo(LoadMap(prototype), &call_runtime);
Comment("Load ObjectCreateMap from PrototypeInfo");
- Node* weak_cell =
- LoadObjectField(prototype_info, PrototypeInfo::kObjectCreateMap);
- GotoIf(IsUndefined(weak_cell), &call_runtime);
- map.Bind(LoadWeakCellValue(weak_cell, &call_runtime));
+ TNode<MaybeObject> maybe_map = LoadMaybeWeakObjectField(
+ prototype_info, PrototypeInfo::kObjectCreateMapOffset);
+ GotoIf(IsStrongReferenceTo(maybe_map, UndefinedConstant()),
+ &call_runtime);
+ map.Bind(ToWeakHeapObject(maybe_map, &call_runtime));
Goto(&instantiate_map);
}
@@ -1366,12 +1466,17 @@ TF_BUILTIN(CreateGeneratorObject, ObjectBuiltinsAssembler) {
LoadObjectField(closure, JSFunction::kSharedFunctionInfoOffset);
Node* bytecode_array = LoadSharedFunctionInfoBytecodeArray(shared);
+ Node* formal_parameter_count = ChangeInt32ToIntPtr(
+ LoadObjectField(shared, SharedFunctionInfo::kFormalParameterCountOffset,
+ MachineType::Uint16()));
Node* frame_size = ChangeInt32ToIntPtr(LoadObjectField(
bytecode_array, BytecodeArray::kFrameSizeOffset, MachineType::Int32()));
- Node* size = WordSar(frame_size, IntPtrConstant(kPointerSizeLog2));
- Node* register_file = AllocateFixedArray(HOLEY_ELEMENTS, size);
- FillFixedArrayWithValue(HOLEY_ELEMENTS, register_file, IntPtrConstant(0),
- size, Heap::kUndefinedValueRootIndex);
+ Node* size = IntPtrAdd(WordSar(frame_size, IntPtrConstant(kPointerSizeLog2)),
+ formal_parameter_count);
+ Node* parameters_and_registers = AllocateFixedArray(HOLEY_ELEMENTS, size);
+ FillFixedArrayWithValue(HOLEY_ELEMENTS, parameters_and_registers,
+ IntPtrConstant(0), size,
+ Heap::kUndefinedValueRootIndex);
// TODO(cbruni): support start_offset to avoid double initialization.
Node* result = AllocateJSObjectFromMap(maybe_map, nullptr, nullptr, kNone,
kWithSlackTracking);
@@ -1381,8 +1486,9 @@ TF_BUILTIN(CreateGeneratorObject, ObjectBuiltinsAssembler) {
context);
StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kReceiverOffset,
receiver);
- StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kRegisterFileOffset,
- register_file);
+ StoreObjectFieldNoWriteBarrier(
+ result, JSGeneratorObject::kParametersAndRegistersOffset,
+ parameters_and_registers);
Node* executing = SmiConstant(JSGeneratorObject::kGeneratorExecuting);
StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kContinuationOffset,
executing);
@@ -1403,9 +1509,9 @@ TF_BUILTIN(CreateGeneratorObject, ObjectBuiltinsAssembler) {
// ES6 section 19.1.2.7 Object.getOwnPropertyDescriptor ( O, P )
TF_BUILTIN(ObjectGetOwnPropertyDescriptor, ObjectBuiltinsAssembler) {
- Node* argc = Parameter(BuiltinDescriptor::kArgumentsCount);
- Node* context = Parameter(BuiltinDescriptor::kContext);
- CSA_ASSERT(this, IsUndefined(Parameter(BuiltinDescriptor::kNewTarget)));
+ Node* argc = Parameter(Descriptor::kJSActualArgumentsCount);
+ Node* context = Parameter(Descriptor::kContext);
+ CSA_ASSERT(this, IsUndefined(Parameter(Descriptor::kJSNewTarget)));
CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
Node* object = args.GetOptionalArgumentValue(0);