diff options
Diffstat (limited to 'deps/v8/src/x64/ic-x64.cc')
-rw-r--r-- | deps/v8/src/x64/ic-x64.cc | 98 |
1 files changed, 72 insertions, 26 deletions
diff --git a/deps/v8/src/x64/ic-x64.cc b/deps/v8/src/x64/ic-x64.cc index e5a4bfcfb5..f8c40ab4e1 100644 --- a/deps/v8/src/x64/ic-x64.cc +++ b/deps/v8/src/x64/ic-x64.cc @@ -108,6 +108,9 @@ 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 + @@ -819,27 +822,18 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { // rbx: receiver's elements array // rcx: index, zero-extended. __ bind(&check_pixel_array); - __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), - Heap::kPixelArrayMapRootIndex); - __ j(not_equal, &slow); - // Check that the value is a smi. If a conversion is needed call into the - // runtime to convert and clamp. - __ JumpIfNotSmi(rax, &slow); - __ cmpl(rcx, FieldOperand(rbx, PixelArray::kLengthOffset)); - __ j(above_equal, &slow); - // No more bailouts to slow case on this path, so key not needed. - __ SmiToInteger32(rdi, rax); - { // Clamp the value to [0..255]. - NearLabel done; - __ testl(rdi, Immediate(0xFFFFFF00)); - __ j(zero, &done); - __ setcc(negative, rdi); // 1 if negative, 0 if positive. - __ decb(rdi); // 0 if negative, 255 if positive. - __ bind(&done); - } - __ movq(rbx, FieldOperand(rbx, PixelArray::kExternalPointerOffset)); - __ movb(Operand(rbx, rcx, times_1, 0), rdi); - __ ret(0); + GenerateFastPixelArrayStore(masm, + rdx, + rcx, + rax, + rbx, + rdi, + false, + true, + NULL, + &slow, + &slow, + &slow); // Extra capacity case: Check if there is extra capacity to // perform the store and update the length. Used for adding one @@ -1233,7 +1227,13 @@ void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { // rsp[(argc + 1) * 8] : argument 0 = receiver // ----------------------------------- + // Check if the name is a string. + Label miss; + __ JumpIfSmi(rcx, &miss); + Condition cond = masm->IsObjectStringType(rcx, rax, rax); + __ j(NegateCondition(cond), &miss); GenerateCallNormal(masm, argc); + __ bind(&miss); GenerateMiss(masm, argc); } @@ -1473,7 +1473,8 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { } -void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { +void StoreIC::GenerateMegamorphic(MacroAssembler* masm, + Code::ExtraICState extra_ic_state) { // ----------- S t a t e ------------- // -- rax : value // -- rcx : name @@ -1484,7 +1485,8 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { // Get the receiver from the stack and probe the stub cache. Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, NOT_IN_LOOP, - MONOMORPHIC); + MONOMORPHIC, + extra_ic_state); StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, no_reg); // Cache miss: Jump to runtime. @@ -1673,11 +1675,23 @@ Condition CompareIC::ComputeCondition(Token::Value op) { } +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, false, x, y); + + State state = TargetState(previous_state, HasInlinedSmiCode(address()), x, y); if (state == GENERIC) { CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS); rewritten = stub.GetCode(); @@ -1695,11 +1709,43 @@ void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { Token::Name(op_)); } #endif + + // Activate inlined smi code. + if (previous_state == UNINITIALIZED) { + PatchInlinedSmiCode(address()); + } } void PatchInlinedSmiCode(Address address) { - // Disabled, then patched inline smi code is not implemented on X64. - // So we do nothing in this case. + // 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); } |