Chromium Code Reviews| Index: src/ia32/lithium-codegen-ia32.cc |
| =================================================================== |
| --- src/ia32/lithium-codegen-ia32.cc (revision 6109) |
| +++ src/ia32/lithium-codegen-ia32.cc (working copy) |
| @@ -1700,7 +1700,7 @@ |
| void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| - // Object and function are in fixed registers eax and edx. |
| + // Object and function are in fixed registers defined by the stub. |
| InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
| CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| @@ -1726,6 +1726,107 @@ |
| } |
| +void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
| + class DeferredInstanceOfKnownGlobal: public LDeferredCode { |
| + public: |
| + DeferredInstanceOfKnownGlobal(LCodeGen* codegen, |
| + LInstanceOfKnownGlobal* instr) |
| + : LDeferredCode(codegen), instr_(instr) { } |
| + virtual void Generate() { |
| + 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 done, cache_miss, false_result; |
| + Register object = ToRegister(instr->input()); |
| + Register temp = ToRegister(instr->temp()); |
| + |
| + // A Smi is not instance of anything. |
| + __ test(object, Immediate(kSmiTagMask)); |
| + __ j(zero, &false_result, not_taken); |
| + |
| + // This is the inlined call site instanceof cache. The two occourences of the |
| + // hole value will be patched to the last map/result pair generated by the |
| + // instance off stub. |
|
Mads Ager (chromium)
2011/01/04 17:25:58
off -> of
Søren Thygesen Gjesse
2011/01/05 09:28:00
Done.
|
| + Register map = ToRegister(instr->temp()); |
| + __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); |
| + __ bind(deferred->map_check()); // Label for calculating code patching. |
| + __ cmp(map, Factory::the_hole_value()); // Patched to cached map. |
| + __ j(not_equal, &cache_miss, not_taken); |
| + __ mov(eax, Factory::the_hole_value()); // Patched to either true or false. |
| + __ jmp(&done); |
| + |
| + // The inlined call site cache did not match. Check null and string before |
| + // calling the deferred code. |
| + __ bind(&cache_miss); |
| + // Null is not instance of anything. |
| + __ cmp(object, Factory::null_value()); |
| + __ j(equal, &false_result); |
| + |
| + // String values is not instance of anything. |
| + Condition is_string = masm_->IsObjectStringType(object, temp, temp); |
| + __ j(is_string, &false_result); |
| + |
| + // Go to the deferred code. |
| + __ jmp(deferred->entry()); |
| + |
| + __ bind(&false_result); |
| + __ mov(ToRegister(instr->result()), Factory::false_value()); |
| + |
| + // Here result has either true or false. Deferred code also produces true or |
| + // false object. |
| + __ bind(deferred->exit()); |
| + __ bind(&done); |
| +} |
| + |
| + |
| +void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, |
| + Label* map_check) { |
| + __ PushSafepointRegisters(); |
| + |
| + InstanceofStub::Flags flags = InstanceofStub::kNoFlags; |
| + flags = static_cast<InstanceofStub::Flags>( |
| + flags | InstanceofStub::kArgsInRegisters); |
| + flags = static_cast<InstanceofStub::Flags>( |
| + flags | InstanceofStub::kCallSiteInlineCheck); |
| + flags = static_cast<InstanceofStub::Flags>( |
| + flags | InstanceofStub::kReturnTrueFalseObject); |
| + |
|
Mads Ager (chromium)
2011/01/04 17:25:58
Remove extra newline?
Søren Thygesen Gjesse
2011/01/05 09:28:00
Done.
|
| + |
| + // Get the temp register reserved by the instruction. This needs to be edi as |
| + // its slot of the pushing of safepoint registers is used to communicate the |
| + // offset to the location where to patch the map. |
|
Mads Ager (chromium)
2011/01/04 17:25:58
to the location of the map check?
Søren Thygesen Gjesse
2011/01/05 09:28:00
Done.
|
| + Register temp = ToRegister(instr->temp()); |
| + ASSERT(temp.is(edi)); |
| + __ mov(InstanceofStub::right(), Immediate(instr->function())); |
| + InstanceofStub stub(flags); |
| + static const int kAdditionalDelta = 13; |
| + int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; |
| + Label before_push_delta; |
| + __ bind(&before_push_delta); |
| + __ mov(temp, Immediate(delta)); |
| + __ mov(Operand(esp, EspIndexForPushAll(temp) * kPointerSize), temp); |
| + __ call(stub.GetCode(), RelocInfo::CODE_TARGET); |
| + ASSERT_EQ(kAdditionalDelta, |
| + masm_->SizeOfCodeGeneratedSince(&before_push_delta)); |
| + RecordSafepointWithRegisters( |
| + instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
| + // Put the result value into the eax slot and restore all registres. |
|
Mads Ager (chromium)
2011/01/04 17:25:58
registres -> registers
Søren Thygesen Gjesse
2011/01/05 09:28:00
Done.
|
| + __ mov(Operand(esp, EspIndexForPushAll(eax) * kPointerSize), eax); |
| + |
| + __ PopSafepointRegisters(); |
| +} |
| + |
| + |
| static Condition ComputeCompareCondition(Token::Value op) { |
| switch (op) { |
| case Token::EQ_STRICT: |