[crankshaft][turbofan] Avoid calling Runtime::kTryMigrateInstance if the map is not deprecated.
BUG=chromium:680995 Change-Id: Ib567c88df357dea77cba802cbc0e567ee4097235 Reviewed-on: https://chromium-review.googlesource.com/440124 Commit-Queue: Igor Sheludko <ishell@chromium.org> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Cr-Commit-Position: refs/heads/master@{#43067}
This commit is contained in:
parent
2de26fab02
commit
f6012cbd60
@ -1102,6 +1102,17 @@ Node* EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
|
||||
// Perform the (deferred) instance migration.
|
||||
__ Bind(&migrate);
|
||||
{
|
||||
auto migration_failed = __ MakeLabel<2>();
|
||||
auto retry_check_maps = __ MakeLabel<2>();
|
||||
|
||||
// If map is not deprecated the migration attempt does not make sense.
|
||||
Node* bitfield3 =
|
||||
__ LoadField(AccessBuilder::ForMapBitField3(), value_map);
|
||||
Node* if_not_deprecated = __ WordEqual(
|
||||
__ Word32And(bitfield3, __ Int32Constant(Map::Deprecated::kMask)),
|
||||
__ Int32Constant(0));
|
||||
__ GotoIf(if_not_deprecated, &migration_failed);
|
||||
|
||||
Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
|
||||
Runtime::FunctionId id = Runtime::kTryMigrateInstance;
|
||||
CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
|
||||
@ -1111,8 +1122,15 @@ Node* EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
|
||||
__ ExternalConstant(ExternalReference(id, isolate())),
|
||||
__ Int32Constant(1), __ NoContextConstant());
|
||||
Node* check = ObjectIsSmi(result);
|
||||
__ DeoptimizeIf(DeoptimizeReason::kInstanceMigrationFailed, check,
|
||||
frame_state);
|
||||
__ GotoIf(check, &retry_check_maps);
|
||||
__ Goto(&migration_failed);
|
||||
|
||||
__ Bind(&migration_failed);
|
||||
__ DeoptimizeIf(DeoptimizeReason::kInstanceMigrationFailed,
|
||||
__ Int32Constant(1), frame_state);
|
||||
|
||||
__ Goto(&retry_check_maps);
|
||||
__ Bind(&retry_check_maps);
|
||||
}
|
||||
|
||||
// Reload the current map of the {value}.
|
||||
|
@ -4759,6 +4759,13 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) {
|
||||
|
||||
|
||||
void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
||||
Label deopt, done;
|
||||
// If the map is not deprecated the migration attempt does not make sense.
|
||||
__ ldr(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
|
||||
__ ldr(scratch0(), FieldMemOperand(scratch0(), Map::kBitField3Offset));
|
||||
__ tst(scratch0(), Operand(Map::Deprecated::kMask));
|
||||
__ b(eq, &deopt);
|
||||
|
||||
{
|
||||
PushSafepointRegistersScope scope(this);
|
||||
__ push(object);
|
||||
@ -4769,7 +4776,12 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
||||
__ StoreToSafepointRegisterSlot(r0, scratch0());
|
||||
}
|
||||
__ tst(scratch0(), Operand(kSmiTagMask));
|
||||
DeoptimizeIf(eq, instr, DeoptimizeReason::kInstanceMigrationFailed);
|
||||
__ b(ne, &done);
|
||||
|
||||
__ bind(&deopt);
|
||||
DeoptimizeIf(al, instr, DeoptimizeReason::kInstanceMigrationFailed);
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2024,6 +2024,13 @@ void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
|
||||
|
||||
void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
||||
Register temp = ToRegister(instr->temp());
|
||||
Label deopt, done;
|
||||
// If the map is not deprecated the migration attempt does not make sense.
|
||||
__ Ldr(temp, FieldMemOperand(object, HeapObject::kMapOffset));
|
||||
__ Ldr(temp, FieldMemOperand(temp, Map::kBitField3Offset));
|
||||
__ Tst(temp, Operand(Map::Deprecated::kMask));
|
||||
__ B(eq, &deopt);
|
||||
|
||||
{
|
||||
PushSafepointRegistersScope scope(this);
|
||||
__ Push(object);
|
||||
@ -2033,7 +2040,13 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
||||
instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
|
||||
__ StoreToSafepointRegisterSlot(x0, temp);
|
||||
}
|
||||
DeoptimizeIfSmi(temp, instr, DeoptimizeReason::kInstanceMigrationFailed);
|
||||
__ Tst(temp, Operand(kSmiTagMask));
|
||||
__ B(ne, &done);
|
||||
|
||||
__ bind(&deopt);
|
||||
Deoptimize(instr, DeoptimizeReason::kInstanceMigrationFailed);
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4543,6 +4543,15 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) {
|
||||
|
||||
|
||||
void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
||||
Label deopt, done;
|
||||
// If the map is not deprecated the migration attempt does not make sense.
|
||||
__ push(object);
|
||||
__ mov(object, FieldOperand(object, HeapObject::kMapOffset));
|
||||
__ test(FieldOperand(object, Map::kBitField3Offset),
|
||||
Immediate(Map::Deprecated::kMask));
|
||||
__ pop(object);
|
||||
__ j(zero, &deopt);
|
||||
|
||||
{
|
||||
PushSafepointRegistersScope scope(this);
|
||||
__ push(object);
|
||||
@ -4553,7 +4562,12 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
||||
|
||||
__ test(eax, Immediate(kSmiTagMask));
|
||||
}
|
||||
DeoptimizeIf(zero, instr, DeoptimizeReason::kInstanceMigrationFailed);
|
||||
__ j(not_zero, &done);
|
||||
|
||||
__ bind(&deopt);
|
||||
DeoptimizeIf(no_condition, instr, DeoptimizeReason::kInstanceMigrationFailed);
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4762,6 +4762,13 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) {
|
||||
|
||||
|
||||
void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
||||
Label deopt, done;
|
||||
// If the map is not deprecated the migration attempt does not make sense.
|
||||
__ lw(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
|
||||
__ lw(scratch0(), FieldMemOperand(scratch0(), Map::kBitField3Offset));
|
||||
__ And(at, scratch0(), Operand(Map::Deprecated::kMask));
|
||||
__ Branch(&deopt, eq, at, Operand(zero_reg));
|
||||
|
||||
{
|
||||
PushSafepointRegistersScope scope(this);
|
||||
__ push(object);
|
||||
@ -4772,8 +4779,15 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
||||
__ StoreToSafepointRegisterSlot(v0, scratch0());
|
||||
}
|
||||
__ SmiTst(scratch0(), at);
|
||||
DeoptimizeIf(eq, instr, DeoptimizeReason::kInstanceMigrationFailed, at,
|
||||
__ Branch(&done, ne, at, Operand(zero_reg));
|
||||
|
||||
__ bind(&deopt);
|
||||
// In case of "al" condition the operands are not used so just pass zero_reg
|
||||
// there.
|
||||
DeoptimizeIf(al, instr, DeoptimizeReason::kInstanceMigrationFailed, zero_reg,
|
||||
Operand(zero_reg));
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4967,6 +4967,13 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) {
|
||||
|
||||
|
||||
void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
||||
Label deopt, done;
|
||||
// If the map is not deprecated the migration attempt does not make sense.
|
||||
__ ld(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
|
||||
__ lwu(scratch0(), FieldMemOperand(scratch0(), Map::kBitField3Offset));
|
||||
__ And(at, scratch0(), Operand(Map::Deprecated::kMask));
|
||||
__ Branch(&deopt, eq, at, Operand(zero_reg));
|
||||
|
||||
{
|
||||
PushSafepointRegistersScope scope(this);
|
||||
__ push(object);
|
||||
@ -4977,8 +4984,15 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
||||
__ StoreToSafepointRegisterSlot(v0, scratch0());
|
||||
}
|
||||
__ SmiTst(scratch0(), at);
|
||||
DeoptimizeIf(eq, instr, DeoptimizeReason::kInstanceMigrationFailed, at,
|
||||
__ Branch(&done, ne, at, Operand(zero_reg));
|
||||
|
||||
__ bind(&deopt);
|
||||
// In case of "al" condition the operands are not used so just pass zero_reg
|
||||
// there.
|
||||
DeoptimizeIf(al, instr, DeoptimizeReason::kInstanceMigrationFailed, zero_reg,
|
||||
Operand(zero_reg));
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
|
||||
|
@ -5058,6 +5058,13 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) {
|
||||
|
||||
void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
||||
Register temp = ToRegister(instr->temp());
|
||||
Label deopt, done;
|
||||
// If the map is not deprecated the migration attempt does not make sense.
|
||||
__ LoadP(temp, FieldMemOperand(object, HeapObject::kMapOffset));
|
||||
__ lwz(temp, FieldMemOperand(temp, Map::kBitField3Offset));
|
||||
__ TestBitMask(temp, Map::Deprecated::kMask, r0);
|
||||
__ beq(&deopt, cr0);
|
||||
|
||||
{
|
||||
PushSafepointRegistersScope scope(this);
|
||||
__ push(object);
|
||||
@ -5068,7 +5075,13 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
||||
__ StoreToSafepointRegisterSlot(r3, temp);
|
||||
}
|
||||
__ TestIfSmi(temp, r0);
|
||||
DeoptimizeIf(eq, instr, DeoptimizeReason::kInstanceMigrationFailed, cr0);
|
||||
__ bne(&done, cr0);
|
||||
|
||||
__ bind(&deopt);
|
||||
// In case of "al" condition the operand is not used so just pass cr0 there.
|
||||
DeoptimizeIf(al, instr, DeoptimizeReason::kInstanceMigrationFailed, cr0);
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4987,6 +4987,13 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) {
|
||||
|
||||
void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
||||
Register temp = ToRegister(instr->temp());
|
||||
Label deopt, done;
|
||||
// If the map is not deprecated the migration attempt does not make sense.
|
||||
__ LoadP(temp, FieldMemOperand(object, HeapObject::kMapOffset));
|
||||
__ LoadlW(temp, FieldMemOperand(temp, Map::kBitField3Offset));
|
||||
__ TestBitMask(temp, Map::Deprecated::kMask, r0);
|
||||
__ beq(&deopt);
|
||||
|
||||
{
|
||||
PushSafepointRegistersScope scope(this);
|
||||
__ push(object);
|
||||
@ -4997,7 +5004,13 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
||||
__ StoreToSafepointRegisterSlot(r2, temp);
|
||||
}
|
||||
__ TestIfSmi(temp);
|
||||
DeoptimizeIf(eq, instr, DeoptimizeReason::kInstanceMigrationFailed, cr0);
|
||||
__ bne(&done);
|
||||
|
||||
__ bind(&deopt);
|
||||
// In case of "al" condition the operand is not used so just pass cr0 there.
|
||||
DeoptimizeIf(al, instr, DeoptimizeReason::kInstanceMigrationFailed, cr0);
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
|
||||
|
@ -4817,9 +4817,19 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) {
|
||||
|
||||
|
||||
void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
||||
Label deopt, done;
|
||||
// If the map is not deprecated the migration attempt does not make sense.
|
||||
__ Push(object);
|
||||
__ movp(object, FieldOperand(object, HeapObject::kMapOffset));
|
||||
__ testl(FieldOperand(object, Map::kBitField3Offset),
|
||||
Immediate(Map::Deprecated::kMask));
|
||||
__ Pop(object);
|
||||
__ j(zero, &deopt);
|
||||
|
||||
{
|
||||
PushSafepointRegistersScope scope(this);
|
||||
__ Push(object);
|
||||
|
||||
__ Set(rsi, 0);
|
||||
__ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
|
||||
RecordSafepointWithRegisters(
|
||||
@ -4827,7 +4837,12 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
||||
|
||||
__ testp(rax, Immediate(kSmiTagMask));
|
||||
}
|
||||
DeoptimizeIf(zero, instr, DeoptimizeReason::kInstanceMigrationFailed);
|
||||
__ j(not_zero, &done);
|
||||
|
||||
__ bind(&deopt);
|
||||
DeoptimizeIf(always, instr, DeoptimizeReason::kInstanceMigrationFailed);
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4946,6 +4946,15 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) {
|
||||
|
||||
|
||||
void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
||||
Label deopt, done;
|
||||
// If the map is not deprecated the migration attempt does not make sense.
|
||||
__ push(object);
|
||||
__ mov(object, FieldOperand(object, HeapObject::kMapOffset));
|
||||
__ test(FieldOperand(object, Map::kBitField3Offset),
|
||||
Immediate(Map::Deprecated::kMask));
|
||||
__ pop(object);
|
||||
__ j(zero, &deopt);
|
||||
|
||||
{
|
||||
PushSafepointRegistersScope scope(this);
|
||||
__ push(object);
|
||||
@ -4956,7 +4965,12 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
||||
|
||||
__ test(eax, Immediate(kSmiTagMask));
|
||||
}
|
||||
DeoptimizeIf(zero, instr, DeoptimizeReason::kInstanceMigrationFailed);
|
||||
__ j(not_zero, &done);
|
||||
|
||||
__ bind(&deopt);
|
||||
DeoptimizeIf(no_condition, instr, DeoptimizeReason::kInstanceMigrationFailed);
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
|
||||
|
@ -586,6 +586,7 @@ RUNTIME_FUNCTION(Runtime_TryMigrateInstance) {
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
|
||||
if (!object->IsJSObject()) return Smi::kZero;
|
||||
Handle<JSObject> js_object = Handle<JSObject>::cast(object);
|
||||
// It could have been a DCHECK but we call this function directly from tests.
|
||||
if (!js_object->map()->is_deprecated()) return Smi::kZero;
|
||||
// This call must not cause lazy deopts, because it's called from deferred
|
||||
// code where we can't handle lazy deopts for lack of a suitable bailout
|
||||
|
Loading…
Reference in New Issue
Block a user