Avoid creating weak cells for literal arrays that are empty of literals.
It may be that we have a feedback vector, but no literals. In this case we can store into the OptimizedCodeMap directly instead of using a WeakCell, because all data in the feedback vector is already held weakly. The use of a WeakCell in the OptimizedCodeMap is only required when there are literals which may hold maps strongly. This is to address a performance regression caused by the creation of a large number of WeakCells. BUG=chromium:615831 Review-Url: https://codereview.chromium.org/2031123003 Cr-Commit-Position: refs/heads/master@{#36786}
This commit is contained in:
parent
2963b5bd40
commit
3cfcc7e111
@ -1297,13 +1297,29 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||
const int bailout_id = BailoutId::None().ToInt();
|
||||
__ cmp(temp, Operand(Smi::FromInt(bailout_id)));
|
||||
__ b(ne, &loop_bottom);
|
||||
|
||||
// Literals available?
|
||||
Label got_literals, maybe_cleared_weakcell;
|
||||
__ ldr(temp, FieldMemOperand(array_pointer,
|
||||
SharedFunctionInfo::kOffsetToPreviousLiterals));
|
||||
// temp contains either a WeakCell pointing to the literals array or the
|
||||
// literals array directly.
|
||||
STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
|
||||
__ ldr(r4, FieldMemOperand(temp, WeakCell::kValueOffset));
|
||||
__ JumpIfSmi(r4, &maybe_cleared_weakcell);
|
||||
// r4 is a pointer, therefore temp is a WeakCell pointing to a literals array.
|
||||
__ ldr(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
|
||||
__ JumpIfSmi(temp, &gotta_call_runtime);
|
||||
__ jmp(&got_literals);
|
||||
|
||||
// r4 is a smi. If it's 0, then we are looking at a cleared WeakCell
|
||||
// around the literals array, and we should visit the runtime. If it's > 0,
|
||||
// then temp already contains the literals array.
|
||||
__ bind(&maybe_cleared_weakcell);
|
||||
__ cmp(r4, Operand(Smi::FromInt(0)));
|
||||
__ b(eq, &gotta_call_runtime);
|
||||
|
||||
// Save the literals in the closure.
|
||||
__ bind(&got_literals);
|
||||
__ ldr(r4, MemOperand(sp, 0));
|
||||
__ str(temp, FieldMemOperand(r4, JSFunction::kLiteralsOffset));
|
||||
__ push(index);
|
||||
|
@ -1308,13 +1308,31 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||
const int bailout_id = BailoutId::None().ToInt();
|
||||
__ Cmp(temp, Operand(Smi::FromInt(bailout_id)));
|
||||
__ B(ne, &loop_bottom);
|
||||
|
||||
// Literals available?
|
||||
Label got_literals, maybe_cleared_weakcell;
|
||||
Register temp2 = x7;
|
||||
__ Ldr(temp, FieldMemOperand(array_pointer,
|
||||
SharedFunctionInfo::kOffsetToPreviousLiterals));
|
||||
// temp contains either a WeakCell pointing to the literals array or the
|
||||
// literals array directly.
|
||||
STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
|
||||
__ Ldr(temp2, FieldMemOperand(temp, WeakCell::kValueOffset));
|
||||
__ JumpIfSmi(temp2, &maybe_cleared_weakcell);
|
||||
// temp2 is a pointer, therefore temp is a WeakCell pointing to a literals
|
||||
// array.
|
||||
__ Ldr(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
|
||||
__ JumpIfSmi(temp, &gotta_call_runtime);
|
||||
__ jmp(&got_literals);
|
||||
|
||||
// r4 is a smi. If it's 0, then we are looking at a cleared WeakCell
|
||||
// around the literals array, and we should visit the runtime. If it's > 0,
|
||||
// then temp already contains the literals array.
|
||||
__ bind(&maybe_cleared_weakcell);
|
||||
__ Cmp(temp2, Operand(Smi::FromInt(0)));
|
||||
__ B(eq, &gotta_call_runtime);
|
||||
|
||||
// Save the literals in the closure.
|
||||
__ bind(&got_literals);
|
||||
__ Str(temp, FieldMemOperand(closure, JSFunction::kLiteralsOffset));
|
||||
__ RecordWriteField(closure, JSFunction::kLiteralsOffset, temp, x7,
|
||||
kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
|
||||
|
@ -896,13 +896,30 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||
const int bailout_id = BailoutId::None().ToInt();
|
||||
__ cmp(temp, Immediate(Smi::FromInt(bailout_id)));
|
||||
__ j(not_equal, &loop_bottom);
|
||||
|
||||
// Literals available?
|
||||
Label got_literals, maybe_cleared_weakcell;
|
||||
__ mov(temp, FieldOperand(map, index, times_half_pointer_size,
|
||||
SharedFunctionInfo::kOffsetToPreviousLiterals));
|
||||
|
||||
// temp contains either a WeakCell pointing to the literals array or the
|
||||
// literals array directly.
|
||||
STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
|
||||
__ JumpIfSmi(FieldOperand(temp, WeakCell::kValueOffset),
|
||||
&maybe_cleared_weakcell);
|
||||
// The WeakCell value is a pointer, therefore it's a valid literals array.
|
||||
__ mov(temp, FieldOperand(temp, WeakCell::kValueOffset));
|
||||
__ JumpIfSmi(temp, &gotta_call_runtime);
|
||||
__ jmp(&got_literals);
|
||||
|
||||
// We have a smi. If it's 0, then we are looking at a cleared WeakCell
|
||||
// around the literals array, and we should visit the runtime. If it's > 0,
|
||||
// then temp already contains the literals array.
|
||||
__ bind(&maybe_cleared_weakcell);
|
||||
__ cmp(FieldOperand(temp, WeakCell::kValueOffset), Immediate(0));
|
||||
__ j(equal, &gotta_call_runtime);
|
||||
|
||||
// Save the literals in the closure.
|
||||
__ bind(&got_literals);
|
||||
__ mov(ecx, Operand(esp, 0));
|
||||
__ mov(FieldOperand(ecx, JSFunction::kLiteralsOffset), temp);
|
||||
__ push(index);
|
||||
|
@ -1294,13 +1294,28 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||
SharedFunctionInfo::kOffsetToPreviousOsrAstId));
|
||||
const int bailout_id = BailoutId::None().ToInt();
|
||||
__ Branch(&loop_bottom, ne, temp, Operand(Smi::FromInt(bailout_id)));
|
||||
|
||||
// Literals available?
|
||||
Label got_literals, maybe_cleared_weakcell;
|
||||
__ lw(temp, FieldMemOperand(array_pointer,
|
||||
SharedFunctionInfo::kOffsetToPreviousLiterals));
|
||||
// temp contains either a WeakCell pointing to the literals array or the
|
||||
// literals array directly.
|
||||
STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
|
||||
__ lw(t0, FieldMemOperand(temp, WeakCell::kValueOffset));
|
||||
__ JumpIfSmi(t0, &maybe_cleared_weakcell);
|
||||
// t0 is a pointer, therefore temp is a WeakCell pointing to a literals array.
|
||||
__ lw(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
|
||||
__ JumpIfSmi(temp, &gotta_call_runtime);
|
||||
__ jmp(&got_literals);
|
||||
|
||||
// t0 is a smi. If it's 0, then we are looking at a cleared WeakCell
|
||||
// around the literals array, and we should visit the runtime. If it's > 0,
|
||||
// then temp already contains the literals array.
|
||||
__ bind(&maybe_cleared_weakcell);
|
||||
__ Branch(&gotta_call_runtime, eq, t0, Operand(Smi::FromInt(0)));
|
||||
|
||||
// Save the literals in the closure.
|
||||
__ bind(&got_literals);
|
||||
__ lw(t0, MemOperand(sp, 0));
|
||||
__ sw(temp, FieldMemOperand(t0, JSFunction::kLiteralsOffset));
|
||||
__ push(index);
|
||||
|
@ -1280,13 +1280,27 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||
SharedFunctionInfo::kOffsetToPreviousOsrAstId));
|
||||
const int bailout_id = BailoutId::None().ToInt();
|
||||
__ Branch(&loop_bottom, ne, temp, Operand(Smi::FromInt(bailout_id)));
|
||||
|
||||
// Literals available?
|
||||
Label got_literals, maybe_cleared_weakcell;
|
||||
__ ld(temp, FieldMemOperand(array_pointer,
|
||||
SharedFunctionInfo::kOffsetToPreviousLiterals));
|
||||
// temp contains either a WeakCell pointing to the literals array or the
|
||||
// literals array directly.
|
||||
__ ld(a4, FieldMemOperand(temp, WeakCell::kValueOffset));
|
||||
__ JumpIfSmi(a4, &maybe_cleared_weakcell);
|
||||
// a4 is a pointer, therefore temp is a WeakCell pointing to a literals array.
|
||||
__ ld(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
|
||||
__ JumpIfSmi(temp, &gotta_call_runtime);
|
||||
__ jmp(&got_literals);
|
||||
|
||||
// a4 is a smi. If it's 0, then we are looking at a cleared WeakCell
|
||||
// around the literals array, and we should visit the runtime. If it's > 0,
|
||||
// then temp already contains the literals array.
|
||||
__ bind(&maybe_cleared_weakcell);
|
||||
__ Branch(&gotta_call_runtime, eq, a4, Operand(Smi::FromInt(0)));
|
||||
|
||||
// Save the literals in the closure.
|
||||
__ bind(&got_literals);
|
||||
__ ld(a4, MemOperand(sp, 0));
|
||||
__ sd(temp, FieldMemOperand(a4, JSFunction::kLiteralsOffset));
|
||||
__ push(index);
|
||||
|
@ -11610,9 +11610,13 @@ void SharedFunctionInfo::AddToOptimizedCodeMap(
|
||||
isolate->factory()->NewWeakCell(code.ToHandleChecked());
|
||||
old_code_map->set(entry + kCachedCodeOffset, *code_cell);
|
||||
}
|
||||
Handle<WeakCell> literals_cell =
|
||||
isolate->factory()->NewWeakCell(literals);
|
||||
old_code_map->set(entry + kLiteralsOffset, *literals_cell);
|
||||
if (literals->literals_count() == 0) {
|
||||
old_code_map->set(entry + kLiteralsOffset, *literals);
|
||||
} else {
|
||||
Handle<WeakCell> literals_cell =
|
||||
isolate->factory()->NewWeakCell(literals);
|
||||
old_code_map->set(entry + kLiteralsOffset, *literals_cell);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -11643,12 +11647,18 @@ void SharedFunctionInfo::AddToOptimizedCodeMap(
|
||||
Handle<WeakCell> code_cell =
|
||||
code.is_null() ? isolate->factory()->empty_weak_cell()
|
||||
: isolate->factory()->NewWeakCell(code.ToHandleChecked());
|
||||
Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals);
|
||||
WeakCell* context_cell = native_context->self_weak_cell();
|
||||
|
||||
new_code_map->set(entry + kContextOffset, context_cell);
|
||||
new_code_map->set(entry + kCachedCodeOffset, *code_cell);
|
||||
new_code_map->set(entry + kLiteralsOffset, *literals_cell);
|
||||
|
||||
if (literals->literals_count() == 0) {
|
||||
new_code_map->set(entry + kLiteralsOffset, *literals);
|
||||
} else {
|
||||
Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals);
|
||||
new_code_map->set(entry + kLiteralsOffset, *literals_cell);
|
||||
}
|
||||
|
||||
new_code_map->set(entry + kOsrAstIdOffset, Smi::FromInt(osr_ast_id.ToInt()));
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -11659,8 +11669,16 @@ void SharedFunctionInfo::AddToOptimizedCodeMap(
|
||||
DCHECK(cell->cleared() ||
|
||||
(cell->value()->IsCode() &&
|
||||
Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION));
|
||||
cell = WeakCell::cast(new_code_map->get(i + kLiteralsOffset));
|
||||
DCHECK(cell->cleared() || cell->value()->IsFixedArray());
|
||||
Object* lits = new_code_map->get(i + kLiteralsOffset);
|
||||
if (lits->IsWeakCell()) {
|
||||
cell = WeakCell::cast(lits);
|
||||
DCHECK(cell->cleared() ||
|
||||
(cell->value()->IsLiteralsArray() &&
|
||||
LiteralsArray::cast(cell->value())->literals_count() > 0));
|
||||
} else {
|
||||
DCHECK(lits->IsLiteralsArray() &&
|
||||
LiteralsArray::cast(lits)->literals_count() == 0);
|
||||
}
|
||||
DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi());
|
||||
}
|
||||
#endif
|
||||
@ -13278,13 +13296,18 @@ CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap(
|
||||
} else {
|
||||
DCHECK_LE(entry + kEntryLength, code_map->length());
|
||||
WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset));
|
||||
WeakCell* literals_cell =
|
||||
WeakCell::cast(code_map->get(entry + kLiteralsOffset));
|
||||
|
||||
Object* lits = code_map->get(entry + kLiteralsOffset);
|
||||
LiteralsArray* literals = nullptr;
|
||||
if (lits->IsWeakCell()) {
|
||||
WeakCell* literal_cell = WeakCell::cast(lits);
|
||||
if (!literal_cell->cleared()) {
|
||||
literals = LiteralsArray::cast(literal_cell->value());
|
||||
}
|
||||
} else {
|
||||
literals = LiteralsArray::cast(lits);
|
||||
}
|
||||
result = {cell->cleared() ? nullptr : Code::cast(cell->value()),
|
||||
literals_cell->cleared()
|
||||
? nullptr
|
||||
: LiteralsArray::cast(literals_cell->value())};
|
||||
literals};
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -284,11 +284,19 @@ void TypeFeedbackVector::ClearAllKeyedStoreICs(Isolate* isolate) {
|
||||
int length = optimized_code_map->length();
|
||||
for (int i = SharedFunctionInfo::kEntriesStart; i < length;
|
||||
i += SharedFunctionInfo::kEntryLength) {
|
||||
WeakCell* cell = WeakCell::cast(
|
||||
optimized_code_map->get(i + SharedFunctionInfo::kLiteralsOffset));
|
||||
if (cell->value()->IsLiteralsArray()) {
|
||||
TypeFeedbackVector* vector =
|
||||
LiteralsArray::cast(cell->value())->feedback_vector();
|
||||
Object* lits =
|
||||
optimized_code_map->get(i + SharedFunctionInfo::kLiteralsOffset);
|
||||
TypeFeedbackVector* vector = nullptr;
|
||||
if (lits->IsWeakCell()) {
|
||||
WeakCell* cell = WeakCell::cast(lits);
|
||||
if (cell->value()->IsLiteralsArray()) {
|
||||
vector = LiteralsArray::cast(cell->value())->feedback_vector();
|
||||
}
|
||||
} else {
|
||||
DCHECK(lits->IsLiteralsArray());
|
||||
vector = LiteralsArray::cast(lits)->feedback_vector();
|
||||
}
|
||||
if (vector != nullptr) {
|
||||
vector->ClearKeyedStoreICs(shared);
|
||||
}
|
||||
}
|
||||
|
@ -962,13 +962,30 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||
const int bailout_id = BailoutId::None().ToInt();
|
||||
__ cmpl(temp, Immediate(bailout_id));
|
||||
__ j(not_equal, &loop_bottom);
|
||||
|
||||
// Literals available?
|
||||
Label got_literals, maybe_cleared_weakcell;
|
||||
__ movp(temp, FieldOperand(map, index, times_pointer_size,
|
||||
SharedFunctionInfo::kOffsetToPreviousLiterals));
|
||||
// temp contains either a WeakCell pointing to the literals array or the
|
||||
// literals array directly.
|
||||
STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
|
||||
__ movp(r15, FieldOperand(temp, WeakCell::kValueOffset));
|
||||
__ JumpIfSmi(r15, &maybe_cleared_weakcell);
|
||||
// r15 is a pointer, therefore temp is a WeakCell pointing to a literals
|
||||
// array.
|
||||
__ movp(temp, FieldOperand(temp, WeakCell::kValueOffset));
|
||||
__ JumpIfSmi(temp, &gotta_call_runtime);
|
||||
__ jmp(&got_literals);
|
||||
|
||||
// r15 is a smi. If it's 0, then we are looking at a cleared WeakCell
|
||||
// around the literals array, and we should visit the runtime. If it's > 0,
|
||||
// then temp already contains the literals array.
|
||||
__ bind(&maybe_cleared_weakcell);
|
||||
__ cmpp(r15, Immediate(0));
|
||||
__ j(equal, &gotta_call_runtime);
|
||||
|
||||
// Save the literals in the closure.
|
||||
__ bind(&got_literals);
|
||||
__ movp(FieldOperand(closure, JSFunction::kLiteralsOffset), temp);
|
||||
__ movp(r15, index);
|
||||
__ RecordWriteField(closure, JSFunction::kLiteralsOffset, temp, r15,
|
||||
|
Loading…
Reference in New Issue
Block a user