[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:
ishell@chromium.org 2017-02-09 14:38:02 +01:00 committed by Commit Bot
parent 2de26fab02
commit f6012cbd60
11 changed files with 152 additions and 11 deletions

View File

@ -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}.

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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