Skip to content

Commit 0f94e0d

Browse files
mi-acCommit bot
authored andcommitted
Revert of [fullcodegen] Remove the hacky %_FastOneByteArrayJoin intrinsic. (patchset #1 id:1 of https://codereview.chromium.org/1708523002/ )
Reason for revert: [Sheriff] Speculative revert for adding arm flakes: https://build.chromium.org/p/client.v8/builders/V8%20Linux%20-%20arm%20-%20sim/builds/5756 https://build.chromium.org/p/client.v8/builders/V8%20Linux%20-%20arm%20-%20sim%20-%20novfp3/builds/3375/ And some more... Original issue's description: > [fullcodegen] Remove the hacky %_FastOneByteArrayJoin intrinsic. > > This intrinsic was only supported in fullcodegen, and is actually no > longer relevant for SunSpider peak performance it seems, so let's get > rid of it and maybe just implement Array.prototype.join with a fast > path at some point instead. > > R=mstarzinger@chromium.org > > Committed: https://crrev.com/ccf12b4bede3f1ce3ce14fb33bcc4041525a40af > Cr-Commit-Position: refs/heads/master@{#34084} TBR=mstarzinger@chromium.org,bmeurer@chromium.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true Review URL: https://codereview.chromium.org/1709693002 Cr-Commit-Position: refs/heads/master@{#34091}
1 parent 789ad2f commit 0f94e0d

15 files changed

Lines changed: 2040 additions & 0 deletions

src/bailout-reason.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ namespace internal {
9797
V(kImportDeclaration, "Import declaration") \
9898
V(kIndexIsNegative, "Index is negative") \
9999
V(kIndexIsTooLarge, "Index is too large") \
100+
V(kInlinedRuntimeFunctionFastOneByteArrayJoin, \
101+
"Inlined runtime function: FastOneByteArrayJoin") \
100102
V(kInliningBailedOut, "Inlining bailed out") \
101103
V(kInputGPRIsExpectedToHaveUpper32Cleared, \
102104
"Input GPR is expected to have upper32 cleared") \
@@ -127,6 +129,8 @@ namespace internal {
127129
V(kNativeFunctionLiteral, "Native function literal") \
128130
V(kNeedSmiLiteral, "Need a Smi literal here") \
129131
V(kNoCasesLeft, "No cases left") \
132+
V(kNoEmptyArraysHereInEmitFastOneByteArrayJoin, \
133+
"No empty arrays here in EmitFastOneByteArrayJoin") \
130134
V(kNonInitializerAssignmentToConst, "Non-initializer assignment to const") \
131135
V(kNonSmiIndex, "Non-smi index") \
132136
V(kNonSmiKeyInArrayLiteral, "Non-smi key in array literal") \

src/crankshaft/hydrogen.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12900,6 +12900,16 @@ void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
1290012900
}
1290112901

1290212902

12903+
void HOptimizedGraphBuilder::GenerateFastOneByteArrayJoin(CallRuntime* call) {
12904+
// Simply returning undefined here would be semantically correct and even
12905+
// avoid the bailout. Nevertheless, some ancient benchmarks like SunSpider's
12906+
// string-fasta would tank, because fullcode contains an optimized version.
12907+
// Obviously the fullcode => Crankshaft => bailout => fullcode dance is
12908+
// faster... *sigh*
12909+
return Bailout(kInlinedRuntimeFunctionFastOneByteArrayJoin);
12910+
}
12911+
12912+
1290312913
void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode(
1290412914
CallRuntime* call) {
1290512915
Add<HDebugBreak>();

src/crankshaft/hydrogen.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2213,6 +2213,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
22132213
F(MathPow) \
22142214
F(HasCachedArrayIndex) \
22152215
F(GetCachedArrayIndex) \
2216+
F(FastOneByteArrayJoin) \
22162217
F(DebugBreakInOptimizedCode) \
22172218
F(StringCharCodeAt) \
22182219
F(SubString) \

src/full-codegen/arm/full-codegen-arm.cc

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3414,6 +3414,243 @@ void FullCodeGenerator::EmitGetSuperConstructor(CallRuntime* expr) {
34143414
}
34153415

34163416

3417+
void FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) {
3418+
Label bailout, done, one_char_separator, long_separator, non_trivial_array,
3419+
not_size_one_array, loop, empty_separator_loop, one_char_separator_loop,
3420+
one_char_separator_loop_entry, long_separator_loop;
3421+
ZoneList<Expression*>* args = expr->arguments();
3422+
DCHECK(args->length() == 2);
3423+
VisitForStackValue(args->at(1));
3424+
VisitForAccumulatorValue(args->at(0));
3425+
3426+
// All aliases of the same register have disjoint lifetimes.
3427+
Register array = r0;
3428+
Register elements = no_reg; // Will be r0.
3429+
Register result = no_reg; // Will be r0.
3430+
Register separator = r1;
3431+
Register array_length = r2;
3432+
Register result_pos = no_reg; // Will be r2
3433+
Register string_length = r3;
3434+
Register string = r4;
3435+
Register element = r5;
3436+
Register elements_end = r6;
3437+
Register scratch = r9;
3438+
3439+
// Separator operand is on the stack.
3440+
__ pop(separator);
3441+
3442+
// Check that the array is a JSArray.
3443+
__ JumpIfSmi(array, &bailout);
3444+
__ CompareObjectType(array, scratch, array_length, JS_ARRAY_TYPE);
3445+
__ b(ne, &bailout);
3446+
3447+
// Check that the array has fast elements.
3448+
__ CheckFastElements(scratch, array_length, &bailout);
3449+
3450+
// If the array has length zero, return the empty string.
3451+
__ ldr(array_length, FieldMemOperand(array, JSArray::kLengthOffset));
3452+
__ SmiUntag(array_length, SetCC);
3453+
__ b(ne, &non_trivial_array);
3454+
__ LoadRoot(r0, Heap::kempty_stringRootIndex);
3455+
__ b(&done);
3456+
3457+
__ bind(&non_trivial_array);
3458+
3459+
// Get the FixedArray containing array's elements.
3460+
elements = array;
3461+
__ ldr(elements, FieldMemOperand(array, JSArray::kElementsOffset));
3462+
array = no_reg; // End of array's live range.
3463+
3464+
// Check that all array elements are sequential one-byte strings, and
3465+
// accumulate the sum of their lengths, as a smi-encoded value.
3466+
__ mov(string_length, Operand::Zero());
3467+
__ add(element,
3468+
elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3469+
__ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2));
3470+
// Loop condition: while (element < elements_end).
3471+
// Live values in registers:
3472+
// elements: Fixed array of strings.
3473+
// array_length: Length of the fixed array of strings (not smi)
3474+
// separator: Separator string
3475+
// string_length: Accumulated sum of string lengths (smi).
3476+
// element: Current array element.
3477+
// elements_end: Array end.
3478+
if (generate_debug_code_) {
3479+
__ cmp(array_length, Operand::Zero());
3480+
__ Assert(gt, kNoEmptyArraysHereInEmitFastOneByteArrayJoin);
3481+
}
3482+
__ bind(&loop);
3483+
__ ldr(string, MemOperand(element, kPointerSize, PostIndex));
3484+
__ JumpIfSmi(string, &bailout);
3485+
__ ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset));
3486+
__ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
3487+
__ JumpIfInstanceTypeIsNotSequentialOneByte(scratch, scratch, &bailout);
3488+
__ ldr(scratch, FieldMemOperand(string, SeqOneByteString::kLengthOffset));
3489+
__ add(string_length, string_length, Operand(scratch), SetCC);
3490+
__ b(vs, &bailout);
3491+
__ cmp(element, elements_end);
3492+
__ b(lt, &loop);
3493+
3494+
// If array_length is 1, return elements[0], a string.
3495+
__ cmp(array_length, Operand(1));
3496+
__ b(ne, &not_size_one_array);
3497+
__ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize));
3498+
__ b(&done);
3499+
3500+
__ bind(&not_size_one_array);
3501+
3502+
// Live values in registers:
3503+
// separator: Separator string
3504+
// array_length: Length of the array.
3505+
// string_length: Sum of string lengths (smi).
3506+
// elements: FixedArray of strings.
3507+
3508+
// Check that the separator is a flat one-byte string.
3509+
__ JumpIfSmi(separator, &bailout);
3510+
__ ldr(scratch, FieldMemOperand(separator, HeapObject::kMapOffset));
3511+
__ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
3512+
__ JumpIfInstanceTypeIsNotSequentialOneByte(scratch, scratch, &bailout);
3513+
3514+
// Add (separator length times array_length) - separator length to the
3515+
// string_length to get the length of the result string. array_length is not
3516+
// smi but the other values are, so the result is a smi
3517+
__ ldr(scratch, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
3518+
__ sub(string_length, string_length, Operand(scratch));
3519+
__ smull(scratch, ip, array_length, scratch);
3520+
// Check for smi overflow. No overflow if higher 33 bits of 64-bit result are
3521+
// zero.
3522+
__ cmp(ip, Operand::Zero());
3523+
__ b(ne, &bailout);
3524+
__ tst(scratch, Operand(0x80000000));
3525+
__ b(ne, &bailout);
3526+
__ add(string_length, string_length, Operand(scratch), SetCC);
3527+
__ b(vs, &bailout);
3528+
__ SmiUntag(string_length);
3529+
3530+
// Bailout for large object allocations.
3531+
__ cmp(string_length, Operand(Page::kMaxRegularHeapObjectSize));
3532+
__ b(gt, &bailout);
3533+
3534+
// Get first element in the array to free up the elements register to be used
3535+
// for the result.
3536+
__ add(element,
3537+
elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3538+
result = elements; // End of live range for elements.
3539+
elements = no_reg;
3540+
// Live values in registers:
3541+
// element: First array element
3542+
// separator: Separator string
3543+
// string_length: Length of result string (not smi)
3544+
// array_length: Length of the array.
3545+
__ AllocateOneByteString(result, string_length, scratch,
3546+
string, // used as scratch
3547+
elements_end, // used as scratch
3548+
&bailout);
3549+
// Prepare for looping. Set up elements_end to end of the array. Set
3550+
// result_pos to the position of the result where to write the first
3551+
// character.
3552+
__ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2));
3553+
result_pos = array_length; // End of live range for array_length.
3554+
array_length = no_reg;
3555+
__ add(result_pos,
3556+
result,
3557+
Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3558+
3559+
// Check the length of the separator.
3560+
__ ldr(scratch, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
3561+
__ cmp(scratch, Operand(Smi::FromInt(1)));
3562+
__ b(eq, &one_char_separator);
3563+
__ b(gt, &long_separator);
3564+
3565+
// Empty separator case
3566+
__ bind(&empty_separator_loop);
3567+
// Live values in registers:
3568+
// result_pos: the position to which we are currently copying characters.
3569+
// element: Current array element.
3570+
// elements_end: Array end.
3571+
3572+
// Copy next array element to the result.
3573+
__ ldr(string, MemOperand(element, kPointerSize, PostIndex));
3574+
__ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
3575+
__ SmiUntag(string_length);
3576+
__ add(string,
3577+
string,
3578+
Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3579+
__ CopyBytes(string, result_pos, string_length, scratch);
3580+
__ cmp(element, elements_end);
3581+
__ b(lt, &empty_separator_loop); // End while (element < elements_end).
3582+
DCHECK(result.is(r0));
3583+
__ b(&done);
3584+
3585+
// One-character separator case
3586+
__ bind(&one_char_separator);
3587+
// Replace separator with its one-byte character value.
3588+
__ ldrb(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize));
3589+
// Jump into the loop after the code that copies the separator, so the first
3590+
// element is not preceded by a separator
3591+
__ jmp(&one_char_separator_loop_entry);
3592+
3593+
__ bind(&one_char_separator_loop);
3594+
// Live values in registers:
3595+
// result_pos: the position to which we are currently copying characters.
3596+
// element: Current array element.
3597+
// elements_end: Array end.
3598+
// separator: Single separator one-byte char (in lower byte).
3599+
3600+
// Copy the separator character to the result.
3601+
__ strb(separator, MemOperand(result_pos, 1, PostIndex));
3602+
3603+
// Copy next array element to the result.
3604+
__ bind(&one_char_separator_loop_entry);
3605+
__ ldr(string, MemOperand(element, kPointerSize, PostIndex));
3606+
__ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
3607+
__ SmiUntag(string_length);
3608+
__ add(string,
3609+
string,
3610+
Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3611+
__ CopyBytes(string, result_pos, string_length, scratch);
3612+
__ cmp(element, elements_end);
3613+
__ b(lt, &one_char_separator_loop); // End while (element < elements_end).
3614+
DCHECK(result.is(r0));
3615+
__ b(&done);
3616+
3617+
// Long separator case (separator is more than one character). Entry is at the
3618+
// label long_separator below.
3619+
__ bind(&long_separator_loop);
3620+
// Live values in registers:
3621+
// result_pos: the position to which we are currently copying characters.
3622+
// element: Current array element.
3623+
// elements_end: Array end.
3624+
// separator: Separator string.
3625+
3626+
// Copy the separator to the result.
3627+
__ ldr(string_length, FieldMemOperand(separator, String::kLengthOffset));
3628+
__ SmiUntag(string_length);
3629+
__ add(string,
3630+
separator,
3631+
Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3632+
__ CopyBytes(string, result_pos, string_length, scratch);
3633+
3634+
__ bind(&long_separator);
3635+
__ ldr(string, MemOperand(element, kPointerSize, PostIndex));
3636+
__ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
3637+
__ SmiUntag(string_length);
3638+
__ add(string,
3639+
string,
3640+
Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3641+
__ CopyBytes(string, result_pos, string_length, scratch);
3642+
__ cmp(element, elements_end);
3643+
__ b(lt, &long_separator_loop); // End while (element < elements_end).
3644+
DCHECK(result.is(r0));
3645+
__ b(&done);
3646+
3647+
__ bind(&bailout);
3648+
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
3649+
__ bind(&done);
3650+
context()->Plug(r0);
3651+
}
3652+
3653+
34173654
void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
34183655
DCHECK(expr->arguments()->length() == 0);
34193656
ExternalReference debug_is_active =

0 commit comments

Comments
 (0)