| Index: src/x64/lithium-codegen-x64.cc
|
| ===================================================================
|
| --- src/x64/lithium-codegen-x64.cc (revision 7107)
|
| +++ src/x64/lithium-codegen-x64.cc (working copy)
|
| @@ -1823,24 +1823,50 @@
|
| LInstanceOfKnownGlobal* instr)
|
| : LDeferredCode(codegen), instr_(instr) { }
|
| virtual void Generate() {
|
| - codegen()->DoDeferredLInstanceOfKnownGlobal(instr_);
|
| + codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_);
|
| }
|
|
|
| + Label* map_check() { return &map_check_; }
|
| +
|
| private:
|
| LInstanceOfKnownGlobal* instr_;
|
| + Label map_check_;
|
| };
|
|
|
|
|
| DeferredInstanceOfKnownGlobal* deferred;
|
| deferred = new DeferredInstanceOfKnownGlobal(this, instr);
|
|
|
| - Label false_result;
|
| + Label done, false_result;
|
| Register object = ToRegister(instr->InputAt(0));
|
|
|
| // A Smi is not an instance of anything.
|
| __ JumpIfSmi(object, &false_result);
|
|
|
| - // Null is not an instance of anything.
|
| + // 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.
|
| + NearLabel cache_miss;
|
| + // Use a temp register to avoid memory operands with variable lengths.
|
| + Register map = ToRegister(instr->TempAt(0));
|
| + __ movq(map, FieldOperand(object, HeapObject::kMapOffset));
|
| + __ bind(deferred->map_check()); // Label for calculating code patching.
|
| + __ Move(kScratchRegister, Factory::the_hole_value());
|
| + __ cmpq(map, kScratchRegister); // Patched to cached map.
|
| + __ j(not_equal, &cache_miss);
|
| + // Patched to load either true or false.
|
| + __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex);
|
| +#ifdef DEBUG
|
| + // Check that the code size between patch label and patch sites is invariant.
|
| + Label end_of_patched_code;
|
| + __ bind(&end_of_patched_code);
|
| + ASSERT(true);
|
| +#endif
|
| + __ jmp(&done);
|
| +
|
| + // The inlined call site cache did not match. Check for null and string
|
| + // before calling the deferred code.
|
| + __ bind(&cache_miss); // Null is not an instance of anything.
|
| __ CompareRoot(object, Heap::kNullValueRootIndex);
|
| __ j(equal, &false_result);
|
|
|
| @@ -1851,17 +1877,26 @@
|
| __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
|
|
|
| __ bind(deferred->exit());
|
| + __ bind(&done);
|
| }
|
|
|
|
|
| -void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
|
| +void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
|
| + Label* map_check) {
|
| __ PushSafepointRegisters();
|
| + InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>(
|
| + InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck);
|
| + InstanceofStub stub(flags);
|
|
|
| - InstanceofStub stub(InstanceofStub::kNoFlags);
|
| -
|
| __ push(ToRegister(instr->InputAt(0)));
|
| __ Push(instr->function());
|
| - __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| + Register temp = ToRegister(instr->TempAt(0));
|
| + ASSERT(temp.is(rdi));
|
| + static const int kAdditionalDelta = 16;
|
| + int delta =
|
| + masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
|
| + __ movq(temp, Immediate(delta));
|
| + __ push(temp);
|
| CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
| __ movq(kScratchRegister, rax);
|
| __ PopSafepointRegisters();
|
|
|