Skip to content

Commit b8294aa

Browse files
ripsawridgeCommit bot
authored andcommitted
[TypeFeedbackVector] Root literal arrays in function literals slots
Literal arrays and feedback vectors for a function can be garbage collected if we don't have a rooted closure for the function, which happens often. It's expensive to come back from this (recreating boilerplates and gathering feedback again), and the cost is disproportionate if the function was inlined into optimized code. To guard against losing these arrays when we need them, we'll now create literal arrays when creating the feedback vector for the outer closure, and root them strongly in that vector. BUG=v8:5456 Review-Url: https://codereview.chromium.org/2620753003 Cr-Original-Commit-Position: refs/heads/master@{#42258} Committed: https://chromium.googlesource.com/v8/v8/+/31887804107bf5c103d915f5c601cfaaf1cd7cb6 Review-Url: https://codereview.chromium.org/2620753003 Cr-Commit-Position: refs/heads/master@{#42264}
1 parent 2bca056 commit b8294aa

25 files changed

Lines changed: 327 additions & 525 deletions

src/builtins/arm/builtins-arm.cc

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,20 +1337,26 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
13371337
Register argument_count = r0;
13381338
Register closure = r1;
13391339
Register new_target = r3;
1340+
Register map = argument_count;
1341+
Register index = r2;
1342+
1343+
// Do we have a valid feedback vector?
1344+
__ ldr(index, FieldMemOperand(closure, JSFunction::kLiteralsOffset));
1345+
__ ldr(index, FieldMemOperand(index, LiteralsArray::kFeedbackVectorOffset));
1346+
__ JumpIfRoot(index, Heap::kUndefinedValueRootIndex,
1347+
&gotta_call_runtime_no_stack);
1348+
13401349
__ push(argument_count);
13411350
__ push(new_target);
13421351
__ push(closure);
13431352

1344-
Register map = argument_count;
1345-
Register index = r2;
13461353
__ ldr(map, FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
13471354
__ ldr(map,
13481355
FieldMemOperand(map, SharedFunctionInfo::kOptimizedCodeMapOffset));
13491356
__ ldr(index, FieldMemOperand(map, FixedArray::kLengthOffset));
13501357
__ cmp(index, Operand(Smi::FromInt(2)));
13511358
__ b(lt, &gotta_call_runtime);
13521359

1353-
// Find literals.
13541360
// r3 : native context
13551361
// r2 : length / index
13561362
// r0 : optimized code map
@@ -1370,20 +1376,6 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
13701376
__ ldr(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
13711377
__ cmp(temp, native_context);
13721378
__ b(ne, &loop_bottom);
1373-
// Literals available?
1374-
__ ldr(temp, FieldMemOperand(array_pointer,
1375-
SharedFunctionInfo::kOffsetToPreviousLiterals));
1376-
__ ldr(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
1377-
__ JumpIfSmi(temp, &gotta_call_runtime);
1378-
1379-
// Save the literals in the closure.
1380-
__ ldr(r4, MemOperand(sp, 0));
1381-
__ str(temp, FieldMemOperand(r4, JSFunction::kLiteralsOffset));
1382-
__ push(index);
1383-
__ RecordWriteField(r4, JSFunction::kLiteralsOffset, temp, index,
1384-
kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
1385-
OMIT_SMI_CHECK);
1386-
__ pop(index);
13871379

13881380
// Code available?
13891381
Register entry = r4;
@@ -1393,7 +1385,7 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
13931385
__ ldr(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
13941386
__ JumpIfSmi(entry, &try_shared);
13951387

1396-
// Found literals and code. Get them into the closure and return.
1388+
// Found code. Get it into the closure and return.
13971389
__ pop(closure);
13981390
// Store code entry in the closure.
13991391
__ add(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
@@ -1428,7 +1420,7 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
14281420
__ cmp(index, Operand(Smi::FromInt(1)));
14291421
__ b(gt, &loop_top);
14301422

1431-
// We found neither literals nor code.
1423+
// We found no code.
14321424
__ jmp(&gotta_call_runtime);
14331425

14341426
__ bind(&try_shared);

src/builtins/arm64/builtins-arm64.cc

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,14 +1347,19 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
13471347
Register closure = x1;
13481348
Register map = x13;
13491349
Register index = x2;
1350+
1351+
// Do we have a valid feedback vector?
1352+
__ Ldr(index, FieldMemOperand(closure, JSFunction::kLiteralsOffset));
1353+
__ Ldr(index, FieldMemOperand(index, LiteralsArray::kFeedbackVectorOffset));
1354+
__ JumpIfRoot(index, Heap::kUndefinedValueRootIndex, &gotta_call_runtime);
1355+
13501356
__ Ldr(map, FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
13511357
__ Ldr(map,
13521358
FieldMemOperand(map, SharedFunctionInfo::kOptimizedCodeMapOffset));
13531359
__ Ldrsw(index, UntagSmiFieldMemOperand(map, FixedArray::kLengthOffset));
13541360
__ Cmp(index, Operand(2));
13551361
__ B(lt, &gotta_call_runtime);
13561362

1357-
// Find literals.
13581363
// x3 : native context
13591364
// x2 : length / index
13601365
// x13 : optimized code map
@@ -1374,17 +1379,6 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
13741379
__ Ldr(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
13751380
__ Cmp(temp, native_context);
13761381
__ B(ne, &loop_bottom);
1377-
// Literals available?
1378-
__ Ldr(temp, FieldMemOperand(array_pointer,
1379-
SharedFunctionInfo::kOffsetToPreviousLiterals));
1380-
__ Ldr(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
1381-
__ JumpIfSmi(temp, &gotta_call_runtime);
1382-
1383-
// Save the literals in the closure.
1384-
__ Str(temp, FieldMemOperand(closure, JSFunction::kLiteralsOffset));
1385-
__ RecordWriteField(closure, JSFunction::kLiteralsOffset, temp, x7,
1386-
kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
1387-
OMIT_SMI_CHECK);
13881382

13891383
// Code available?
13901384
Register entry = x7;
@@ -1394,7 +1388,7 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
13941388
__ Ldr(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
13951389
__ JumpIfSmi(entry, &try_shared);
13961390

1397-
// Found literals and code. Get them into the closure and return.
1391+
// Found code. Get it into the closure and return.
13981392
__ Add(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
13991393
__ Str(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
14001394
__ RecordWriteCodeEntryField(closure, entry, x5);
@@ -1423,7 +1417,7 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
14231417
__ Cmp(index, Operand(1));
14241418
__ B(gt, &loop_top);
14251419

1426-
// We found neither literals nor code.
1420+
// We found no code.
14271421
__ B(&gotta_call_runtime);
14281422

14291423
__ Bind(&try_shared);

src/builtins/builtins-constructor.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,14 @@ Node* ConstructorBuiltinsAssembler::EmitFastNewClosure(Node* shared_info,
120120

121121
// Initialize the rest of the function.
122122
Node* empty_fixed_array = HeapConstant(factory->empty_fixed_array());
123-
Node* empty_literals_array = HeapConstant(factory->empty_literals_array());
124123
StoreObjectFieldNoWriteBarrier(result, JSObject::kPropertiesOffset,
125124
empty_fixed_array);
126125
StoreObjectFieldNoWriteBarrier(result, JSObject::kElementsOffset,
127126
empty_fixed_array);
127+
Node* literals_array = LoadFixedArrayElement(
128+
feedback_vector, slot, 0, CodeStubAssembler::SMI_PARAMETERS);
128129
StoreObjectFieldNoWriteBarrier(result, JSFunction::kLiteralsOffset,
129-
empty_literals_array);
130+
literals_array);
130131
StoreObjectFieldNoWriteBarrier(
131132
result, JSFunction::kPrototypeOrInitialMapOffset, TheHoleConstant());
132133
StoreObjectFieldNoWriteBarrier(result, JSFunction::kSharedFunctionInfoOffset,

src/builtins/ia32/builtins-ia32.cc

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,12 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
10251025
Register new_target = edx;
10261026
Register argument_count = eax;
10271027

1028+
// Do we have a valid feedback vector?
1029+
__ mov(ebx, FieldOperand(closure, JSFunction::kLiteralsOffset));
1030+
__ mov(ebx, FieldOperand(ebx, LiteralsArray::kFeedbackVectorOffset));
1031+
__ cmp(ebx, masm->isolate()->factory()->undefined_value());
1032+
__ j(equal, &gotta_call_runtime_no_stack);
1033+
10281034
__ push(argument_count);
10291035
__ push(new_target);
10301036
__ push(closure);
@@ -1037,7 +1043,6 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
10371043
__ cmp(index, Immediate(Smi::FromInt(2)));
10381044
__ j(less, &gotta_call_runtime);
10391045

1040-
// Find literals.
10411046
// edx : native context
10421047
// ebx : length / index
10431048
// eax : optimized code map
@@ -1055,28 +1060,14 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
10551060
__ mov(temp, FieldOperand(temp, WeakCell::kValueOffset));
10561061
__ cmp(temp, native_context);
10571062
__ j(not_equal, &loop_bottom);
1058-
// Literals available?
1059-
__ mov(temp, FieldOperand(map, index, times_half_pointer_size,
1060-
SharedFunctionInfo::kOffsetToPreviousLiterals));
1061-
__ mov(temp, FieldOperand(temp, WeakCell::kValueOffset));
1062-
__ JumpIfSmi(temp, &gotta_call_runtime);
1063-
1064-
// Save the literals in the closure.
1065-
__ mov(ecx, Operand(esp, 0));
1066-
__ mov(FieldOperand(ecx, JSFunction::kLiteralsOffset), temp);
1067-
__ push(index);
1068-
__ RecordWriteField(ecx, JSFunction::kLiteralsOffset, temp, index,
1069-
kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
1070-
__ pop(index);
1071-
10721063
// Code available?
10731064
Register entry = ecx;
10741065
__ mov(entry, FieldOperand(map, index, times_half_pointer_size,
10751066
SharedFunctionInfo::kOffsetToPreviousCachedCode));
10761067
__ mov(entry, FieldOperand(entry, WeakCell::kValueOffset));
10771068
__ JumpIfSmi(entry, &try_shared);
10781069

1079-
// Found literals and code. Get them into the closure and return.
1070+
// Found code. Get it into the closure and return.
10801071
__ pop(closure);
10811072
// Store code entry in the closure.
10821073
__ lea(entry, FieldOperand(entry, Code::kHeaderSize));
@@ -1110,7 +1101,7 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
11101101
__ cmp(index, Immediate(Smi::FromInt(1)));
11111102
__ j(greater, &loop_top);
11121103

1113-
// We found neither literals nor code.
1104+
// We found no code.
11141105
__ jmp(&gotta_call_runtime);
11151106

11161107
__ bind(&try_shared);

src/builtins/mips/builtins-mips.cc

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,18 +1349,24 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
13491349
Register argument_count = a0;
13501350
Register closure = a1;
13511351
Register new_target = a3;
1352+
Register map = a0;
1353+
Register index = a2;
1354+
1355+
// Do we have a valid feedback vector?
1356+
__ lw(index, FieldMemOperand(closure, JSFunction::kLiteralsOffset));
1357+
__ lw(index, FieldMemOperand(index, LiteralsArray::kFeedbackVectorOffset));
1358+
__ JumpIfRoot(index, Heap::kUndefinedValueRootIndex,
1359+
&gotta_call_runtime_no_stack);
1360+
13521361
__ push(argument_count);
13531362
__ push(new_target);
13541363
__ push(closure);
13551364

1356-
Register map = a0;
1357-
Register index = a2;
13581365
__ lw(map, FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
13591366
__ lw(map, FieldMemOperand(map, SharedFunctionInfo::kOptimizedCodeMapOffset));
13601367
__ lw(index, FieldMemOperand(map, FixedArray::kLengthOffset));
13611368
__ Branch(&gotta_call_runtime, lt, index, Operand(Smi::FromInt(2)));
13621369

1363-
// Find literals.
13641370
// a3 : native context
13651371
// a2 : length / index
13661372
// a0 : optimized code map
@@ -1380,20 +1386,6 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
13801386
SharedFunctionInfo::kOffsetToPreviousContext));
13811387
__ lw(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
13821388
__ Branch(&loop_bottom, ne, temp, Operand(native_context));
1383-
// Literals available?
1384-
__ lw(temp, FieldMemOperand(array_pointer,
1385-
SharedFunctionInfo::kOffsetToPreviousLiterals));
1386-
__ lw(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
1387-
__ JumpIfSmi(temp, &gotta_call_runtime);
1388-
1389-
// Save the literals in the closure.
1390-
__ lw(t0, MemOperand(sp, 0));
1391-
__ sw(temp, FieldMemOperand(t0, JSFunction::kLiteralsOffset));
1392-
__ push(index);
1393-
__ RecordWriteField(t0, JSFunction::kLiteralsOffset, temp, index,
1394-
kRAHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
1395-
OMIT_SMI_CHECK);
1396-
__ pop(index);
13971389

13981390
// Code available?
13991391
Register entry = t0;
@@ -1403,7 +1395,7 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
14031395
__ lw(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
14041396
__ JumpIfSmi(entry, &try_shared);
14051397

1406-
// Found literals and code. Get them into the closure and return.
1398+
// Found code. Get it into the closure and return.
14071399
__ pop(closure);
14081400
// Store code entry in the closure.
14091401
__ Addu(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
@@ -1438,7 +1430,7 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
14381430
Operand(Smi::FromInt(SharedFunctionInfo::kEntryLength)));
14391431
__ Branch(&loop_top, gt, index, Operand(Smi::FromInt(1)));
14401432

1441-
// We found neither literals nor code.
1433+
// We found no code.
14421434
__ jmp(&gotta_call_runtime);
14431435

14441436
__ bind(&try_shared);

src/builtins/mips64/builtins-mips64.cc

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,18 +1340,24 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
13401340
Register argument_count = a0;
13411341
Register closure = a1;
13421342
Register new_target = a3;
1343+
Register map = a0;
1344+
Register index = a2;
1345+
1346+
// Do we have a valid feedback vector?
1347+
__ ld(index, FieldMemOperand(closure, JSFunction::kLiteralsOffset));
1348+
__ ld(index, FieldMemOperand(index, LiteralsArray::kFeedbackVectorOffset));
1349+
__ JumpIfRoot(index, Heap::kUndefinedValueRootIndex,
1350+
&gotta_call_runtime_no_stack);
1351+
13431352
__ push(argument_count);
13441353
__ push(new_target);
13451354
__ push(closure);
13461355

1347-
Register map = a0;
1348-
Register index = a2;
13491356
__ ld(map, FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
13501357
__ ld(map, FieldMemOperand(map, SharedFunctionInfo::kOptimizedCodeMapOffset));
13511358
__ ld(index, FieldMemOperand(map, FixedArray::kLengthOffset));
13521359
__ Branch(&gotta_call_runtime, lt, index, Operand(Smi::FromInt(2)));
13531360

1354-
// Find literals.
13551361
// a3 : native context
13561362
// a2 : length / index
13571363
// a0 : optimized code map
@@ -1371,20 +1377,6 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
13711377
SharedFunctionInfo::kOffsetToPreviousContext));
13721378
__ ld(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
13731379
__ Branch(&loop_bottom, ne, temp, Operand(native_context));
1374-
// Literals available?
1375-
__ ld(temp, FieldMemOperand(array_pointer,
1376-
SharedFunctionInfo::kOffsetToPreviousLiterals));
1377-
__ ld(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
1378-
__ JumpIfSmi(temp, &gotta_call_runtime);
1379-
1380-
// Save the literals in the closure.
1381-
__ ld(a4, MemOperand(sp, 0));
1382-
__ sd(temp, FieldMemOperand(a4, JSFunction::kLiteralsOffset));
1383-
__ push(index);
1384-
__ RecordWriteField(a4, JSFunction::kLiteralsOffset, temp, index,
1385-
kRAHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
1386-
OMIT_SMI_CHECK);
1387-
__ pop(index);
13881380

13891381
// Code available?
13901382
Register entry = a4;
@@ -1394,7 +1386,7 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
13941386
__ ld(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
13951387
__ JumpIfSmi(entry, &try_shared);
13961388

1397-
// Found literals and code. Get them into the closure and return.
1389+
// Found code. Get it into the closure and return.
13981390
__ pop(closure);
13991391
// Store code entry in the closure.
14001392
__ Daddu(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
@@ -1429,7 +1421,7 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
14291421
Operand(Smi::FromInt(SharedFunctionInfo::kEntryLength)));
14301422
__ Branch(&loop_top, gt, index, Operand(Smi::FromInt(1)));
14311423

1432-
// We found neither literals nor code.
1424+
// We found no code.
14331425
__ jmp(&gotta_call_runtime);
14341426

14351427
__ bind(&try_shared);

src/builtins/x64/builtins-x64.cc

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -994,13 +994,18 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
994994
Register closure = rdi;
995995
Register map = r8;
996996
Register index = r9;
997+
998+
// Do we have a valid feedback vector?
999+
__ movp(rbx, FieldOperand(closure, JSFunction::kLiteralsOffset));
1000+
__ movp(rbx, FieldOperand(rbx, LiteralsArray::kFeedbackVectorOffset));
1001+
__ JumpIfRoot(rbx, Heap::kUndefinedValueRootIndex, &gotta_call_runtime);
1002+
9971003
__ movp(map, FieldOperand(closure, JSFunction::kSharedFunctionInfoOffset));
9981004
__ movp(map, FieldOperand(map, SharedFunctionInfo::kOptimizedCodeMapOffset));
9991005
__ SmiToInteger32(index, FieldOperand(map, FixedArray::kLengthOffset));
10001006
__ cmpl(index, Immediate(2));
10011007
__ j(less, &gotta_call_runtime);
10021008

1003-
// Find literals.
10041009
// r14 : native context
10051010
// r9 : length / index
10061011
// r8 : optimized code map
@@ -1017,17 +1022,6 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
10171022
__ movp(temp, FieldOperand(temp, WeakCell::kValueOffset));
10181023
__ cmpp(temp, native_context);
10191024
__ j(not_equal, &loop_bottom);
1020-
// Literals available?
1021-
__ movp(temp, FieldOperand(map, index, times_pointer_size,
1022-
SharedFunctionInfo::kOffsetToPreviousLiterals));
1023-
__ movp(temp, FieldOperand(temp, WeakCell::kValueOffset));
1024-
__ JumpIfSmi(temp, &gotta_call_runtime);
1025-
1026-
// Save the literals in the closure.
1027-
__ movp(FieldOperand(closure, JSFunction::kLiteralsOffset), temp);
1028-
__ movp(r15, index);
1029-
__ RecordWriteField(closure, JSFunction::kLiteralsOffset, temp, r15,
1030-
kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
10311025

10321026
// Code available?
10331027
Register entry = rcx;
@@ -1036,7 +1030,7 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
10361030
__ movp(entry, FieldOperand(entry, WeakCell::kValueOffset));
10371031
__ JumpIfSmi(entry, &try_shared);
10381032

1039-
// Found literals and code. Get them into the closure and return.
1033+
// Found code. Get it into the closure and return.
10401034
__ leap(entry, FieldOperand(entry, Code::kHeaderSize));
10411035
__ movp(FieldOperand(closure, JSFunction::kCodeEntryOffset), entry);
10421036
__ RecordWriteCodeEntryField(closure, entry, r15);
@@ -1067,7 +1061,7 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
10671061
__ cmpl(index, Immediate(1));
10681062
__ j(greater, &loop_top);
10691063

1070-
// We found neither literals nor code.
1064+
// We found no code.
10711065
__ jmp(&gotta_call_runtime);
10721066

10731067
__ bind(&try_shared);

0 commit comments

Comments
 (0)