| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 } | 205 } |
| 206 | 206 |
| 207 | 207 |
| 208 void KeyedStoreIC::RestoreInlinedVersion(Address address) { | 208 void KeyedStoreIC::RestoreInlinedVersion(Address address) { |
| 209 // Restore the fast-case elements map check so that the inlined | 209 // Restore the fast-case elements map check so that the inlined |
| 210 // version can be used again. | 210 // version can be used again. |
| 211 PatchInlinedStore(address, Heap::fixed_array_map()); | 211 PatchInlinedStore(address, Heap::fixed_array_map()); |
| 212 } | 212 } |
| 213 | 213 |
| 214 | 214 |
| 215 void KeyedLoadIC::Generate(MacroAssembler* masm, | 215 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { |
| 216 ExternalReference const& f) { | |
| 217 // ----------- S t a t e ------------- | 216 // ----------- S t a t e ------------- |
| 218 // -- rsp[0] : return address | 217 // -- rsp[0] : return address |
| 219 // -- rsp[8] : name | 218 // -- rsp[8] : name |
| 220 // -- rsp[16] : receiver | 219 // -- rsp[16] : receiver |
| 221 // ----------------------------------- | 220 // ----------------------------------- |
| 222 | 221 |
| 223 __ movq(rax, Operand(rsp, kPointerSize)); | |
| 224 __ movq(rcx, Operand(rsp, 2 * kPointerSize)); | |
| 225 __ pop(rbx); | 222 __ pop(rbx); |
| 226 __ push(rcx); // receiver | 223 __ push(Operand(rsp, 1 * kPointerSize)); // receiver |
| 227 __ push(rax); // name | 224 __ push(Operand(rsp, 1 * kPointerSize)); // name |
| 228 __ push(rbx); // return address | 225 __ push(rbx); // return address |
| 229 | 226 |
| 230 // Perform tail call to the entry. | 227 // Perform tail call to the entry. |
| 231 __ TailCallRuntime(f, 2, 1); | 228 __ TailCallRuntime(ExternalReference(IC_Utility(kKeyedLoadIC_Miss)), 2, 1); |
| 229 } |
| 230 |
| 231 |
| 232 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 233 // ----------- S t a t e ------------- |
| 234 // -- rsp[0] : return address |
| 235 // -- rsp[8] : name |
| 236 // -- rsp[16] : receiver |
| 237 // ----------------------------------- |
| 238 |
| 239 __ pop(rbx); |
| 240 __ push(Operand(rsp, 1 * kPointerSize)); // receiver |
| 241 __ push(Operand(rsp, 1 * kPointerSize)); // name |
| 242 __ push(rbx); // return address |
| 243 |
| 244 // Perform tail call to the entry. |
| 245 __ TailCallRuntime(ExternalReference(Runtime::kKeyedGetProperty), 2, 1); |
| 232 } | 246 } |
| 233 | 247 |
| 234 | 248 |
| 235 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 249 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
| 236 // ----------- S t a t e ------------- | 250 // ----------- S t a t e ------------- |
| 237 // -- rsp[0] : return address | 251 // -- rsp[0] : return address |
| 238 // -- rsp[8] : name | 252 // -- rsp[8] : name |
| 239 // -- rsp[16] : receiver | 253 // -- rsp[16] : receiver |
| 240 // ----------------------------------- | 254 // ----------------------------------- |
| 241 Label slow, check_string, index_int, index_string; | 255 Label slow, check_string, index_int, index_string; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 294 __ cmpl(rax, FieldOperand(rcx, PixelArray::kLengthOffset)); | 308 __ cmpl(rax, FieldOperand(rcx, PixelArray::kLengthOffset)); |
| 295 __ j(above_equal, &slow); | 309 __ j(above_equal, &slow); |
| 296 __ movq(rcx, FieldOperand(rcx, PixelArray::kExternalPointerOffset)); | 310 __ movq(rcx, FieldOperand(rcx, PixelArray::kExternalPointerOffset)); |
| 297 __ movzxbq(rax, Operand(rcx, rax, times_1, 0)); | 311 __ movzxbq(rax, Operand(rcx, rax, times_1, 0)); |
| 298 __ Integer32ToSmi(rax, rax); | 312 __ Integer32ToSmi(rax, rax); |
| 299 __ ret(0); | 313 __ ret(0); |
| 300 | 314 |
| 301 // Slow case: Load name and receiver from stack and jump to runtime. | 315 // Slow case: Load name and receiver from stack and jump to runtime. |
| 302 __ bind(&slow); | 316 __ bind(&slow); |
| 303 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); | 317 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); |
| 304 Generate(masm, ExternalReference(Runtime::kKeyedGetProperty)); | 318 GenerateRuntimeGetProperty(masm); |
| 305 __ bind(&check_string); | 319 __ bind(&check_string); |
| 306 // The key is not a smi. | 320 // The key is not a smi. |
| 307 // Is it a string? | 321 // Is it a string? |
| 308 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); | 322 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); |
| 309 __ j(above_equal, &slow); | 323 __ j(above_equal, &slow); |
| 310 // Is the string an array index, with cached numeric value? | 324 // Is the string an array index, with cached numeric value? |
| 311 __ movl(rbx, FieldOperand(rax, String::kHashFieldOffset)); | 325 __ movl(rbx, FieldOperand(rax, String::kHashFieldOffset)); |
| 312 __ testl(rbx, Immediate(String::kIsArrayIndexMask)); | 326 __ testl(rbx, Immediate(String::kIsArrayIndexMask)); |
| 313 | 327 |
| 314 // Is the string a symbol? | 328 // Is the string a symbol? |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 531 // If we fail allocation of the HeapNumber, we still have a value on | 545 // If we fail allocation of the HeapNumber, we still have a value on |
| 532 // top of the FPU stack. Remove it. | 546 // top of the FPU stack. Remove it. |
| 533 __ bind(&failed_allocation); | 547 __ bind(&failed_allocation); |
| 534 __ ffree(); | 548 __ ffree(); |
| 535 __ fincstp(); | 549 __ fincstp(); |
| 536 // Fall through to slow case. | 550 // Fall through to slow case. |
| 537 | 551 |
| 538 // Slow case: Load name and receiver from stack and jump to runtime. | 552 // Slow case: Load name and receiver from stack and jump to runtime. |
| 539 __ bind(&slow); | 553 __ bind(&slow); |
| 540 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1); | 554 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1); |
| 541 Generate(masm, ExternalReference(Runtime::kKeyedGetProperty)); | 555 GenerateRuntimeGetProperty(masm); |
| 542 } | 556 } |
| 543 | 557 |
| 544 | 558 |
| 545 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { | 559 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
| 546 // ----------- S t a t e ------------- | 560 // ----------- S t a t e ------------- |
| 547 // -- rsp[0] : return address | 561 // -- rsp[0] : return address |
| 548 // -- rsp[8] : name | 562 // -- rsp[8] : key |
| 549 // -- rsp[16] : receiver | 563 // -- rsp[16] : receiver |
| 550 // ----------------------------------- | 564 // ----------------------------------- |
| 551 Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss))); | 565 Label slow; |
| 566 |
| 567 // Load key and receiver. |
| 568 __ movq(rax, Operand(rsp, kPointerSize)); |
| 569 __ movq(rcx, Operand(rsp, 2 * kPointerSize)); |
| 570 |
| 571 // Check that the receiver isn't a smi. |
| 572 __ JumpIfSmi(rcx, &slow); |
| 573 |
| 574 // Check that the key is a smi. |
| 575 __ JumpIfNotSmi(rax, &slow); |
| 576 |
| 577 // Get the map of the receiver. |
| 578 __ movq(rdx, FieldOperand(rcx, HeapObject::kMapOffset)); |
| 579 |
| 580 // Check that it has indexed interceptor and access checks |
| 581 // are not enabled for this object. |
| 582 __ movb(rdx, FieldOperand(rdx, Map::kBitFieldOffset)); |
| 583 __ andb(rdx, Immediate(kSlowCaseBitFieldMask)); |
| 584 __ cmpb(rdx, Immediate(1 << Map::kHasIndexedInterceptor)); |
| 585 __ j(not_zero, &slow); |
| 586 |
| 587 // Everything is fine, call runtime. |
| 588 __ pop(rdx); |
| 589 __ push(rcx); // receiver |
| 590 __ push(rax); // key |
| 591 __ push(rdx); // return address |
| 592 |
| 593 // Perform tail call to the entry. |
| 594 __ TailCallRuntime(ExternalReference( |
| 595 IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1); |
| 596 |
| 597 __ bind(&slow); |
| 598 GenerateMiss(masm); |
| 552 } | 599 } |
| 553 | 600 |
| 554 | 601 |
| 555 void KeyedStoreIC::Generate(MacroAssembler* masm, ExternalReference const& f) { | 602 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { |
| 556 // ----------- S t a t e ------------- | 603 // ----------- S t a t e ------------- |
| 557 // -- rax : value | 604 // -- rax : value |
| 558 // -- rsp[0] : return address | 605 // -- rsp[0] : return address |
| 559 // -- rsp[8] : key | 606 // -- rsp[8] : key |
| 560 // -- rsp[16] : receiver | 607 // -- rsp[16] : receiver |
| 561 // ----------------------------------- | 608 // ----------------------------------- |
| 562 | 609 |
| 563 __ pop(rcx); | 610 __ pop(rcx); |
| 564 __ push(Operand(rsp, 1 * kPointerSize)); // receiver | 611 __ push(Operand(rsp, 1 * kPointerSize)); // receiver |
| 565 __ push(Operand(rsp, 1 * kPointerSize)); // key | 612 __ push(Operand(rsp, 1 * kPointerSize)); // key |
| 566 __ push(rax); // value | 613 __ push(rax); // value |
| 567 __ push(rcx); // return address | 614 __ push(rcx); // return address |
| 568 | 615 |
| 569 // Do tail-call to runtime routine. | 616 // Do tail-call to runtime routine. |
| 570 __ TailCallRuntime(f, 3, 1); | 617 __ TailCallRuntime(ExternalReference(IC_Utility(kKeyedStoreIC_Miss)), 3, 1); |
| 571 } | 618 } |
| 572 | 619 |
| 573 | 620 |
| 574 void KeyedStoreIC::GenerateExtendStorage(MacroAssembler* masm) { | 621 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { |
| 575 // ----------- S t a t e ------------- | 622 // ----------- S t a t e ------------- |
| 576 // -- rax : value | 623 // -- rax : value |
| 577 // -- rcx : transition map | |
| 578 // -- rsp[0] : return address | 624 // -- rsp[0] : return address |
| 579 // -- rsp[8] : key | 625 // -- rsp[8] : key |
| 580 // -- rsp[16] : receiver | 626 // -- rsp[16] : receiver |
| 581 // ----------------------------------- | 627 // ----------------------------------- |
| 582 | 628 |
| 583 __ pop(rbx); | 629 __ pop(rcx); |
| 584 __ push(Operand(rsp, 1 * kPointerSize)); // receiver | 630 __ push(Operand(rsp, 1 * kPointerSize)); // receiver |
| 585 __ push(rcx); // transition map | 631 __ push(Operand(rsp, 1 * kPointerSize)); // key |
| 586 __ push(rax); // value | 632 __ push(rax); // value |
| 587 __ push(rbx); // return address | 633 __ push(rcx); // return address |
| 588 | 634 |
| 589 // Do tail-call to runtime routine. | 635 // Do tail-call to runtime routine. |
| 590 __ TailCallRuntime( | 636 __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3, 1); |
| 591 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1); | |
| 592 } | 637 } |
| 593 | 638 |
| 594 | 639 |
| 595 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { | 640 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { |
| 596 // ----------- S t a t e ------------- | 641 // ----------- S t a t e ------------- |
| 597 // -- rax : value | 642 // -- rax : value |
| 598 // -- rsp[0] : return address | 643 // -- rsp[0] : return address |
| 599 // -- rsp[8] : key | 644 // -- rsp[8] : key |
| 600 // -- rsp[16] : receiver | 645 // -- rsp[16] : receiver |
| 601 // ----------------------------------- | 646 // ----------------------------------- |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 // Untag the key (for checking against untagged length in the fixed array). | 680 // Untag the key (for checking against untagged length in the fixed array). |
| 636 __ SmiToInteger32(rdx, rbx); | 681 __ SmiToInteger32(rdx, rbx); |
| 637 __ cmpl(rdx, FieldOperand(rcx, Array::kLengthOffset)); | 682 __ cmpl(rdx, FieldOperand(rcx, Array::kLengthOffset)); |
| 638 // rax: value | 683 // rax: value |
| 639 // rcx: FixedArray | 684 // rcx: FixedArray |
| 640 // rbx: index (as a smi) | 685 // rbx: index (as a smi) |
| 641 __ j(below, &fast); | 686 __ j(below, &fast); |
| 642 | 687 |
| 643 // Slow case: call runtime. | 688 // Slow case: call runtime. |
| 644 __ bind(&slow); | 689 __ bind(&slow); |
| 645 Generate(masm, ExternalReference(Runtime::kSetProperty)); | 690 GenerateRuntimeSetProperty(masm); |
| 646 | 691 |
| 647 // Check whether the elements is a pixel array. | 692 // Check whether the elements is a pixel array. |
| 648 // rax: value | 693 // rax: value |
| 649 // rcx: elements array | 694 // rcx: elements array |
| 650 // rbx: index (as a smi), zero-extended. | 695 // rbx: index (as a smi), zero-extended. |
| 651 __ bind(&check_pixel_array); | 696 __ bind(&check_pixel_array); |
| 652 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), | 697 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), |
| 653 Heap::kPixelArrayMapRootIndex); | 698 Heap::kPixelArrayMapRootIndex); |
| 654 __ j(not_equal, &slow); | 699 __ j(not_equal, &slow); |
| 655 // Check that the value is a smi. If a conversion is needed call into the | 700 // Check that the value is a smi. If a conversion is needed call into the |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 899 default: | 944 default: |
| 900 UNREACHABLE(); | 945 UNREACHABLE(); |
| 901 break; | 946 break; |
| 902 } | 947 } |
| 903 __ movq(rax, rdx); // Return the original value. | 948 __ movq(rax, rdx); // Return the original value. |
| 904 __ ret(0); | 949 __ ret(0); |
| 905 } | 950 } |
| 906 | 951 |
| 907 // Slow case: call runtime. | 952 // Slow case: call runtime. |
| 908 __ bind(&slow); | 953 __ bind(&slow); |
| 909 Generate(masm, ExternalReference(Runtime::kSetProperty)); | 954 GenerateRuntimeSetProperty(masm); |
| 910 } | 955 } |
| 911 | 956 |
| 912 | 957 |
| 913 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { | 958 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { |
| 959 // ----------- S t a t e ------------- |
| 960 // rcx : function name |
| 961 // rsp[0] : return address |
| 962 // rsp[8] : argument argc |
| 963 // rsp[16] : argument argc - 1 |
| 964 // ... |
| 965 // rsp[argc * 8] : argument 1 |
| 966 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 967 // ----------------------------------- |
| 914 // Get the receiver of the function from the stack; 1 ~ return address. | 968 // Get the receiver of the function from the stack; 1 ~ return address. |
| 915 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 969 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 916 // Get the name of the function to call from the stack. | |
| 917 // 2 ~ receiver, return address. | |
| 918 __ movq(rbx, Operand(rsp, (argc + 2) * kPointerSize)); | |
| 919 | 970 |
| 920 // Enter an internal frame. | 971 // Enter an internal frame. |
| 921 __ EnterInternalFrame(); | 972 __ EnterInternalFrame(); |
| 922 | 973 |
| 923 // Push the receiver and the name of the function. | 974 // Push the receiver and the name of the function. |
| 924 __ push(rdx); | 975 __ push(rdx); |
| 925 __ push(rbx); | 976 __ push(rcx); |
| 926 | 977 |
| 927 // Call the entry. | 978 // Call the entry. |
| 928 CEntryStub stub(1); | 979 CEntryStub stub(1); |
| 929 __ movq(rax, Immediate(2)); | 980 __ movq(rax, Immediate(2)); |
| 930 __ movq(rbx, ExternalReference(IC_Utility(kCallIC_Miss))); | 981 __ movq(rbx, ExternalReference(IC_Utility(kCallIC_Miss))); |
| 931 __ CallStub(&stub); | 982 __ CallStub(&stub); |
| 932 | 983 |
| 933 // Move result to rdi and exit the internal frame. | 984 // Move result to rdi and exit the internal frame. |
| 934 __ movq(rdi, rax); | 985 __ movq(rdi, rax); |
| 935 __ LeaveInternalFrame(); | 986 __ LeaveInternalFrame(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 953 __ bind(&invoke); | 1004 __ bind(&invoke); |
| 954 __ InvokeFunction(rdi, actual, JUMP_FUNCTION); | 1005 __ InvokeFunction(rdi, actual, JUMP_FUNCTION); |
| 955 } | 1006 } |
| 956 | 1007 |
| 957 | 1008 |
| 958 // Defined in ic.cc. | 1009 // Defined in ic.cc. |
| 959 Object* CallIC_Miss(Arguments args); | 1010 Object* CallIC_Miss(Arguments args); |
| 960 | 1011 |
| 961 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { | 1012 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { |
| 962 // ----------- S t a t e ------------- | 1013 // ----------- S t a t e ------------- |
| 963 // rsp[0] return address | 1014 // rcx : function name |
| 964 // rsp[8] argument argc | 1015 // rsp[0] : return address |
| 965 // rsp[16] argument argc - 1 | 1016 // rsp[8] : argument argc |
| 1017 // rsp[16] : argument argc - 1 |
| 966 // ... | 1018 // ... |
| 967 // rsp[argc * 8] argument 1 | 1019 // rsp[argc * 8] : argument 1 |
| 968 // rsp[(argc + 1) * 8] argument 0 = receiver | 1020 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 969 // rsp[(argc + 2) * 8] function name | |
| 970 // ----------------------------------- | 1021 // ----------------------------------- |
| 971 Label number, non_number, non_string, boolean, probe, miss; | 1022 Label number, non_number, non_string, boolean, probe, miss; |
| 972 | 1023 |
| 973 // Get the receiver of the function from the stack; 1 ~ return address. | 1024 // Get the receiver of the function from the stack; 1 ~ return address. |
| 974 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1025 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 975 // Get the name of the function from the stack; 2 ~ return address, receiver | |
| 976 __ movq(rcx, Operand(rsp, (argc + 2) * kPointerSize)); | |
| 977 | 1026 |
| 978 // Probe the stub cache. | 1027 // Probe the stub cache. |
| 979 Code::Flags flags = | 1028 Code::Flags flags = |
| 980 Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc); | 1029 Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc); |
| 981 StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, rax); | 1030 StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, rax); |
| 982 | 1031 |
| 983 // If the stub cache probing failed, the receiver might be a value. | 1032 // If the stub cache probing failed, the receiver might be a value. |
| 984 // For value objects, we use the map of the prototype objects for | 1033 // For value objects, we use the map of the prototype objects for |
| 985 // the corresponding JSValue for the cache and that is what we need | 1034 // the corresponding JSValue for the cache and that is what we need |
| 986 // to probe. | 1035 // to probe. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1019 // Cache miss: Jump to runtime. | 1068 // Cache miss: Jump to runtime. |
| 1020 __ bind(&miss); | 1069 __ bind(&miss); |
| 1021 GenerateMiss(masm, argc); | 1070 GenerateMiss(masm, argc); |
| 1022 } | 1071 } |
| 1023 | 1072 |
| 1024 | 1073 |
| 1025 static void GenerateNormalHelper(MacroAssembler* masm, | 1074 static void GenerateNormalHelper(MacroAssembler* masm, |
| 1026 int argc, | 1075 int argc, |
| 1027 bool is_global_object, | 1076 bool is_global_object, |
| 1028 Label* miss) { | 1077 Label* miss) { |
| 1078 // ----------- S t a t e ------------- |
| 1079 // rcx : function name |
| 1080 // rdx : receiver |
| 1081 // rsp[0] : return address |
| 1082 // rsp[8] : argument argc |
| 1083 // rsp[16] : argument argc - 1 |
| 1084 // ... |
| 1085 // rsp[argc * 8] : argument 1 |
| 1086 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1087 // ----------------------------------- |
| 1029 // Search dictionary - put result in register rdx. | 1088 // Search dictionary - put result in register rdx. |
| 1030 GenerateDictionaryLoad(masm, miss, rax, rdx, rbx, rcx, CHECK_DICTIONARY); | 1089 GenerateDictionaryLoad(masm, miss, rax, rdx, rbx, rcx, CHECK_DICTIONARY); |
| 1031 | 1090 |
| 1032 // Move the result to register rdi and check that it isn't a smi. | 1091 // Move the result to register rdi and check that it isn't a smi. |
| 1033 __ movq(rdi, rdx); | 1092 __ movq(rdi, rdx); |
| 1034 __ JumpIfSmi(rdx, miss); | 1093 __ JumpIfSmi(rdx, miss); |
| 1035 | 1094 |
| 1036 // Check that the value is a JavaScript function. | 1095 // Check that the value is a JavaScript function. |
| 1037 __ CmpObjectType(rdx, JS_FUNCTION_TYPE, rdx); | 1096 __ CmpObjectType(rdx, JS_FUNCTION_TYPE, rdx); |
| 1038 __ j(not_equal, miss); | 1097 __ j(not_equal, miss); |
| 1039 | 1098 |
| 1040 // Patch the receiver with the global proxy if necessary. | 1099 // Patch the receiver with the global proxy if necessary. |
| 1041 if (is_global_object) { | 1100 if (is_global_object) { |
| 1042 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1101 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1043 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 1102 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 1044 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 1103 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 1045 } | 1104 } |
| 1046 | 1105 |
| 1047 // Invoke the function. | 1106 // Invoke the function. |
| 1048 ParameterCount actual(argc); | 1107 ParameterCount actual(argc); |
| 1049 __ InvokeFunction(rdi, actual, JUMP_FUNCTION); | 1108 __ InvokeFunction(rdi, actual, JUMP_FUNCTION); |
| 1050 } | 1109 } |
| 1051 | 1110 |
| 1052 | 1111 |
| 1053 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { | 1112 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { |
| 1054 // ----------- S t a t e ------------- | 1113 // ----------- S t a t e ------------- |
| 1055 // rsp[0] return address | 1114 // rcx : function name |
| 1056 // rsp[8] argument argc | 1115 // rsp[0] : return address |
| 1057 // rsp[16] argument argc - 1 | 1116 // rsp[8] : argument argc |
| 1117 // rsp[16] : argument argc - 1 |
| 1058 // ... | 1118 // ... |
| 1059 // rsp[argc * 8] argument 1 | 1119 // rsp[argc * 8] : argument 1 |
| 1060 // rsp[(argc + 1) * 8] argument 0 = receiver | 1120 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1061 // rsp[(argc + 2) * 8] function name | |
| 1062 // ----------------------------------- | 1121 // ----------------------------------- |
| 1063 Label miss, global_object, non_global_object; | 1122 Label miss, global_object, non_global_object; |
| 1064 | 1123 |
| 1065 // Get the receiver of the function from the stack. | 1124 // Get the receiver of the function from the stack. |
| 1066 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1125 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1067 // Get the name of the function from the stack. | |
| 1068 __ movq(rcx, Operand(rsp, (argc + 2) * kPointerSize)); | |
| 1069 | 1126 |
| 1070 // Check that the receiver isn't a smi. | 1127 // Check that the receiver isn't a smi. |
| 1071 __ JumpIfSmi(rdx, &miss); | 1128 __ JumpIfSmi(rdx, &miss); |
| 1072 | 1129 |
| 1073 // Check that the receiver is a valid JS object. | 1130 // Check that the receiver is a valid JS object. |
| 1074 // Because there are so many map checks and type checks, do not | 1131 // Because there are so many map checks and type checks, do not |
| 1075 // use CmpObjectType, but load map and type into registers. | 1132 // use CmpObjectType, but load map and type into registers. |
| 1076 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); | 1133 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); |
| 1077 __ movb(rax, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 1134 __ movb(rax, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
| 1078 __ cmpb(rax, Immediate(FIRST_JS_OBJECT_TYPE)); | 1135 __ cmpb(rax, Immediate(FIRST_JS_OBJECT_TYPE)); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1125 | 1182 |
| 1126 | 1183 |
| 1127 void LoadIC::ClearInlinedVersion(Address address) { | 1184 void LoadIC::ClearInlinedVersion(Address address) { |
| 1128 // Reset the map check of the inlined inobject property load (if | 1185 // Reset the map check of the inlined inobject property load (if |
| 1129 // present) to guarantee failure by holding an invalid map (the null | 1186 // present) to guarantee failure by holding an invalid map (the null |
| 1130 // value). The offset can be patched to anything. | 1187 // value). The offset can be patched to anything. |
| 1131 PatchInlinedLoad(address, Heap::null_value(), kMaxInt); | 1188 PatchInlinedLoad(address, Heap::null_value(), kMaxInt); |
| 1132 } | 1189 } |
| 1133 | 1190 |
| 1134 | 1191 |
| 1135 void LoadIC::Generate(MacroAssembler* masm, ExternalReference const& f) { | 1192 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
| 1136 // ----------- S t a t e ------------- | 1193 // ----------- S t a t e ------------- |
| 1137 // -- rcx : name | 1194 // -- rcx : name |
| 1138 // -- rsp[0] : return address | 1195 // -- rsp[0] : return address |
| 1139 // -- rsp[8] : receiver | 1196 // -- rsp[8] : receiver |
| 1140 // ----------------------------------- | 1197 // ----------------------------------- |
| 1141 | 1198 |
| 1142 __ movq(rax, Operand(rsp, kPointerSize)); | |
| 1143 | |
| 1144 __ pop(rbx); | 1199 __ pop(rbx); |
| 1145 __ push(rax); // receiver | 1200 __ push(Operand(rsp, 0)); // receiver |
| 1146 __ push(rcx); // name | 1201 __ push(rcx); // name |
| 1147 __ push(rbx); // return address | 1202 __ push(rbx); // return address |
| 1148 | 1203 |
| 1149 // Perform tail call to the entry. | 1204 // Perform tail call to the entry. |
| 1150 __ TailCallRuntime(f, 2, 1); | 1205 __ TailCallRuntime(ExternalReference(IC_Utility(kLoadIC_Miss)), 2, 1); |
| 1151 } | 1206 } |
| 1152 | 1207 |
| 1153 | 1208 |
| 1154 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { | 1209 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { |
| 1155 // ----------- S t a t e ------------- | 1210 // ----------- S t a t e ------------- |
| 1156 // -- rcx : name | 1211 // -- rcx : name |
| 1157 // -- rsp[0] : return address | 1212 // -- rsp[0] : return address |
| 1158 // -- rsp[8] : receiver | 1213 // -- rsp[8] : receiver |
| 1159 // ----------------------------------- | 1214 // ----------------------------------- |
| 1160 Label miss; | 1215 Label miss; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1196 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, | 1251 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, |
| 1197 NOT_IN_LOOP, | 1252 NOT_IN_LOOP, |
| 1198 MONOMORPHIC); | 1253 MONOMORPHIC); |
| 1199 StubCache::GenerateProbe(masm, flags, rax, rcx, rbx, rdx); | 1254 StubCache::GenerateProbe(masm, flags, rax, rcx, rbx, rdx); |
| 1200 | 1255 |
| 1201 // Cache miss: Jump to runtime. | 1256 // Cache miss: Jump to runtime. |
| 1202 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | 1257 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
| 1203 } | 1258 } |
| 1204 | 1259 |
| 1205 | 1260 |
| 1206 void LoadIC::GenerateMiss(MacroAssembler* masm) { | |
| 1207 // ----------- S t a t e ------------- | |
| 1208 // -- rcx : name | |
| 1209 // -- rsp[0] : return address | |
| 1210 // -- rsp[8] : receiver | |
| 1211 // ----------------------------------- | |
| 1212 | |
| 1213 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss))); | |
| 1214 } | |
| 1215 | |
| 1216 | |
| 1217 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 1261 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
| 1218 // ----------- S t a t e ------------- | 1262 // ----------- S t a t e ------------- |
| 1219 // -- rcx : name | 1263 // -- rcx : name |
| 1220 // -- rsp[0] : return address | 1264 // -- rsp[0] : return address |
| 1221 // -- rsp[8] : receiver | 1265 // -- rsp[8] : receiver |
| 1222 // ----------------------------------- | 1266 // ----------------------------------- |
| 1223 Label miss, probe, global; | 1267 Label miss, probe, global; |
| 1224 | 1268 |
| 1225 __ movq(rax, Operand(rsp, kPointerSize)); | 1269 __ movq(rax, Operand(rsp, kPointerSize)); |
| 1226 | 1270 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1249 __ ret(0); | 1293 __ ret(0); |
| 1250 | 1294 |
| 1251 // Global object access: Check access rights. | 1295 // Global object access: Check access rights. |
| 1252 __ bind(&global); | 1296 __ bind(&global); |
| 1253 __ CheckAccessGlobalProxy(rax, rdx, &miss); | 1297 __ CheckAccessGlobalProxy(rax, rdx, &miss); |
| 1254 __ jmp(&probe); | 1298 __ jmp(&probe); |
| 1255 | 1299 |
| 1256 // Cache miss: Restore receiver from stack and jump to runtime. | 1300 // Cache miss: Restore receiver from stack and jump to runtime. |
| 1257 __ bind(&miss); | 1301 __ bind(&miss); |
| 1258 __ movq(rax, Operand(rsp, 1 * kPointerSize)); | 1302 __ movq(rax, Operand(rsp, 1 * kPointerSize)); |
| 1259 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss))); | 1303 GenerateMiss(masm); |
| 1260 } | 1304 } |
| 1261 | 1305 |
| 1262 | 1306 |
| 1263 void LoadIC::GenerateStringLength(MacroAssembler* masm) { | 1307 void LoadIC::GenerateStringLength(MacroAssembler* masm) { |
| 1264 // ----------- S t a t e ------------- | 1308 // ----------- S t a t e ------------- |
| 1265 // -- rcx : name | 1309 // -- rcx : name |
| 1266 // -- rsp[0] : return address | 1310 // -- rsp[0] : return address |
| 1267 // -- rsp[8] : receiver | 1311 // -- rsp[8] : receiver |
| 1268 // ----------------------------------- | 1312 // ----------------------------------- |
| 1269 Label miss; | 1313 Label miss; |
| 1270 | 1314 |
| 1271 __ movq(rax, Operand(rsp, kPointerSize)); | 1315 __ movq(rax, Operand(rsp, kPointerSize)); |
| 1272 | 1316 |
| 1273 StubCompiler::GenerateLoadStringLength(masm, rax, rdx, &miss); | 1317 StubCompiler::GenerateLoadStringLength(masm, rax, rdx, rbx, &miss); |
| 1274 __ bind(&miss); | 1318 __ bind(&miss); |
| 1275 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | 1319 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
| 1276 } | 1320 } |
| 1277 | 1321 |
| 1278 | 1322 |
| 1279 | |
| 1280 bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { | 1323 bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { |
| 1281 // The address of the instruction following the call. | 1324 // The address of the instruction following the call. |
| 1282 Address test_instruction_address = | 1325 Address test_instruction_address = |
| 1283 address + Assembler::kCallTargetAddressOffset; | 1326 address + Assembler::kCallTargetAddressOffset; |
| 1284 // If the instruction following the call is not a test eax, nothing | 1327 // If the instruction following the call is not a test eax, nothing |
| 1285 // was inlined. | 1328 // was inlined. |
| 1286 if (*test_instruction_address != kTestEaxByte) return false; | 1329 if (*test_instruction_address != kTestEaxByte) return false; |
| 1287 | 1330 |
| 1288 Address delta_address = test_instruction_address + 1; | 1331 Address delta_address = test_instruction_address + 1; |
| 1289 // The delta to the start of the map check instruction. | 1332 // The delta to the start of the map check instruction. |
| 1290 int delta = *reinterpret_cast<int*>(delta_address); | 1333 int delta = *reinterpret_cast<int*>(delta_address); |
| 1291 | 1334 |
| 1292 // The map address is the last 8 bytes of the 10-byte | 1335 // The map address is the last 8 bytes of the 10-byte |
| 1293 // immediate move instruction, so we add 2 to get the | 1336 // immediate move instruction, so we add 2 to get the |
| 1294 // offset to the last 8 bytes. | 1337 // offset to the last 8 bytes. |
| 1295 Address map_address = test_instruction_address + delta + 2; | 1338 Address map_address = test_instruction_address + delta + 2; |
| 1296 *(reinterpret_cast<Object**>(map_address)) = map; | 1339 *(reinterpret_cast<Object**>(map_address)) = map; |
| 1297 | 1340 |
| 1298 // The offset is in the 32-bit displacement of a seven byte | 1341 // The offset is in the 32-bit displacement of a seven byte |
| 1299 // memory-to-register move instruction (REX.W 0x88 ModR/M disp32), | 1342 // memory-to-register move instruction (REX.W 0x88 ModR/M disp32), |
| 1300 // so we add 3 to get the offset of the displacement. | 1343 // so we add 3 to get the offset of the displacement. |
| 1301 Address offset_address = | 1344 Address offset_address = |
| 1302 test_instruction_address + delta + kOffsetToLoadInstruction + 3; | 1345 test_instruction_address + delta + kOffsetToLoadInstruction + 3; |
| 1303 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; | 1346 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; |
| 1304 return true; | 1347 return true; |
| 1305 } | 1348 } |
| 1306 | 1349 |
| 1350 |
| 1307 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 1351 void StoreIC::GenerateMiss(MacroAssembler* masm) { |
| 1308 // ----------- S t a t e ------------- | 1352 // ----------- S t a t e ------------- |
| 1309 // -- rax : value | 1353 // -- rax : value |
| 1310 // -- rcx : name | 1354 // -- rcx : name |
| 1311 // -- rdx : receiver | 1355 // -- rdx : receiver |
| 1312 // -- rsp[0] : return address | 1356 // -- rsp[0] : return address |
| 1313 // ----------------------------------- | 1357 // ----------------------------------- |
| 1314 | 1358 |
| 1315 __ pop(rbx); | 1359 __ pop(rbx); |
| 1316 __ push(rdx); // receiver | 1360 __ push(rdx); // receiver |
| 1317 __ push(rcx); // name | 1361 __ push(rcx); // name |
| 1318 __ push(rax); // value | 1362 __ push(rax); // value |
| 1319 __ push(rbx); // return address | 1363 __ push(rbx); // return address |
| 1320 | 1364 |
| 1321 // Perform tail call to the entry. | 1365 // Perform tail call to the entry. |
| 1322 __ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_Miss)), 3, 1); | 1366 __ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_Miss)), 3, 1); |
| 1323 } | 1367 } |
| 1324 | 1368 |
| 1325 void StoreIC::GenerateExtendStorage(MacroAssembler* masm) { | |
| 1326 // ----------- S t a t e ------------- | |
| 1327 // -- rax : value | |
| 1328 // -- rcx : Map (target of map transition) | |
| 1329 // -- rdx : receiver | |
| 1330 // -- rsp[0] : return address | |
| 1331 // ----------------------------------- | |
| 1332 | |
| 1333 __ pop(rbx); | |
| 1334 __ push(rdx); // receiver | |
| 1335 __ push(rcx); // transition map | |
| 1336 __ push(rax); // value | |
| 1337 __ push(rbx); // return address | |
| 1338 | |
| 1339 // Perform tail call to the entry. | |
| 1340 __ TailCallRuntime( | |
| 1341 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1); | |
| 1342 } | |
| 1343 | 1369 |
| 1344 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { | 1370 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 1345 // ----------- S t a t e ------------- | 1371 // ----------- S t a t e ------------- |
| 1346 // -- rax : value | 1372 // -- rax : value |
| 1347 // -- rcx : name | 1373 // -- rcx : name |
| 1348 // -- rdx : receiver | 1374 // -- rdx : receiver |
| 1349 // -- rsp[0] : return address | 1375 // -- rsp[0] : return address |
| 1350 // ----------------------------------- | 1376 // ----------------------------------- |
| 1351 | 1377 |
| 1352 // Get the receiver from the stack and probe the stub cache. | 1378 // Get the receiver from the stack and probe the stub cache. |
| 1353 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, | 1379 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, |
| 1354 NOT_IN_LOOP, | 1380 NOT_IN_LOOP, |
| 1355 MONOMORPHIC); | 1381 MONOMORPHIC); |
| 1356 StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, no_reg); | 1382 StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, no_reg); |
| 1357 | 1383 |
| 1358 // Cache miss: Jump to runtime. | 1384 // Cache miss: Jump to runtime. |
| 1359 GenerateMiss(masm); | 1385 GenerateMiss(masm); |
| 1360 } | 1386 } |
| 1361 | 1387 |
| 1388 |
| 1389 void StoreIC::GenerateArrayLength(MacroAssembler* masm) { |
| 1390 // ----------- S t a t e ------------- |
| 1391 // -- rax : value |
| 1392 // -- rcx : name |
| 1393 // -- rdx : receiver |
| 1394 // -- rsp[0] : return address |
| 1395 // ----------------------------------- |
| 1396 // |
| 1397 // This accepts as a receiver anything JSObject::SetElementsLength accepts |
| 1398 // (currently anything except for external and pixel arrays which means |
| 1399 // anything with elements of FixedArray type.), but currently is restricted |
| 1400 // to JSArray. |
| 1401 // Value must be a number, but only smis are accepted as the most common case. |
| 1402 |
| 1403 Label miss; |
| 1404 |
| 1405 Register receiver = rdx; |
| 1406 Register value = rax; |
| 1407 Register scratch = rbx; |
| 1408 |
| 1409 // Check that the receiver isn't a smi. |
| 1410 __ JumpIfSmi(receiver, &miss); |
| 1411 |
| 1412 // Check that the object is a JS array. |
| 1413 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); |
| 1414 __ j(not_equal, &miss); |
| 1415 |
| 1416 // Check that elements are FixedArray. |
| 1417 __ movq(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); |
| 1418 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); |
| 1419 __ j(not_equal, &miss); |
| 1420 |
| 1421 // Check that value is a smi. |
| 1422 __ JumpIfNotSmi(value, &miss); |
| 1423 |
| 1424 // Prepare tail call to StoreIC_ArrayLength. |
| 1425 __ pop(scratch); |
| 1426 __ push(receiver); |
| 1427 __ push(value); |
| 1428 __ push(scratch); // return address |
| 1429 |
| 1430 __ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_ArrayLength)), 2, 1); |
| 1431 |
| 1432 __ bind(&miss); |
| 1433 |
| 1434 GenerateMiss(masm); |
| 1435 } |
| 1436 |
| 1362 | 1437 |
| 1363 #undef __ | 1438 #undef __ |
| 1364 | 1439 |
| 1365 | 1440 |
| 1366 } } // namespace v8::internal | 1441 } } // namespace v8::internal |
| OLD | NEW |