Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Unified Diff: src/code-stub-assembler.cc

Issue 2775503006: [builtins] Improve performance of array.prototype.filter and map (Closed)
Patch Set: fixes Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/js/array.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/code-stub-assembler.cc
diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
index 0fff014eb50e8fe0337f123aedadb0f218505ab4..8d74ae654f45e79f7efaaab56efff1e3f3817ebe 100644
--- a/src/code-stub-assembler.cc
+++ b/src/code-stub-assembler.cc
@@ -1478,8 +1478,47 @@ Node* CodeStubAssembler::StoreFixedDoubleArrayElement(
return StoreNoWriteBarrier(rep, object, offset, value);
}
-Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context,
- Node* array,
+Node* CodeStubAssembler::EnsureArrayPushable(Node* receiver, Label* bailout) {
+ // Disallow pushing onto prototypes. It might be the JSArray prototype.
+ // Disallow pushing onto non-extensible objects.
+ Comment("Disallow pushing onto prototypes");
+ Node* map = LoadMap(receiver);
+ Node* bit_field2 = LoadMapBitField2(map);
+ int mask = static_cast<int>(Map::IsPrototypeMapBits::kMask) |
+ (1 << Map::kIsExtensible);
+ Node* test = Word32And(bit_field2, Int32Constant(mask));
+ GotoIf(Word32NotEqual(test, Int32Constant(1 << Map::kIsExtensible)), bailout);
+
+ // Disallow pushing onto arrays in dictionary named property mode. We need
+ // to figure out whether the length property is still writable.
+ Comment("Disallow pushing onto arrays in dictionary named property mode");
+ GotoIf(IsDictionaryMap(map), bailout);
+
+ // Check whether the length property is writable. The length property is the
+ // only default named property on arrays. It's nonconfigurable, hence is
+ // guaranteed to stay the first property.
+ Node* descriptors = LoadMapDescriptors(map);
+ Node* details =
+ LoadFixedArrayElement(descriptors, DescriptorArray::ToDetailsIndex(0));
+ GotoIf(IsSetSmi(details, PropertyDetails::kAttributesReadOnlyMask), bailout);
+
+ Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2);
+ return kind;
+}
+
+Node* CodeStubAssembler::PossiblyGrowElementsCapacity(
+ ParameterMode mode, ElementsKind kind, Node* array, Node* length,
+ Node* elements, Node* growth, Label* fits, Label* bailout) {
+ Node* capacity = TaggedToParameter(LoadFixedArrayBaseLength(elements), mode);
+ Node* new_length =
+ IntPtrOrSmiAdd(WordToParameter(growth, mode), length, mode);
+ GotoIfNot(IntPtrOrSmiGreaterThan(new_length, capacity, mode), fits);
+ Node* new_capacity = CalculateNewElementsCapacity(new_length, mode);
+ return GrowElementsCapacity(array, elements, kind, kind, capacity,
+ new_capacity, mode, bailout);
+}
+
+Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* array,
CodeStubArguments& args,
Variable& arg_index,
Label* bailout) {
@@ -1492,20 +1531,14 @@ Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context,
TaggedToParameter(LoadJSArrayLength(array), mode));
Variable var_elements(this, MachineRepresentation::kTagged,
LoadElements(array));
- Node* capacity =
- TaggedToParameter(LoadFixedArrayBaseLength(var_elements.value()), mode);
// Resize the capacity of the fixed array if it doesn't fit.
Label fits(this, &var_elements);
Node* first = arg_index.value();
Node* growth = IntPtrSub(args.GetLength(), first);
- Node* new_length =
- IntPtrOrSmiAdd(WordToParameter(growth, mode), var_length.value(), mode);
- GotoIfNot(IntPtrOrSmiGreaterThan(new_length, capacity, mode), &fits);
- Node* new_capacity = CalculateNewElementsCapacity(new_length, mode);
- var_elements.Bind(GrowElementsCapacity(array, var_elements.value(), kind,
- kind, capacity, new_capacity, mode,
- &pre_bailout));
+ var_elements.Bind(PossiblyGrowElementsCapacity(
+ mode, kind, array, var_length.value(), var_elements.value(), growth,
+ &fits, &pre_bailout));
Goto(&fits);
Bind(&fits);
Node* elements = var_elements.value();
@@ -1516,22 +1549,8 @@ Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context,
args.ForEach(
push_vars,
[this, kind, mode, elements, &var_length, &pre_bailout](Node* arg) {
- if (IsFastSmiElementsKind(kind)) {
- GotoIf(TaggedIsNotSmi(arg), &pre_bailout);
- } else if (IsFastDoubleElementsKind(kind)) {
- GotoIfNotNumber(arg, &pre_bailout);
- }
- if (IsFastDoubleElementsKind(kind)) {
- Node* double_value = ChangeNumberToFloat64(arg);
- StoreFixedDoubleArrayElement(elements, var_length.value(),
- Float64SilenceNaN(double_value), mode);
- } else {
- WriteBarrierMode barrier_mode = IsFastSmiElementsKind(kind)
- ? SKIP_WRITE_BARRIER
- : UPDATE_WRITE_BARRIER;
- StoreFixedArrayElement(elements, var_length.value(), arg,
- barrier_mode, 0, mode);
- }
+ TryStoreArrayElement(kind, mode, &pre_bailout, elements,
+ var_length.value(), arg);
Increment(var_length, 1, mode);
},
first, nullptr);
@@ -1556,6 +1575,72 @@ Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context,
return var_tagged_length.value();
}
+void CodeStubAssembler::TryStoreArrayElement(ElementsKind kind,
+ ParameterMode mode, Label* bailout,
+ Node* elements, Node* index,
+ Node* value) {
+ if (IsFastSmiElementsKind(kind)) {
+ GotoIf(TaggedIsNotSmi(value), bailout);
+ } else if (IsFastDoubleElementsKind(kind)) {
+ GotoIfNotNumber(value, bailout);
+ }
+ if (IsFastDoubleElementsKind(kind)) {
+ Node* double_value = ChangeNumberToFloat64(value);
+ StoreFixedDoubleArrayElement(elements, index,
+ Float64SilenceNaN(double_value), mode);
+ } else {
+ WriteBarrierMode barrier_mode =
+ IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
+ StoreFixedArrayElement(elements, index, value, barrier_mode, 0, mode);
+ }
+}
+
+Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* array,
+ Node* value, Label* bailout) {
+ Comment("BuildAppendJSArray: %s", ElementsKindToString(kind));
+ Label success(this);
+ Variable var_tagged_length(this, MachineRepresentation::kTagged);
jgruber 2017/04/19 10:25:28 Nit: VARIABLE(var_x, ...) instead of Variable var_
mvstanton 2017/04/23 09:00:09 Done.
+ ParameterMode mode = OptimalParameterMode();
+ Variable var_length(this, OptimalParameterRepresentation(),
+ TaggedToParameter(LoadJSArrayLength(array), mode));
+ Variable var_elements(this, MachineRepresentation::kTagged,
+ LoadElements(array));
+
+ // Resize the capacity of the fixed array if it doesn't fit.
+ Label fits(this, &var_elements);
+ Node* growth = IntPtrOrSmiConstant(1, mode);
+ var_elements.Bind(PossiblyGrowElementsCapacity(
+ mode, kind, array, var_length.value(), var_elements.value(), growth,
+ &fits, bailout));
+ /*
+ Node* new_length = IntPtrOrSmiAdd(growth, var_length.value(), mode);
jgruber 2017/04/19 10:25:28 Nit: Leftover code?
mvstanton 2017/04/23 09:00:09 Done.
+ GotoIfNot(IntPtrOrSmiGreaterThan(new_length, capacity, mode), &fits);
+ Node* new_capacity = CalculateNewElementsCapacity(new_length, mode);
+ var_elements.Bind(GrowElementsCapacity(array, var_elements.value(), kind,
+ kind, capacity, new_capacity, mode,
+ bailout));
+ */
+ Goto(&fits);
+ Bind(&fits);
+ Node* elements = var_elements.value();
+
+ // Push each argument onto the end of the array now that there is enough
+ // capacity.
+ TryStoreArrayElement(kind, mode, bailout, elements, var_length.value(),
+ value);
+ Increment(var_length, 1, mode);
+
+ {
+ Node* length = ParameterToTagged(var_length.value(), mode);
+ var_tagged_length.Bind(length);
jgruber 2017/04/19 10:25:28 Nit: var_tagged_length and the success label aren'
mvstanton 2017/04/23 09:00:09 Good idea, thanks!
+ StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length);
+ Goto(&success);
+ }
+
+ Bind(&success);
+ return var_tagged_length.value();
+}
+
Node* CodeStubAssembler::AllocateHeapNumber(MutableMode mode) {
Node* result = Allocate(HeapNumber::kSize, kNone);
Heap::RootListIndex heap_map_index =
@@ -8369,6 +8454,11 @@ Node* CodeStubAssembler::IsHoleyFastElementsKind(Node* elements_kind) {
return Word32Equal(holey_elements, Int32Constant(1));
}
+Node* CodeStubAssembler::IsElementsKindGreaterThan(
+ Node* target_kind, ElementsKind reference_kind) {
+ return Int32GreaterThan(target_kind, Int32Constant(reference_kind));
+}
+
Node* CodeStubAssembler::IsDebugActive() {
Node* is_debug_active = Load(
MachineType::Uint8(),
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/js/array.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698