diff options
Diffstat (limited to 'src/ia32/ic-ia32.cc')
-rw-r--r-- | src/ia32/ic-ia32.cc | 145 |
1 files changed, 128 insertions, 17 deletions
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc index ddfbb91c..9c9304d5 100644 --- a/src/ia32/ic-ia32.cc +++ b/src/ia32/ic-ia32.cc @@ -108,9 +108,6 @@ static void GenerateStringDictionaryProbes(MacroAssembler* masm, Register name, Register r0, Register r1) { - // Assert that name contains a string. - if (FLAG_debug_code) __ AbortIfNotString(name); - // Compute the capacity mask. const int kCapacityOffset = StringDictionary::kHeaderSize + @@ -713,7 +710,7 @@ void KeyedLoadIC::GenerateString(MacroAssembler* masm) { char_at_generator.GenerateFast(masm); __ ret(0); - ICRuntimeCallHelper call_helper; + StubRuntimeCallHelper call_helper; char_at_generator.GenerateSlow(masm, call_helper); __ bind(&miss); @@ -1552,14 +1549,7 @@ void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { // -- esp[(argc + 1) * 4] : receiver // ----------------------------------- - // Check if the name is a string. - Label miss; - __ test(ecx, Immediate(kSmiTagMask)); - __ j(zero, &miss); - Condition cond = masm->IsObjectStringType(ecx, eax, eax); - __ j(NegateCondition(cond), &miss); GenerateCallNormal(masm, argc); - __ bind(&miss); GenerateMiss(masm, argc); } @@ -1639,16 +1629,15 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) { } -// One byte opcode for test eax,0xXXXXXXXX. -static const byte kTestEaxByte = 0xA9; - bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { + if (V8::UseCrankshaft()) return false; + // 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 eax, nothing // was inlined. - if (*test_instruction_address != kTestEaxByte) return false; + if (*test_instruction_address != Assembler::kTestEaxByte) return false; Address delta_address = test_instruction_address + 1; // The delta to the start of the map check instruction. @@ -1692,6 +1681,8 @@ bool LoadIC::PatchInlinedContextualLoad(Address address, Object* map, Object* cell, bool is_dont_delete) { + if (V8::UseCrankshaft()) return false; + // The address of the instruction following the call. Address mov_instruction_address = address + Assembler::kCallTargetAddressOffset; @@ -1723,13 +1714,15 @@ bool LoadIC::PatchInlinedContextualLoad(Address address, bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { + if (V8::UseCrankshaft()) return false; + // 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 eax, nothing // was inlined. - if (*test_instruction_address != kTestEaxByte) return false; + if (*test_instruction_address != Assembler::kTestEaxByte) return false; // Extract the encoded deltas from the test eax instruction. Address encoded_offsets_address = test_instruction_address + 1; @@ -1769,11 +1762,13 @@ bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { static bool PatchInlinedMapCheck(Address address, Object* map) { + if (V8::UseCrankshaft()) return false; + Address test_instruction_address = address + Assembler::kCallTargetAddressOffset; // The keyed load has a fast inlined case if the IC call instruction // is immediately followed by a test instruction. - if (*test_instruction_address != kTestEaxByte) return false; + if (*test_instruction_address != Assembler::kTestEaxByte) return false; // Fetch the offset from the test instruction to the map cmp // instruction. This offset is stored in the last 4 bytes of the 5 @@ -1969,6 +1964,24 @@ void StoreIC::GenerateNormal(MacroAssembler* masm) { } +void StoreIC::GenerateGlobalProxy(MacroAssembler* masm) { + // ----------- S t a t e ------------- + // -- eax : value + // -- ecx : name + // -- edx : receiver + // -- esp[0] : return address + // ----------------------------------- + __ pop(ebx); + __ push(edx); + __ push(ecx); + __ push(eax); + __ push(ebx); + + // Do tail-call to runtime routine. + __ TailCallRuntime(Runtime::kSetProperty, 3, 1); +} + + // Defined in ic.cc. Object* KeyedStoreIC_Miss(Arguments args); @@ -2010,9 +2023,107 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { __ TailCallExternalReference(ref, 3, 1); } + #undef __ +Condition CompareIC::ComputeCondition(Token::Value op) { + switch (op) { + case Token::EQ_STRICT: + case Token::EQ: + return equal; + case Token::LT: + return less; + case Token::GT: + // Reverse left and right operands to obtain ECMA-262 conversion order. + return less; + case Token::LTE: + // Reverse left and right operands to obtain ECMA-262 conversion order. + return greater_equal; + case Token::GTE: + return greater_equal; + default: + UNREACHABLE(); + return no_condition; + } +} + + +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; + State previous_state = GetState(); + + State state = TargetState(previous_state, HasInlinedSmiCode(address()), x, y); + if (state == GENERIC) { + CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS); + rewritten = stub.GetCode(); + } else { + ICCompareStub stub(op_, state); + rewritten = stub.GetCode(); + } + set_target(*rewritten); + +#ifdef DEBUG + if (FLAG_trace_ic) { + PrintF("[CompareIC (%s->%s)#%s]\n", + GetStateName(previous_state), + GetStateName(state), + 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 + ? not_zero + : zero; + *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); +} + + } } // namespace v8::internal #endif // V8_TARGET_ARCH_IA32 |