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