Index: src/arm64/lithium-codegen-arm64.cc |
diff --git a/src/arm64/lithium-codegen-arm64.cc b/src/arm64/lithium-codegen-arm64.cc |
index 3dff64cbe84ce91571d901dbdfcab2f4cc1c81a7..728f074a8a0b0dcb5a80c392c538ed37e60f0c0f 100644 |
--- a/src/arm64/lithium-codegen-arm64.cc |
+++ b/src/arm64/lithium-codegen-arm64.cc |
@@ -3007,135 +3007,39 @@ void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { |
void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
DCHECK(ToRegister(instr->context()).is(cp)); |
- // Assert that the arguments are in the registers expected by InstanceofStub. |
- DCHECK(ToRegister(instr->left()).Is(InstanceofStub::left())); |
- DCHECK(ToRegister(instr->right()).Is(InstanceofStub::right())); |
- |
- InstanceofStub stub(isolate(), InstanceofStub::kArgsInRegisters); |
+ DCHECK(ToRegister(instr->left()).is(InstanceOfDescriptor::LeftRegister())); |
+ DCHECK(ToRegister(instr->right()).is(InstanceOfDescriptor::RightRegister())); |
+ DCHECK(ToRegister(instr->result()).is(x0)); |
+ InstanceOfStub stub(isolate()); |
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
- |
- // InstanceofStub returns a result in x0: |
- // 0 => not an instance |
- // smi 1 => instance. |
- __ Cmp(x0, 0); |
- __ LoadTrueFalseRoots(x0, x1); |
- __ Csel(x0, x0, x1, eq); |
} |
-void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
- class DeferredInstanceOfKnownGlobal: public LDeferredCode { |
- public: |
- DeferredInstanceOfKnownGlobal(LCodeGen* codegen, |
- LInstanceOfKnownGlobal* instr) |
- : LDeferredCode(codegen), instr_(instr) { } |
- virtual void Generate() { |
- codegen()->DoDeferredInstanceOfKnownGlobal(instr_); |
- } |
- virtual LInstruction* instr() { return instr_; } |
- private: |
- LInstanceOfKnownGlobal* instr_; |
- }; |
- |
- DeferredInstanceOfKnownGlobal* deferred = |
- new(zone()) DeferredInstanceOfKnownGlobal(this, instr); |
- |
- Label map_check, return_false, cache_miss, done; |
- Register object = ToRegister(instr->value()); |
- Register result = ToRegister(instr->result()); |
- // x4 is expected in the associated deferred code and stub. |
- Register map_check_site = x4; |
- Register map = x5; |
- |
- // This instruction is marked as call. We can clobber any register. |
- DCHECK(instr->IsMarkedAsCall()); |
- |
- // We must take into account that object is in x11. |
- DCHECK(object.Is(x11)); |
- Register scratch = x10; |
- |
- // A Smi is not instance of anything. |
- __ JumpIfSmi(object, &return_false); |
+void LCodeGen::DoHasInPrototypeChainAndBranch( |
+ LHasInPrototypeChainAndBranch* instr) { |
+ Register const object = ToRegister(instr->object()); |
+ Register const object_map = ToRegister(instr->scratch()); |
+ Register const object_prototype = object_map; |
+ Register const prototype = ToRegister(instr->prototype()); |
- // This is the inlined call site instanceof cache. The two occurences of the |
- // hole value will be patched to the last map/result pair generated by the |
- // instanceof stub. |
- __ Ldr(map, FieldMemOperand(object, HeapObject::kMapOffset)); |
- { |
- // Below we use Factory::the_hole_value() on purpose instead of loading from |
- // the root array to force relocation and later be able to patch with a |
- // custom value. |
- InstructionAccurateScope scope(masm(), 5); |
- __ bind(&map_check); |
- // Will be patched with the cached map. |
- Handle<Cell> cell = factory()->NewCell(factory()->the_hole_value()); |
- __ ldr(scratch, Immediate(cell)); |
- __ ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); |
- __ cmp(map, scratch); |
- __ b(&cache_miss, ne); |
- // The address of this instruction is computed relative to the map check |
- // above, so check the size of the code generated. |
- DCHECK(masm()->InstructionsGeneratedSince(&map_check) == 4); |
- // Will be patched with the cached result. |
- __ ldr(result, Immediate(factory()->the_hole_value())); |
+ // The {object} must be a spec object. It's sufficient to know that {object} |
+ // is not a smi, since all other non-spec objects have {null} prototypes and |
+ // will be ruled out below. |
+ if (instr->hydrogen()->ObjectNeedsSmiCheck()) { |
+ __ JumpIfSmi(object, instr->FalseLabel(chunk_)); |
} |
- __ B(&done); |
- |
- // The inlined call site cache did not match. |
- // Check null and string before calling the deferred code. |
- __ Bind(&cache_miss); |
- // Compute the address of the map check. It must not be clobbered until the |
- // InstanceOfStub has used it. |
- __ Adr(map_check_site, &map_check); |
- // Null is not instance of anything. |
- __ JumpIfRoot(object, Heap::kNullValueRootIndex, &return_false); |
- |
- // String values are not instances of anything. |
- // Return false if the object is a string. Otherwise, jump to the deferred |
- // code. |
- // Note that we can't jump directly to deferred code from |
- // IsObjectJSStringType, because it uses tbz for the jump and the deferred |
- // code can be out of range. |
- __ IsObjectJSStringType(object, scratch, NULL, &return_false); |
- __ B(deferred->entry()); |
- |
- __ Bind(&return_false); |
- __ LoadRoot(result, Heap::kFalseValueRootIndex); |
- |
- // Here result is either true or false. |
- __ Bind(deferred->exit()); |
- __ Bind(&done); |
-} |
- |
-void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
- Register result = ToRegister(instr->result()); |
- DCHECK(result.Is(x0)); // InstanceofStub returns its result in x0. |
- InstanceofStub::Flags flags = InstanceofStub::kNoFlags; |
- flags = static_cast<InstanceofStub::Flags>( |
- flags | InstanceofStub::kArgsInRegisters); |
- flags = static_cast<InstanceofStub::Flags>( |
- flags | InstanceofStub::kReturnTrueFalseObject); |
- flags = static_cast<InstanceofStub::Flags>( |
- flags | InstanceofStub::kCallSiteInlineCheck); |
- |
- PushSafepointRegistersScope scope(this); |
- LoadContextFromDeferred(instr->context()); |
- |
- // Prepare InstanceofStub arguments. |
- DCHECK(ToRegister(instr->value()).Is(InstanceofStub::left())); |
- __ LoadObject(InstanceofStub::right(), instr->function()); |
- |
- InstanceofStub stub(isolate(), flags); |
- CallCodeGeneric(stub.GetCode(), |
- RelocInfo::CODE_TARGET, |
- instr, |
- RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
- LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment(); |
- safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
- |
- // Put the result value into the result register slot. |
- __ StoreToSafepointRegisterSlot(result, result); |
+ // Loop through the {object}s prototype chain looking for the {prototype}. |
+ __ Ldr(object_map, FieldMemOperand(object, HeapObject::kMapOffset)); |
+ Label loop; |
+ __ Bind(&loop); |
+ __ Ldr(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset)); |
+ __ Cmp(object_prototype, prototype); |
+ __ B(eq, instr->TrueLabel(chunk_)); |
+ __ CompareRoot(object_prototype, Heap::kNullValueRootIndex); |
+ __ B(eq, instr->FalseLabel(chunk_)); |
+ __ Ldr(object_map, FieldMemOperand(object_prototype, HeapObject::kMapOffset)); |
+ __ B(&loop); |
} |