Chromium Code Reviews| Index: src/ia32/ic-ia32.cc |
| =================================================================== |
| --- src/ia32/ic-ia32.cc (revision 6011) |
| +++ src/ia32/ic-ia32.cc (working copy) |
| @@ -2049,13 +2049,23 @@ |
| } |
| +static bool HasInlinedSmiCode(Address address) { |
| + // The address of the instruction following the call. |
| + Address test_instruction_address = |
| + address + Assembler::kCallTargetAddressOffset; |
| + |
| + // If the instruction following the call is not a test al, nothing |
| + // was inlined. |
| + return *test_instruction_address == Assembler::kTestAlByte; |
| +} |
| + |
| + |
| void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { |
| HandleScope scope; |
| Handle<Code> rewritten; |
| -#ifdef DEBUG |
| State previous_state = GetState(); |
| -#endif |
| - State state = TargetState(x, y); |
| + |
| + State state = TargetState(previous_state, HasInlinedSmiCode(address()), x, y); |
| if (state == GENERIC) { |
| CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS); |
| rewritten = stub.GetCode(); |
| @@ -2073,9 +2083,47 @@ |
| Token::Name(op_)); |
| } |
| #endif |
| + |
| + // Activate inlined smi code. |
| + if (previous_state == UNINITIALIZED) { |
| + PatchInlinedSmiCode(address()); |
| + } |
| } |
| +void PatchInlinedSmiCode(Address address) { |
| + // The address of the instruction following the call. |
| + Address test_instruction_address = |
| + address + Assembler::kCallTargetAddressOffset; |
| + |
| + // If the instruction following the call is not a test al, nothing |
| + // was inlined. |
| + if (*test_instruction_address != Assembler::kTestAlByte) { |
| + ASSERT(*test_instruction_address == Assembler::kNopByte); |
| + return; |
| + } |
| + |
| + Address delta_address = test_instruction_address + 1; |
| + // The delta to the start of the map check instruction and the |
| + // condition code uses at the patched jump. |
| + int8_t delta = *reinterpret_cast<int8_t*>(delta_address); |
| + if (FLAG_trace_ic) { |
| + PrintF("[ patching ic at %p, test=%p, delta=%d\n", |
| + address, test_instruction_address, delta); |
| + } |
| + |
| + // Patch with a short conditional jump. There must be a |
| + // short jump-if-carry/not-carry at this position. |
| + Address jmp_address = test_instruction_address - delta; |
| + ASSERT(*jmp_address == Assembler::kJncShortOpcode || |
| + *jmp_address == Assembler::kJcShortOpcode); |
| + Condition cc = *jmp_address == Assembler::kJncShortOpcode |
|
Vitaly Repeshko
2010/12/15 12:18:50
Nit: "(*jmp_address == Assembler::kJncShortOpcode
|
| + ? not_zero |
| + : zero; |
| + *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| +} |
| + |
| + |
| } } // namespace v8::internal |
| #endif // V8_TARGET_ARCH_IA32 |