diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index 3d490ab233..8f3423ecd7 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -5193,31 +5193,63 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) { } -void LCodeGen::DoCheckMapCommon(Register map_reg, - Handle map, - LEnvironment* env) { - Label success; - __ CompareMapAndBranch(map_reg, map, &success, eq, &success); - DeoptimizeIf(al, env); - __ bind(&success); +void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { + { + PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); + __ push(object); + CallRuntimeFromDeferred(Runtime::kMigrateInstance, 1, instr); + __ StoreToSafepointRegisterSlot(v0, scratch0()); + } + __ And(at, scratch0(), Operand(kSmiTagMask)); + DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); } void LCodeGen::DoCheckMaps(LCheckMaps* instr) { + class DeferredCheckMaps: public LDeferredCode { + public: + DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) + : LDeferredCode(codegen), instr_(instr), object_(object) { + SetExit(check_maps()); + } + virtual void Generate() { + codegen()->DoDeferredInstanceMigration(instr_, object_); + } + Label* check_maps() { return &check_maps_; } + virtual LInstruction* instr() { return instr_; } + private: + LCheckMaps* instr_; + Label check_maps_; + Register object_; + }; + if (instr->hydrogen()->CanOmitMapChecks()) return; Register map_reg = scratch0(); LOperand* input = instr->value(); ASSERT(input->IsRegister()); Register reg = ToRegister(input); - Label success; SmallMapList* map_set = instr->hydrogen()->map_set(); __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); + + DeferredCheckMaps* deferred = NULL; + if (instr->hydrogen()->has_migration_target()) { + deferred = new(zone()) DeferredCheckMaps(this, instr, reg); + __ bind(deferred->check_maps()); + } + + Label success; for (int i = 0; i < map_set->length() - 1; i++) { Handle map = map_set->at(i); __ CompareMapAndBranch(map_reg, map, &success, eq, &success); } Handle map = map_set->last(); - DoCheckMapCommon(map_reg, map, instr->environment()); + __ CompareMapAndBranch(map_reg, map, &success, eq, &success); + if (instr->hydrogen()->has_migration_target()) { + __ Branch(deferred->entry()); + } else { + DeoptimizeIf(al, instr->environment()); + } + __ bind(&success); } diff --git a/src/mips/lithium-codegen-mips.h b/src/mips/lithium-codegen-mips.h index a328b03ba9..cc3873d845 100644 --- a/src/mips/lithium-codegen-mips.h +++ b/src/mips/lithium-codegen-mips.h @@ -153,7 +153,7 @@ class LCodeGen BASE_EMBEDDED { void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, Label* map_check); - void DoCheckMapCommon(Register map_reg, Handle map, LEnvironment* env); + void DoDeferredInstanceMigration(LCheckMaps* instr, Register object); // Parallel move support. void DoParallelMove(LParallelMove* move); diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc index c937f899b8..5adcff2409 100644 --- a/src/mips/lithium-mips.cc +++ b/src/mips/lithium-mips.cc @@ -1934,10 +1934,16 @@ LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) { LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { LOperand* value = NULL; - if (!instr->CanOmitMapChecks()) value = UseRegisterAtStart(instr->value()); - LInstruction* result = new(zone()) LCheckMaps(value); - if (instr->CanOmitMapChecks()) return result; - return AssignEnvironment(result); + if (!instr->CanOmitMapChecks()) { + value = UseRegisterAtStart(instr->value()); + if (instr->has_migration_target()) info()->MarkAsDeferredCalling(); + } + LCheckMaps* result = new(zone()) LCheckMaps(value); + if (!instr->CanOmitMapChecks()) { + AssignEnvironment(result); + if (instr->has_migration_target()) return AssignPointerMap(result); + } + return result; }