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