Index: src/code-stub-assembler.cc |
diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc |
index 6d4ce690ff97f01062099ea524a4ea1c767f1cef..0cad3b77217fe239940179ac5593a3efc2536f68 100644 |
--- a/src/code-stub-assembler.cc |
+++ b/src/code-stub-assembler.cc |
@@ -525,6 +525,12 @@ Node* CodeStubAssembler::TaggedIsSmi(Node* a) { |
IntPtrConstant(0)); |
} |
+Node* CodeStubAssembler::TaggedIsNotSmi(Node* a) { |
+ return WordNotEqual( |
+ WordAnd(BitcastTaggedToWord(a), IntPtrConstant(kSmiTagMask)), |
+ IntPtrConstant(0)); |
+} |
+ |
Node* CodeStubAssembler::WordIsPositiveSmi(Node* a) { |
return WordEqual(WordAnd(a, IntPtrConstant(kSmiTagMask | kSmiSignMask)), |
IntPtrConstant(0)); |
@@ -653,8 +659,9 @@ void CodeStubAssembler::BranchIfJSObject(Node* object, Label* if_true, |
if_true, if_false); |
} |
-void CodeStubAssembler::BranchIfFastJSArray(Node* object, Node* context, |
- Label* if_true, Label* if_false) { |
+void CodeStubAssembler::BranchIfFastJSArray( |
+ Node* object, Node* context, CodeStubAssembler::FastJSArrayAccessMode mode, |
+ Label* if_true, Label* if_false) { |
// Bailout if receiver is a Smi. |
GotoIf(TaggedIsSmi(object), if_false); |
@@ -670,8 +677,9 @@ void CodeStubAssembler::BranchIfFastJSArray(Node* object, Node* context, |
GotoUnless(IsFastElementsKind(elements_kind), if_false); |
// Check prototype chain if receiver does not have packed elements. |
- GotoUnless(IsHoleyFastElementsKind(elements_kind), if_true); |
- |
+ if (mode == FastJSArrayAccessMode::INBOUNDS_READ) { |
+ GotoUnless(IsHoleyFastElementsKind(elements_kind), if_true); |
+ } |
BranchIfPrototypesHaveNoElements(map, if_true, if_false); |
} |
@@ -1361,6 +1369,79 @@ Node* CodeStubAssembler::StoreFixedDoubleArrayElement( |
return StoreNoWriteBarrier(rep, object, offset, value); |
} |
+Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context, |
+ Node* array, |
+ CodeStubArguments& args, |
+ Variable& arg_index, |
+ Label* bailout) { |
+ Comment("BuildAppendJSArray: %s", ElementsKindToString(kind)); |
+ Label pre_bailout(this); |
+ Label success(this); |
+ Variable elements(this, MachineRepresentation::kTagged); |
+ ParameterMode mode = OptimalParameterMode(); |
+ Variable length(this, OptimalParameterRepresentation()); |
+ length.Bind(UntagParameter(LoadJSArrayLength(array), mode)); |
+ elements.Bind(LoadElements(array)); |
+ Node* capacity = |
+ UntagParameter(LoadFixedArrayBaseLength(elements.value()), mode); |
+ |
+ // Resize the capacity of the fixed array if it doesn't fit. |
+ Label fits(this, &elements); |
+ Node* first = arg_index.value(); |
+ Node* growth = IntPtrSubFoldConstants(args.GetLength(), first); |
+ Node* new_length = IntPtrAdd( |
+ mode == INTPTR_PARAMETERS ? growth : SmiTag(growth), length.value()); |
+ GotoUnless(IntPtrGreaterThanOrEqual(new_length, capacity), &fits); |
+ Node* new_capacity = CalculateNewElementsCapacity( |
+ IntPtrAdd(new_length, IntPtrOrSmiConstant(1, mode)), mode); |
+ elements.Bind(GrowElementsCapacity(array, elements.value(), kind, kind, |
+ capacity, new_capacity, mode, |
+ &pre_bailout)); |
+ Goto(&fits); |
+ Bind(&fits); |
+ |
+ // Push each argument onto the end of the array now that there is enough |
+ // capacity. |
+ CodeStubAssembler::VariableList push_vars({&length, &elements}, zone()); |
+ args.ForEach( |
+ push_vars, |
+ [kind, mode, &length, &elements, &pre_bailout]( |
+ CodeStubAssembler* assembler, Node* arg) { |
+ if (IsFastSmiElementsKind(kind)) { |
+ assembler->GotoIf(assembler->TaggedIsNotSmi(arg), &pre_bailout); |
+ } else if (IsFastDoubleElementsKind(kind)) { |
+ assembler->GotoIfNotNumber(arg, &pre_bailout); |
+ } |
+ if (IsFastDoubleElementsKind(kind)) { |
+ Node* double_value = assembler->ChangeNumberToFloat64(arg); |
+ assembler->StoreFixedDoubleArrayElement( |
+ elements.value(), length.value(), |
+ assembler->Float64SilenceNaN(double_value), mode); |
+ } else { |
+ WriteBarrierMode barrier_mode = IsFastSmiElementsKind(kind) |
+ ? SKIP_WRITE_BARRIER |
+ : UPDATE_WRITE_BARRIER; |
+ assembler->StoreFixedArrayElement(elements.value(), length.value(), |
+ arg, barrier_mode, 0, mode); |
+ } |
+ assembler->Increment(length, 1, mode); |
+ }, |
+ first, nullptr); |
+ length.Bind(TagParameter(length.value(), mode)); |
+ StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length.value()); |
+ Goto(&success); |
+ |
+ Bind(&pre_bailout); |
+ length.Bind(TagParameter(length.value(), mode)); |
+ Node* diff = SmiSub(length.value(), LoadJSArrayLength(array)); |
+ StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length.value()); |
+ arg_index.Bind(IntPtrAdd(arg_index.value(), SmiUntag(diff))); |
+ Goto(bailout); |
+ |
+ Bind(&success); |
+ return length.value(); |
+} |
+ |
Node* CodeStubAssembler::AllocateHeapNumber(MutableMode mode) { |
Node* result = Allocate(HeapNumber::kSize, kNone); |
Heap::RootListIndex heap_map_index = |
@@ -2130,9 +2211,7 @@ void CodeStubAssembler::CopyStringCharacters(Node* from_string, Node* to_string, |
rep, to_string, |
index_same ? offset : current_to_offset.value(), value); |
if (!index_same) { |
- current_to_offset.Bind(assembler->IntPtrAdd( |
- current_to_offset.value(), |
- assembler->IntPtrConstant(to_increment))); |
+ assembler->Increment(current_to_offset, to_increment); |
} |
}, |
from_increment, IndexAdvanceMode::kPost); |
@@ -2554,6 +2633,25 @@ Node* CodeStubAssembler::ToThisString(Node* context, Node* value, |
return var_value.value(); |
} |
+Node* CodeStubAssembler::ChangeNumberToFloat64(compiler::Node* value) { |
+ Variable result(this, MachineRepresentation::kFloat64); |
+ Label smi(this); |
+ Label done(this, &result); |
+ GotoIf(TaggedIsSmi(value), &smi); |
+ result.Bind( |
+ LoadObjectField(value, HeapNumber::kValueOffset, MachineType::Float64())); |
+ Goto(&done); |
+ |
+ Bind(&smi); |
+ { |
+ result.Bind(ChangeInt32ToFloat64(SmiUntag(value))); |
+ Goto(&done); |
+ } |
+ |
+ Bind(&done); |
+ return result.value(); |
+} |
+ |
Node* CodeStubAssembler::ToThisValue(Node* context, Node* value, |
PrimitiveType primitive_type, |
char const* method_name) { |
@@ -3966,6 +4064,16 @@ void CodeStubAssembler::DecrementCounter(StatsCounter* counter, int delta) { |
} |
} |
+void CodeStubAssembler::Increment(Variable& variable, int value, |
+ ParameterMode mode) { |
+ DCHECK_IMPLIES(mode == INTPTR_PARAMETERS, |
+ variable.rep() == MachineType::PointerRepresentation()); |
+ DCHECK_IMPLIES(mode == SMI_PARAMETERS, |
+ variable.rep() == MachineRepresentation::kTagged || |
+ variable.rep() == MachineRepresentation::kTaggedSigned); |
+ variable.Bind(IntPtrAdd(variable.value(), IntPtrOrSmiConstant(value, mode))); |
+} |
+ |
void CodeStubAssembler::Use(Label* label) { |
GotoIf(Word32Equal(Int32Constant(0), Int32Constant(1)), label); |
} |
@@ -4126,7 +4234,6 @@ void CodeStubAssembler::NameDictionaryLookup(Node* dictionary, |
Goto(&loop); |
Bind(&loop); |
{ |
- Node* count = var_count.value(); |
Node* entry = var_entry.value(); |
Node* index = EntryToIndex<Dictionary>(entry); |
@@ -4143,10 +4250,9 @@ void CodeStubAssembler::NameDictionaryLookup(Node* dictionary, |
} |
// See Dictionary::NextProbe(). |
- count = IntPtrAdd(count, IntPtrConstant(1)); |
- entry = WordAnd(IntPtrAdd(entry, count), mask); |
+ Increment(var_count); |
+ entry = WordAnd(IntPtrAdd(entry, var_count.value()), mask); |
- var_count.Bind(count); |
var_entry.Bind(entry); |
Goto(&loop); |
} |
@@ -4209,7 +4315,6 @@ void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, |
Goto(&loop); |
Bind(&loop); |
{ |
- Node* count = var_count.value(); |
Node* entry = var_entry->value(); |
Node* index = EntryToIndex<Dictionary>(entry); |
@@ -4237,10 +4342,9 @@ void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, |
Bind(&next_probe); |
// See Dictionary::NextProbe(). |
- count = IntPtrAdd(count, IntPtrConstant(1)); |
- entry = WordAnd(IntPtrAdd(entry, count), mask); |
+ Increment(var_count); |
+ entry = WordAnd(IntPtrAdd(entry, var_count.value()), mask); |
- var_count.Bind(count); |
var_entry->Bind(entry); |
Goto(&loop); |
} |
@@ -5902,11 +6006,11 @@ void CodeStubAssembler::BuildFastLoop( |
Bind(&loop); |
{ |
if (mode == IndexAdvanceMode::kPre) { |
- var.Bind(IntPtrAdd(var.value(), IntPtrConstant(increment))); |
+ Increment(var, increment); |
} |
body(this, var.value()); |
if (mode == IndexAdvanceMode::kPost) { |
- var.Bind(IntPtrAdd(var.value(), IntPtrConstant(increment))); |
+ Increment(var, increment); |
} |
Branch(WordNotEqual(var.value(), end_index), &loop, &after_loop); |
} |
@@ -7545,6 +7649,20 @@ Node* CodeStubAssembler::NumberInc(Node* value) { |
return var_result.value(); |
} |
+void CodeStubAssembler::GotoIfNotNumber(Node* input, Label* is_not_number) { |
+ Label is_number(this); |
+ GotoIf(TaggedIsSmi(input), &is_number); |
+ Node* input_map = LoadMap(input); |
+ Branch(IsHeapNumberMap(input_map), &is_number, is_not_number); |
+ Bind(&is_number); |
+} |
+ |
+void CodeStubAssembler::GotoIfNumber(Node* input, Label* is_number) { |
+ GotoIf(TaggedIsSmi(input), is_number); |
+ Node* input_map = LoadMap(input); |
+ GotoIf(IsHeapNumberMap(input_map), is_number); |
+} |
+ |
Node* CodeStubAssembler::CreateArrayIterator(Node* array, Node* array_map, |
Node* array_type, Node* context, |
IterationKind mode) { |
@@ -7601,7 +7719,8 @@ Node* CodeStubAssembler::CreateArrayIterator(Node* array, Node* array_map, |
Bind(&if_isgeneric); |
{ |
Label if_isfast(this), if_isslow(this); |
- BranchIfFastJSArray(array, context, &if_isfast, &if_isslow); |
+ BranchIfFastJSArray(array, context, FastJSArrayAccessMode::INBOUNDS_READ, |
+ &if_isfast, &if_isslow); |
Bind(&if_isfast); |
{ |
@@ -7635,7 +7754,8 @@ Node* CodeStubAssembler::CreateArrayIterator(Node* array, Node* array_map, |
Bind(&if_isgeneric); |
{ |
Label if_isfast(this), if_isslow(this); |
- BranchIfFastJSArray(array, context, &if_isfast, &if_isslow); |
+ BranchIfFastJSArray(array, context, FastJSArrayAccessMode::INBOUNDS_READ, |
+ &if_isfast, &if_isslow); |
Bind(&if_isfast); |
{ |
@@ -7778,13 +7898,14 @@ CodeStubArguments::CodeStubArguments(CodeStubAssembler* assembler, Node* argc, |
} |
} |
-Node* CodeStubArguments::GetReceiver() { |
+Node* CodeStubArguments::GetReceiver() const { |
return assembler_->Load(MachineType::AnyTagged(), arguments_, |
assembler_->IntPtrConstant(kPointerSize)); |
} |
Node* CodeStubArguments::AtIndex(Node* index, |
- CodeStubAssembler::ParameterMode mode) { |
+ CodeStubAssembler::ParameterMode mode) const { |
+ typedef compiler::Node Node; |
Node* negated_index = assembler_->IntPtrSubFoldConstants( |
assembler_->IntPtrOrSmiConstant(0, mode), index); |
Node* offset = |
@@ -7792,7 +7913,7 @@ Node* CodeStubArguments::AtIndex(Node* index, |
return assembler_->Load(MachineType::AnyTagged(), arguments_, offset); |
} |
-Node* CodeStubArguments::AtIndex(int index) { |
+Node* CodeStubArguments::AtIndex(int index) const { |
return AtIndex(assembler_->IntPtrConstant(index)); |
} |