| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 |
| 6 | 6 |
| 7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
| 8 #include "src/ic/ic.h" | 8 #include "src/ic/ic.h" |
| 9 #include "src/ic/ic-compiler.h" | 9 #include "src/ic/ic-compiler.h" |
| 10 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 // Smi stores don't require further checks. | 402 // Smi stores don't require further checks. |
| 403 Label non_smi_value; | 403 Label non_smi_value; |
| 404 __ JumpIfNotSmi(value, &non_smi_value); | 404 __ JumpIfNotSmi(value, &non_smi_value); |
| 405 if (increment_length == kIncrementLength) { | 405 if (increment_length == kIncrementLength) { |
| 406 // Add 1 to receiver->length. | 406 // Add 1 to receiver->length. |
| 407 __ add(FieldOperand(receiver, JSArray::kLengthOffset), | 407 __ add(FieldOperand(receiver, JSArray::kLengthOffset), |
| 408 Immediate(Smi::FromInt(1))); | 408 Immediate(Smi::FromInt(1))); |
| 409 } | 409 } |
| 410 // It's irrelevant whether array is smi-only or not when writing a smi. | 410 // It's irrelevant whether array is smi-only or not when writing a smi. |
| 411 __ mov(FixedArrayElementOperand(ebx, key), value); | 411 __ mov(FixedArrayElementOperand(ebx, key), value); |
| 412 __ ret(0); | 412 __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize); |
| 413 | 413 |
| 414 __ bind(&non_smi_value); | 414 __ bind(&non_smi_value); |
| 415 // Escape to elements kind transition case. | 415 // Escape to elements kind transition case. |
| 416 __ mov(edi, FieldOperand(receiver, HeapObject::kMapOffset)); | 416 __ mov(edi, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 417 __ CheckFastObjectElements(edi, &transition_smi_elements); | 417 __ CheckFastObjectElements(edi, &transition_smi_elements); |
| 418 | 418 |
| 419 // Fast elements array, store the value to the elements backing store. | 419 // Fast elements array, store the value to the elements backing store. |
| 420 __ bind(&finish_object_store); | 420 __ bind(&finish_object_store); |
| 421 if (increment_length == kIncrementLength) { | 421 if (increment_length == kIncrementLength) { |
| 422 // Add 1 to receiver->length. | 422 // Add 1 to receiver->length. |
| 423 __ add(FieldOperand(receiver, JSArray::kLengthOffset), | 423 __ add(FieldOperand(receiver, JSArray::kLengthOffset), |
| 424 Immediate(Smi::FromInt(1))); | 424 Immediate(Smi::FromInt(1))); |
| 425 } | 425 } |
| 426 __ mov(FixedArrayElementOperand(ebx, key), value); | 426 __ mov(FixedArrayElementOperand(ebx, key), value); |
| 427 // Update write barrier for the elements array address. | 427 // Update write barrier for the elements array address. |
| 428 __ mov(edx, value); // Preserve the value which is returned. | 428 __ mov(edx, value); // Preserve the value which is returned. |
| 429 __ RecordWriteArray(ebx, edx, key, kDontSaveFPRegs, EMIT_REMEMBERED_SET, | 429 __ RecordWriteArray(ebx, edx, key, kDontSaveFPRegs, EMIT_REMEMBERED_SET, |
| 430 OMIT_SMI_CHECK); | 430 OMIT_SMI_CHECK); |
| 431 __ ret(0); | 431 __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize); |
| 432 | 432 |
| 433 __ bind(fast_double); | 433 __ bind(fast_double); |
| 434 if (check_map == kCheckMap) { | 434 if (check_map == kCheckMap) { |
| 435 // Check for fast double array case. If this fails, call through to the | 435 // Check for fast double array case. If this fails, call through to the |
| 436 // runtime. | 436 // runtime. |
| 437 __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map()); | 437 __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map()); |
| 438 __ j(not_equal, slow); | 438 __ j(not_equal, slow); |
| 439 // If the value is a number, store it as a double in the FastDoubleElements | 439 // If the value is a number, store it as a double in the FastDoubleElements |
| 440 // array. | 440 // array. |
| 441 } | 441 } |
| 442 | 442 |
| 443 // HOLECHECK: guards "A[i] double hole?" | 443 // HOLECHECK: guards "A[i] double hole?" |
| 444 // We have to see if the double version of the hole is present. If so | 444 // We have to see if the double version of the hole is present. If so |
| 445 // go to the runtime. | 445 // go to the runtime. |
| 446 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); | 446 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); |
| 447 __ cmp(FieldOperand(ebx, key, times_4, offset), Immediate(kHoleNanUpper32)); | 447 __ cmp(FieldOperand(ebx, key, times_4, offset), Immediate(kHoleNanUpper32)); |
| 448 __ j(not_equal, &fast_double_without_map_check); | 448 __ j(not_equal, &fast_double_without_map_check); |
| 449 __ JumpIfDictionaryInPrototypeChain(receiver, ebx, edi, slow); | 449 __ JumpIfDictionaryInPrototypeChain(receiver, ebx, edi, slow); |
| 450 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); | 450 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); |
| 451 | 451 |
| 452 __ bind(&fast_double_without_map_check); | 452 __ bind(&fast_double_without_map_check); |
| 453 __ StoreNumberToDoubleElements(value, ebx, key, edi, | 453 __ StoreNumberToDoubleElements(value, ebx, key, edi, |
| 454 &transition_double_elements, false); | 454 &transition_double_elements, false); |
| 455 if (increment_length == kIncrementLength) { | 455 if (increment_length == kIncrementLength) { |
| 456 // Add 1 to receiver->length. | 456 // Add 1 to receiver->length. |
| 457 __ add(FieldOperand(receiver, JSArray::kLengthOffset), | 457 __ add(FieldOperand(receiver, JSArray::kLengthOffset), |
| 458 Immediate(Smi::FromInt(1))); | 458 Immediate(Smi::FromInt(1))); |
| 459 } | 459 } |
| 460 __ ret(0); | 460 __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize); |
| 461 | 461 |
| 462 __ bind(&transition_smi_elements); | 462 __ bind(&transition_smi_elements); |
| 463 __ mov(ebx, FieldOperand(receiver, HeapObject::kMapOffset)); | 463 __ mov(ebx, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 464 | 464 |
| 465 // Transition the array appropriately depending on the value type. | 465 // Transition the array appropriately depending on the value type. |
| 466 __ CheckMap(value, masm->isolate()->factory()->heap_number_map(), | 466 __ CheckMap(value, masm->isolate()->factory()->heap_number_map(), |
| 467 &non_double_value, DONT_DO_SMI_CHECK); | 467 &non_double_value, DONT_DO_SMI_CHECK); |
| 468 | 468 |
| 469 // Value is a double. Transition FAST_SMI_ELEMENTS -> FAST_DOUBLE_ELEMENTS | 469 // Value is a double. Transition FAST_SMI_ELEMENTS -> FAST_DOUBLE_ELEMENTS |
| 470 // and complete the store. | 470 // and complete the store. |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 __ pop(ebx); | 698 __ pop(ebx); |
| 699 __ push(receiver); | 699 __ push(receiver); |
| 700 __ push(name); | 700 __ push(name); |
| 701 __ push(ebx); | 701 __ push(ebx); |
| 702 | 702 |
| 703 // Do tail-call to runtime routine. | 703 // Do tail-call to runtime routine. |
| 704 __ TailCallRuntime(Runtime::kKeyedGetProperty); | 704 __ TailCallRuntime(Runtime::kKeyedGetProperty); |
| 705 } | 705 } |
| 706 | 706 |
| 707 static void StoreIC_PushArgs(MacroAssembler* masm) { | 707 static void StoreIC_PushArgs(MacroAssembler* masm) { |
| 708 Register receiver = StoreDescriptor::ReceiverRegister(); | 708 Register receiver = StoreWithVectorDescriptor::ReceiverRegister(); |
| 709 Register name = StoreDescriptor::NameRegister(); | 709 Register name = StoreWithVectorDescriptor::NameRegister(); |
| 710 Register value = StoreDescriptor::ValueRegister(); | |
| 711 Register slot = StoreWithVectorDescriptor::SlotRegister(); | |
| 712 Register vector = StoreWithVectorDescriptor::VectorRegister(); | |
| 713 | 710 |
| 714 __ xchg(value, Operand(esp, 0)); | 711 STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3); |
| 715 __ push(slot); | 712 // Current stack layout: |
| 716 __ push(vector); | 713 // - esp[12] -- value |
| 714 // - esp[8] -- slot |
| 715 // - esp[4] -- vector |
| 716 // - esp[0] -- return address |
| 717 |
| 718 Register return_address = StoreWithVectorDescriptor::SlotRegister(); |
| 719 __ pop(return_address); |
| 717 __ push(receiver); | 720 __ push(receiver); |
| 718 __ push(name); | 721 __ push(name); |
| 719 __ push(value); // Contains the return address. | 722 __ push(return_address); |
| 720 } | 723 } |
| 721 | 724 |
| 722 | 725 |
| 723 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 726 void StoreIC::GenerateMiss(MacroAssembler* masm) { |
| 724 // Return address is on the stack. | 727 // Return address is on the stack. |
| 725 StoreIC_PushArgs(masm); | 728 StoreIC_PushArgs(masm); |
| 726 | 729 |
| 727 // Perform tail call to the entry. | 730 // Perform tail call to the entry. |
| 728 __ TailCallRuntime(Runtime::kStoreIC_Miss); | 731 __ TailCallRuntime(Runtime::kStoreIC_Miss); |
| 729 } | 732 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 744 __ push(vector); | 747 __ push(vector); |
| 745 __ push(slot); | 748 __ push(slot); |
| 746 | 749 |
| 747 Register dictionary = ebx; | 750 Register dictionary = ebx; |
| 748 __ mov(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 751 __ mov(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 749 GenerateDictionaryStore(masm, &restore_miss, dictionary, name, value, | 752 GenerateDictionaryStore(masm, &restore_miss, dictionary, name, value, |
| 750 receiver, edi); | 753 receiver, edi); |
| 751 __ Drop(3); | 754 __ Drop(3); |
| 752 Counters* counters = masm->isolate()->counters(); | 755 Counters* counters = masm->isolate()->counters(); |
| 753 __ IncrementCounter(counters->ic_store_normal_hit(), 1); | 756 __ IncrementCounter(counters->ic_store_normal_hit(), 1); |
| 754 __ ret(0); | 757 __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize); |
| 755 | 758 |
| 756 __ bind(&restore_miss); | 759 __ bind(&restore_miss); |
| 757 __ pop(slot); | 760 __ pop(slot); |
| 758 __ pop(vector); | 761 __ pop(vector); |
| 759 __ pop(receiver); | 762 __ pop(receiver); |
| 760 __ IncrementCounter(counters->ic_store_normal_miss(), 1); | 763 __ IncrementCounter(counters->ic_store_normal_miss(), 1); |
| 761 GenerateMiss(masm); | 764 GenerateMiss(masm); |
| 762 } | 765 } |
| 763 | 766 |
| 764 | 767 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 847 Condition cc = | 850 Condition cc = |
| 848 (check == ENABLE_INLINED_SMI_CHECK) | 851 (check == ENABLE_INLINED_SMI_CHECK) |
| 849 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 852 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
| 850 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 853 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
| 851 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 854 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 852 } | 855 } |
| 853 } // namespace internal | 856 } // namespace internal |
| 854 } // namespace v8 | 857 } // namespace v8 |
| 855 | 858 |
| 856 #endif // V8_TARGET_ARCH_X87 | 859 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |