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

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

Issue 2407813002: [stubs] Port StringAddStub to TF (Closed)
Patch Set: Remove stray change Created 4 years, 2 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
Index: src/code-stub-assembler.cc
diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
index a72e267f391581a840defb56e0dfe7e5b25a3dc7..c28f8fc50c6aefd63b1bcc877e00cffcb8999e3c 100644
--- a/src/code-stub-assembler.cc
+++ b/src/code-stub-assembler.cc
@@ -71,6 +71,43 @@ Node* CodeStubAssembler::IntPtrOrSmiConstant(int value, ParameterMode mode) {
}
}
+Node* CodeStubAssembler::IntPtrAddFoldConstants(Node* left, Node* right) {
+ int32_t left_constant;
+ bool is_left_constant = ToInt32Constant(left, left_constant);
+ int32_t right_constant;
+ bool is_right_constant = ToInt32Constant(right, right_constant);
+ if (is_left_constant) {
+ if (is_right_constant) {
+ return IntPtrConstant(left_constant + right_constant);
+ }
+ if (left_constant == 0) {
+ return right;
+ }
+ } else if (is_right_constant) {
+ if (right_constant == 0) {
+ return left;
+ }
+ }
+ return IntPtrAdd(left, right);
+}
+
+Node* CodeStubAssembler::IntPtrSubFoldConstants(Node* left, Node* right) {
+ int32_t left_constant;
+ bool is_left_constant = ToInt32Constant(left, left_constant);
+ int32_t right_constant;
+ bool is_right_constant = ToInt32Constant(right, right_constant);
+ if (is_left_constant) {
+ if (is_right_constant) {
+ return IntPtrConstant(left_constant - right_constant);
+ }
+ } else if (is_right_constant) {
+ if (right_constant == 0) {
+ return left;
+ }
+ }
+ return IntPtrSub(left, right);
+}
+
Node* CodeStubAssembler::Float64Round(Node* x) {
Node* one = Float64Constant(1.0);
Node* one_half = Float64Constant(0.5);
@@ -1212,8 +1249,10 @@ Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value,
return result;
}
-Node* CodeStubAssembler::AllocateSeqOneByteString(int length) {
- Node* result = Allocate(SeqOneByteString::SizeFor(length));
+Node* CodeStubAssembler::AllocateSeqOneByteString(int length,
+ AllocationFlags flags) {
+ Node* result = Allocate(SeqOneByteString::SizeFor(length), flags);
+ DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex));
StoreMapNoWriteBarrier(result, LoadRoot(Heap::kOneByteStringMapRootIndex));
StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset,
SmiConstant(Smi::FromInt(length)));
@@ -1223,7 +1262,8 @@ Node* CodeStubAssembler::AllocateSeqOneByteString(int length) {
return result;
}
-Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length) {
+Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length,
+ AllocationFlags flags) {
Variable var_result(this, MachineRepresentation::kTagged);
// Compute the SeqOneByteString size and check if it fits into new space.
@@ -1240,7 +1280,8 @@ Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length) {
Bind(&if_sizeissmall);
{
// Just allocate the SeqOneByteString in new space.
- Node* result = Allocate(size);
+ Node* result = Allocate(size, flags);
+ DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex));
StoreMapNoWriteBarrier(result, LoadRoot(Heap::kOneByteStringMapRootIndex));
StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset,
SmiFromWord(length));
@@ -1264,8 +1305,10 @@ Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length) {
return var_result.value();
}
-Node* CodeStubAssembler::AllocateSeqTwoByteString(int length) {
- Node* result = Allocate(SeqTwoByteString::SizeFor(length));
+Node* CodeStubAssembler::AllocateSeqTwoByteString(int length,
+ AllocationFlags flags) {
+ Node* result = Allocate(SeqTwoByteString::SizeFor(length), flags);
+ DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex));
StoreMapNoWriteBarrier(result, LoadRoot(Heap::kStringMapRootIndex));
StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset,
SmiConstant(Smi::FromInt(length)));
@@ -1275,7 +1318,8 @@ Node* CodeStubAssembler::AllocateSeqTwoByteString(int length) {
return result;
}
-Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length) {
+Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length,
+ AllocationFlags flags) {
Variable var_result(this, MachineRepresentation::kTagged);
// Compute the SeqTwoByteString size and check if it fits into new space.
@@ -1292,7 +1336,8 @@ Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length) {
Bind(&if_sizeissmall);
{
// Just allocate the SeqTwoByteString in new space.
- Node* result = Allocate(size);
+ Node* result = Allocate(size, flags);
+ DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex));
StoreMapNoWriteBarrier(result, LoadRoot(Heap::kStringMapRootIndex));
StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset,
SmiFromWord(length));
@@ -1723,70 +1768,42 @@ void CodeStubAssembler::CopyStringCharacters(compiler::Node* from_string,
compiler::Node* from_index,
compiler::Node* to_index,
compiler::Node* character_count,
- String::Encoding encoding) {
- Label out(this);
-
- // Nothing to do for zero characters.
-
- GotoIf(SmiLessThanOrEqual(character_count, SmiConstant(Smi::kZero)), &out);
-
- // Calculate offsets into the strings.
-
- Node* from_offset;
- Node* limit_offset;
- Node* to_offset;
-
- {
- Node* byte_count = SmiUntag(character_count);
- Node* from_byte_index = SmiUntag(from_index);
- Node* to_byte_index = SmiUntag(to_index);
- if (encoding == String::ONE_BYTE_ENCODING) {
- const int offset = SeqOneByteString::kHeaderSize - kHeapObjectTag;
- from_offset = IntPtrAdd(IntPtrConstant(offset), from_byte_index);
- limit_offset = IntPtrAdd(from_offset, byte_count);
- to_offset = IntPtrAdd(IntPtrConstant(offset), to_byte_index);
- } else {
- STATIC_ASSERT(2 == sizeof(uc16));
- byte_count = WordShl(byte_count, 1);
- from_byte_index = WordShl(from_byte_index, 1);
- to_byte_index = WordShl(to_byte_index, 1);
-
- const int offset = SeqTwoByteString::kHeaderSize - kHeapObjectTag;
- from_offset = IntPtrAdd(IntPtrConstant(offset), from_byte_index);
- limit_offset = IntPtrAdd(from_offset, byte_count);
- to_offset = IntPtrAdd(IntPtrConstant(offset), to_byte_index);
- }
- }
-
- Variable var_from_offset(this, MachineType::PointerRepresentation());
- Variable var_to_offset(this, MachineType::PointerRepresentation());
-
- var_from_offset.Bind(from_offset);
- var_to_offset.Bind(to_offset);
-
- Variable* vars[] = {&var_from_offset, &var_to_offset};
- Label decrement(this, 2, vars);
-
- Label loop(this, 2, vars);
- Goto(&loop);
- Bind(&loop);
- {
- from_offset = var_from_offset.value();
- to_offset = var_to_offset.value();
-
- // TODO(jgruber): We could make this faster through larger copy unit sizes.
- Node* value = Load(MachineType::Uint8(), from_string, from_offset);
- StoreNoWriteBarrier(MachineRepresentation::kWord8, to_string, to_offset,
- value);
-
- Node* new_from_offset = IntPtrAdd(from_offset, IntPtrConstant(1));
- var_from_offset.Bind(new_from_offset);
- var_to_offset.Bind(IntPtrAdd(to_offset, IntPtrConstant(1)));
-
- Branch(WordNotEqual(new_from_offset, limit_offset), &loop, &out);
- }
-
- Bind(&out);
+ String::Encoding encoding,
+ ParameterMode mode) {
+ bool one_byte = encoding == String::ONE_BYTE_ENCODING;
+ Comment(one_byte ? "CopyStringCharacters ONE_BYTE_ENCODING"
+ : "CopyStringCharacters TWO_BYTE_ENCODING");
+
+ ElementsKind kind = one_byte ? UINT8_ELEMENTS : UINT16_ELEMENTS;
+ int header_size = (one_byte ? SeqOneByteString::kHeaderSize
+ : SeqTwoByteString::kHeaderSize) -
+ kHeapObjectTag;
+ Node* from_offset = ElementOffsetFromIndex(from_index, kind, mode);
+ Node* to_offset = ElementOffsetFromIndex(to_index, kind, mode);
+ Node* byte_count = ElementOffsetFromIndex(character_count, kind, mode);
+ Node* limit_offset = IntPtrAddFoldConstants(from_offset, byte_count);
+
+ // Prepare the fast loop
+ MachineType type = one_byte ? MachineType::Uint8() : MachineType::Uint16();
+ MachineRepresentation rep =
+ one_byte ? MachineRepresentation::kWord8 : MachineRepresentation::kWord16;
+ int increment = -(1 << ElementsKindToShiftSize(kind));
+
+ Node* to_string_adjusted = IntPtrAddFoldConstants(
+ to_string, IntPtrSubFoldConstants(to_offset, from_offset));
+ limit_offset =
+ IntPtrAddFoldConstants(limit_offset, IntPtrConstant(header_size));
+ from_offset =
+ IntPtrAddFoldConstants(from_offset, IntPtrConstant(header_size));
+
+ BuildFastLoop(MachineType::PointerRepresentation(), limit_offset, from_offset,
+ [from_string, to_string_adjusted, type, rep](
+ CodeStubAssembler* assembler, Node* offset) {
+ Node* value = assembler->Load(type, from_string, offset);
+ assembler->StoreNoWriteBarrier(rep, to_string_adjusted,
+ offset, value);
+ },
+ increment);
}
Node* CodeStubAssembler::LoadElementAndPrepareForStore(Node* array,
@@ -2565,7 +2582,8 @@ Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context,
Node* result =
a->AllocateSeqOneByteString(context, a->SmiToWord(character_count));
a->CopyStringCharacters(from, result, from_index, smi_zero, character_count,
- String::ONE_BYTE_ENCODING);
+ String::ONE_BYTE_ENCODING,
+ CodeStubAssembler::SMI_PARAMETERS);
var_result.Bind(result);
a->Goto(&end);
@@ -2577,7 +2595,8 @@ Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context,
Node* result =
a->AllocateSeqTwoByteString(context, a->SmiToWord(character_count));
a->CopyStringCharacters(from, result, from_index, smi_zero, character_count,
- String::TWO_BYTE_ENCODING);
+ String::TWO_BYTE_ENCODING,
+ CodeStubAssembler::SMI_PARAMETERS);
var_result.Bind(result);
a->Goto(&end);
@@ -2849,9 +2868,9 @@ Node* CodeStubAssembler::StringConcat(Node* context, Node* first,
Node* result = AllocateSeqOneByteString(context, SmiToWord(length));
CopyStringCharacters(first, result, smi_zero, smi_zero, first_length,
- String::ONE_BYTE_ENCODING);
+ String::ONE_BYTE_ENCODING, SMI_PARAMETERS);
CopyStringCharacters(second, result, smi_zero, first_length, second_length,
- String::ONE_BYTE_ENCODING);
+ String::ONE_BYTE_ENCODING, SMI_PARAMETERS);
var_result.Bind(result);
Goto(&out);
@@ -3275,6 +3294,247 @@ Node* CodeStubAssembler::ToNumber(Node* context, Node* input) {
return var_result.value();
}
+Node* CodeStubAssembler::ToString(Node* context, Node* input) {
+ Label is_number(this);
+ Label runtime(this, Label::kDeferred);
+ Variable result(this, MachineRepresentation::kTagged);
+ Label done(this, &result);
+
+ GotoIf(TaggedIsSmi(input), &is_number);
+
+ Node* input_map = LoadMap(input);
+ Node* input_instance_type = LoadMapInstanceType(input_map);
+
+ result.Bind(input);
+ GotoIf(IsStringInstanceType(input_instance_type), &done);
+
+ Label not_heap_number(this);
+ Branch(WordNotEqual(input_map, HeapNumberMapConstant()), &not_heap_number,
+ &is_number);
+
+ Bind(&is_number);
+ result.Bind(NumberToString(context, input));
+ Goto(&done);
+
+ Bind(&not_heap_number);
+ {
+ GotoIf(Word32NotEqual(input_instance_type, Int32Constant(ODDBALL_TYPE)),
+ &runtime);
+ result.Bind(LoadObjectField(input, Oddball::kToStringOffset));
+ Goto(&done);
+ }
+
+ Bind(&runtime);
+ {
+ result.Bind(CallRuntime(Runtime::kToString, context, input));
+ Goto(&done);
+ }
+
+ Bind(&done);
+ return result.value();
+}
+
+Node* CodeStubAssembler::JSReceiverToPrimitive(Node* context, Node* input) {
+ STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
+ Label if_isreceiver(this, Label::kDeferred), if_isnotreceiver(this);
+ Variable result(this, MachineRepresentation::kTagged);
+ Label done(this, &result);
+
+ GotoIf(TaggedIsSmi(input), &if_isnotreceiver);
+
+ Node* map = LoadMap(input);
+ Node* instance_type = LoadMapInstanceType(map);
+ Branch(IsJSReceiverInstanceType(instance_type), &if_isreceiver,
+ &if_isnotreceiver);
+
+ Bind(&if_isreceiver);
+ {
+ // Convert {input} to a primitive first passing Number hint.
+ Callable callable = CodeFactory::NonPrimitiveToPrimitive(isolate());
+ result.Bind(CallStub(callable, context, input));
+ Goto(&done);
+ }
+
+ Bind(&if_isnotreceiver);
+ {
+ result.Bind(input);
+ Goto(&done);
+ }
+
+ Bind(&done);
+ return result.value();
+}
+
+Node* CodeStubAssembler::NewConsString(Node* context, Node* length, Node* left,
+ Node* right, AllocationFlags flags) {
+ // Added string can be a cons string.
+ Comment("Allocating ConsString");
+ Node* left_instance_type = LoadInstanceType(left);
+ Node* right_instance_type = LoadInstanceType(right);
+
+ // Allocate the cons string object. After the allocation we decide whether the
+ // cons string is one-byte or two-byte and set the appropriate map.
+ Node* cons_string = Allocate(IntPtrConstant(ConsString::kSize), flags);
+
+ // Compute intersection and difference of instance types.
+ Node* anded_instance_types = WordAnd(left_instance_type, right_instance_type);
+ Node* xored_instance_types = WordXor(left_instance_type, right_instance_type);
+
+ // We create a one-byte cons string if
+ // 1. both strings are one-byte, or
+ // 2. at least one of the strings is two-byte, but happens to contain only
+ // one-byte characters.
+ // To do this, we check
+ // 1. if both strings are one-byte, or if the one-byte data hint is set in
+ // both strings, or
Igor Sheludko 2016/10/13 15:41:33 I wonder why does kOneByteStringTag not imply kOne
danno 2016/10/17 14:23:26 Good question, although before pulling on this str
+ // 2. if one of the strings has the one-byte data hint set and the other
+ // string is one-byte.
+ STATIC_ASSERT(kOneByteStringTag != 0);
+ STATIC_ASSERT(kOneByteDataHintMask != 0);
Igor Sheludko 2016/10/13 15:41:33 kOneByteDataHintTag != 0
danno 2016/10/17 14:23:26 Done.
+ Label one_byte_map(this);
+ Label two_byte_map(this);
+ Label map_done(this);
+ GotoIf(WordNotEqual(
+ WordAnd(anded_instance_types,
+ IntPtrConstant(kOneByteStringTag | kOneByteDataHintTag)),
+ IntPtrConstant(0)),
+ &one_byte_map);
+ Branch(WordNotEqual(
+ WordAnd(xored_instance_types,
+ IntPtrConstant(kOneByteStringTag | kOneByteDataHintMask)),
Igor Sheludko 2016/10/13 15:41:33 kOneByteStringTag -> kStringEncodingMask
danno 2016/10/17 14:23:26 Done.
+ IntPtrConstant(kOneByteStringTag | kOneByteDataHintTag)),
+ &two_byte_map, &one_byte_map);
+
+ Bind(&one_byte_map);
+ Comment("One-byte ConsString");
+ DCHECK(Heap::RootIsImmortalImmovable(Heap::kConsOneByteStringMapRootIndex));
+ StoreMapNoWriteBarrier(cons_string,
+ LoadRoot(Heap::kConsOneByteStringMapRootIndex));
jgruber 2016/10/13 14:10:16 Would it make sense to reuse Allocate{One,Two}Byte
danno 2016/10/17 14:23:26 Yes! Good catch!
+ Goto(&map_done);
+
+ Bind(&two_byte_map);
+ Comment("Two-byte ConsString");
+ DCHECK(Heap::RootIsImmortalImmovable(Heap::kConsStringMapRootIndex));
+ StoreMapNoWriteBarrier(cons_string, LoadRoot(Heap::kConsStringMapRootIndex));
+ Goto(&map_done);
+
+ Bind(&map_done);
+ StoreObjectFieldNoWriteBarrier(cons_string, String::kHashFieldOffset,
+ IntPtrConstant(String::kEmptyHashField));
+ StoreObjectFieldNoWriteBarrier(cons_string, String::kLengthOffset,
+ SmiTag(length));
+ bool const new_space = !(flags & kPretenured);
+ if (new_space) {
+ StoreObjectFieldNoWriteBarrier(cons_string, ConsString::kFirstOffset, left);
+ StoreObjectFieldNoWriteBarrier(cons_string, ConsString::kSecondOffset,
+ right);
+ } else {
+ StoreObjectField(cons_string, ConsString::kFirstOffset, left);
+ StoreObjectField(cons_string, ConsString::kSecondOffset, right);
+ }
+
+ return cons_string;
+}
+
+Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right,
jgruber 2016/10/13 14:10:16 This is basically a more complete version of Strin
danno 2016/10/17 14:23:26 I totally missed that this existed when I ported f
+ AllocationFlags flags) {
+ Label check_right(this);
+ Label runtime(this, Label::kDeferred);
+ Label cons(this);
+ Label non_cons(this);
+ Variable result(this, MachineRepresentation::kTagged);
+ Label done(this, &result);
+ Label done_native(this, &result);
+ Counters* counters = isolate()->counters();
+
+ Node* left_length = LoadStringLength(left);
+ GotoIf(WordNotEqual(IntPtrConstant(0), left_length), &check_right);
+ result.Bind(right);
+ Goto(&done_native);
+
+ Bind(&check_right);
+ Node* right_length = LoadStringLength(right);
+ GotoIf(WordNotEqual(IntPtrConstant(0), right_length), &cons);
+ result.Bind(left);
+ Goto(&done_native);
+
+ Bind(&cons);
+ Node* new_length = IntPtrAdd(SmiUntag(left_length), SmiUntag(right_length));
+ GotoIf(IntPtrLessThan(new_length, IntPtrConstant(0)), &runtime);
+ GotoIf(IntPtrGreaterThan(new_length, IntPtrConstant(String::kMaxLength)),
Igor Sheludko 2016/10/13 15:41:33 How about doing one unsigned comparison instead of
danno 2016/10/17 14:23:26 Done.
+ &runtime);
+
+ GotoIf(IntPtrLessThan(new_length, IntPtrConstant(ConsString::kMinLength)),
+ &non_cons);
+
+ result.Bind(NewConsString(context, new_length, left, right, flags));
+ Goto(&done_native);
+
+ Bind(&non_cons);
+
+ Comment("Full string concatenate");
+ Node* left_instance_type = LoadInstanceType(left);
+ Node* right_instance_type = LoadInstanceType(right);
+ // Compute intersection and difference of instance types.
+
+ Node* ored_instance_types = WordOr(left_instance_type, right_instance_type);
+ Node* xored_instance_types = WordXor(left_instance_type, right_instance_type);
+
+ // Check if both strings have the same encoding and both are sequential.
+ GotoIf(WordNotEqual(
+ WordAnd(xored_instance_types, IntPtrConstant(kStringEncodingMask)),
+ IntPtrConstant(0)),
+ &runtime);
+ GotoIf(WordNotEqual(WordAnd(ored_instance_types,
+ IntPtrConstant(kStringRepresentationMask)),
+ IntPtrConstant(0)),
+ &runtime);
+
+ Label two_byte(this);
+ GotoIf(WordEqual(
+ WordAnd(ored_instance_types, IntPtrConstant(kStringEncodingMask)),
+ IntPtrConstant(0)),
Igor Sheludko 2016/10/13 15:41:33 0 -> kTwoByteStringTag or STATIC_ASSERT
danno 2016/10/17 14:23:26 Done.
+ &two_byte);
+ // One-byte sequential string case
+ Node* new_string = AllocateSeqOneByteString(context, new_length);
+ CopyStringCharacters(left, new_string, SmiConstant(Smi::kZero),
+ SmiConstant(Smi::kZero), left_length,
+ String::ONE_BYTE_ENCODING, SMI_PARAMETERS);
+ CopyStringCharacters(right, new_string, SmiConstant(Smi::kZero), left_length,
+ right_length, String::ONE_BYTE_ENCODING, SMI_PARAMETERS);
+ result.Bind(new_string);
+ Goto(&done_native);
+
+ Bind(&two_byte);
+ {
+ // Two-byte sequential string case
+ new_string = AllocateSeqTwoByteString(context, new_length);
+ CopyStringCharacters(left, new_string, SmiConstant(Smi::kZero),
+ SmiConstant(Smi::kZero), left_length,
+ String::TWO_BYTE_ENCODING, SMI_PARAMETERS);
+ CopyStringCharacters(right, new_string, SmiConstant(Smi::kZero),
+ left_length, right_length, String::TWO_BYTE_ENCODING,
+ SMI_PARAMETERS);
+ result.Bind(new_string);
+ Goto(&done_native);
+ }
+
+ Bind(&runtime);
+ {
+ result.Bind(CallRuntime(Runtime::kStringAdd, context, left, right));
+ Goto(&done);
+ }
+
+ Bind(&done_native);
+ {
+ IncrementCounter(counters->string_add_native(), 1);
+ Goto(&done);
+ }
+
+ Bind(&done);
+ return result.value();
+}
+
Node* CodeStubAssembler::ToInteger(Node* context, Node* input,
ToIntegerTruncationMode mode) {
// We might need to loop once for ToNumber conversion.
@@ -4338,16 +4598,14 @@ compiler::Node* CodeStubAssembler::ElementOffsetFromIndex(Node* index_node,
if (Is64() && mode == INTEGER_PARAMETERS) {
index_node = ChangeInt32ToInt64(index_node);
}
- if (base_size == 0) {
- return (element_size_shift >= 0)
- ? WordShl(index_node, IntPtrConstant(element_size_shift))
- : WordShr(index_node, IntPtrConstant(-element_size_shift));
- }
- return IntPtrAdd(
- IntPtrConstant(base_size),
- (element_size_shift >= 0)
- ? WordShl(index_node, IntPtrConstant(element_size_shift))
- : WordShr(index_node, IntPtrConstant(-element_size_shift)));
+
+ Node* shifted_index =
+ (element_size_shift == 0)
+ ? index_node
+ : ((element_size_shift > 0)
+ ? WordShl(index_node, IntPtrConstant(element_size_shift))
+ : WordShr(index_node, IntPtrConstant(-element_size_shift)));
+ return IntPtrAddFoldConstants(IntPtrConstant(base_size), shifted_index);
}
compiler::Node* CodeStubAssembler::LoadTypeFeedbackVectorForStub() {

Powered by Google App Engine
This is Rietveld 408576698