OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 |
11 // with the distribution. | 11 // with the distribution. |
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 } else { | 480 } else { |
481 push(scratch1); | 481 push(scratch1); |
482 fild_s(Operand(esp, 0)); | 482 fild_s(Operand(esp, 0)); |
483 pop(scratch1); | 483 pop(scratch1); |
484 fstp_d(FieldOperand(elements, key, times_4, FixedDoubleArray::kHeaderSize)); | 484 fstp_d(FieldOperand(elements, key, times_4, FixedDoubleArray::kHeaderSize)); |
485 } | 485 } |
486 bind(&done); | 486 bind(&done); |
487 } | 487 } |
488 | 488 |
489 | 489 |
| 490 void MacroAssembler::CompareMap(Register obj, |
| 491 Handle<Map> map, |
| 492 Label* early_success, |
| 493 CompareMapMode mode) { |
| 494 cmp(FieldOperand(obj, HeapObject::kMapOffset), map); |
| 495 if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) { |
| 496 Map* transitioned_fast_element_map( |
| 497 map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL)); |
| 498 ASSERT(transitioned_fast_element_map == NULL || |
| 499 map->elements_kind() != FAST_ELEMENTS); |
| 500 if (transitioned_fast_element_map != NULL) { |
| 501 j(equal, early_success, Label::kNear); |
| 502 cmp(FieldOperand(obj, HeapObject::kMapOffset), |
| 503 Handle<Map>(transitioned_fast_element_map)); |
| 504 } |
| 505 |
| 506 Map* transitioned_double_map( |
| 507 map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL)); |
| 508 ASSERT(transitioned_double_map == NULL || |
| 509 map->elements_kind() == FAST_SMI_ONLY_ELEMENTS); |
| 510 if (transitioned_double_map != NULL) { |
| 511 j(equal, early_success, Label::kNear); |
| 512 cmp(FieldOperand(obj, HeapObject::kMapOffset), |
| 513 Handle<Map>(transitioned_double_map)); |
| 514 } |
| 515 } |
| 516 } |
| 517 |
| 518 |
490 void MacroAssembler::CheckMap(Register obj, | 519 void MacroAssembler::CheckMap(Register obj, |
491 Handle<Map> map, | 520 Handle<Map> map, |
492 Label* fail, | 521 Label* fail, |
493 SmiCheckType smi_check_type) { | 522 SmiCheckType smi_check_type, |
| 523 CompareMapMode mode) { |
494 if (smi_check_type == DO_SMI_CHECK) { | 524 if (smi_check_type == DO_SMI_CHECK) { |
495 JumpIfSmi(obj, fail); | 525 JumpIfSmi(obj, fail); |
496 } | 526 } |
497 cmp(FieldOperand(obj, HeapObject::kMapOffset), Immediate(map)); | 527 |
| 528 Label success; |
| 529 CompareMap(obj, map, &success, mode); |
498 j(not_equal, fail); | 530 j(not_equal, fail); |
| 531 bind(&success); |
499 } | 532 } |
500 | 533 |
501 | 534 |
502 void MacroAssembler::DispatchMap(Register obj, | 535 void MacroAssembler::DispatchMap(Register obj, |
503 Handle<Map> map, | 536 Handle<Map> map, |
504 Handle<Code> success, | 537 Handle<Code> success, |
505 SmiCheckType smi_check_type) { | 538 SmiCheckType smi_check_type) { |
506 Label fail; | 539 Label fail; |
507 if (smi_check_type == DO_SMI_CHECK) { | 540 if (smi_check_type == DO_SMI_CHECK) { |
508 JumpIfSmi(obj, &fail); | 541 JumpIfSmi(obj, &fail); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
609 if (emit_debug_code()) { | 642 if (emit_debug_code()) { |
610 cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), | 643 cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), |
611 Immediate(Smi::FromInt(type))); | 644 Immediate(Smi::FromInt(type))); |
612 Check(equal, "stack frame types must match"); | 645 Check(equal, "stack frame types must match"); |
613 } | 646 } |
614 leave(); | 647 leave(); |
615 } | 648 } |
616 | 649 |
617 | 650 |
618 void MacroAssembler::EnterExitFramePrologue() { | 651 void MacroAssembler::EnterExitFramePrologue() { |
619 // Setup the frame structure on the stack. | 652 // Set up the frame structure on the stack. |
620 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); | 653 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); |
621 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); | 654 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); |
622 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); | 655 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); |
623 push(ebp); | 656 push(ebp); |
624 mov(ebp, esp); | 657 mov(ebp, esp); |
625 | 658 |
626 // Reserve room for entry stack pointer and push the code object. | 659 // Reserve room for entry stack pointer and push the code object. |
627 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); | 660 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); |
628 push(Immediate(0)); // Saved entry sp, patched before call. | 661 push(Immediate(0)); // Saved entry sp, patched before call. |
629 push(Immediate(CodeObject())); // Accessed from ExitFrame::code_slot. | 662 push(Immediate(CodeObject())); // Accessed from ExitFrame::code_slot. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
661 } | 694 } |
662 | 695 |
663 // Patch the saved entry sp. | 696 // Patch the saved entry sp. |
664 mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp); | 697 mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp); |
665 } | 698 } |
666 | 699 |
667 | 700 |
668 void MacroAssembler::EnterExitFrame(bool save_doubles) { | 701 void MacroAssembler::EnterExitFrame(bool save_doubles) { |
669 EnterExitFramePrologue(); | 702 EnterExitFramePrologue(); |
670 | 703 |
671 // Setup argc and argv in callee-saved registers. | 704 // Set up argc and argv in callee-saved registers. |
672 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; | 705 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; |
673 mov(edi, eax); | 706 mov(edi, eax); |
674 lea(esi, Operand(ebp, eax, times_4, offset)); | 707 lea(esi, Operand(ebp, eax, times_4, offset)); |
675 | 708 |
676 // Reserve space for argc, argv and isolate. | 709 // Reserve space for argc, argv and isolate. |
677 EnterExitFrameEpilogue(3, save_doubles); | 710 EnterExitFrameEpilogue(3, save_doubles); |
678 } | 711 } |
679 | 712 |
680 | 713 |
681 void MacroAssembler::EnterApiExitFrame(int argc) { | 714 void MacroAssembler::EnterApiExitFrame(int argc) { |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
952 Context::SECURITY_TOKEN_INDEX * kPointerSize; | 985 Context::SECURITY_TOKEN_INDEX * kPointerSize; |
953 mov(scratch, FieldOperand(scratch, token_offset)); | 986 mov(scratch, FieldOperand(scratch, token_offset)); |
954 cmp(scratch, FieldOperand(holder_reg, token_offset)); | 987 cmp(scratch, FieldOperand(holder_reg, token_offset)); |
955 pop(holder_reg); | 988 pop(holder_reg); |
956 j(not_equal, miss); | 989 j(not_equal, miss); |
957 | 990 |
958 bind(&same_contexts); | 991 bind(&same_contexts); |
959 } | 992 } |
960 | 993 |
961 | 994 |
| 995 // Compute the hash code from the untagged key. This must be kept in sync |
| 996 // with ComputeIntegerHash in utils.h. |
| 997 // |
| 998 // Note: r0 will contain hash code |
| 999 void MacroAssembler::GetNumberHash(Register r0, Register scratch) { |
| 1000 // Xor original key with a seed. |
| 1001 if (Serializer::enabled()) { |
| 1002 ExternalReference roots_array_start = |
| 1003 ExternalReference::roots_array_start(isolate()); |
| 1004 mov(scratch, Immediate(Heap::kHashSeedRootIndex)); |
| 1005 mov(scratch, |
| 1006 Operand::StaticArray(scratch, times_pointer_size, roots_array_start)); |
| 1007 SmiUntag(scratch); |
| 1008 xor_(r0, scratch); |
| 1009 } else { |
| 1010 int32_t seed = isolate()->heap()->HashSeed(); |
| 1011 xor_(r0, Immediate(seed)); |
| 1012 } |
| 1013 |
| 1014 // hash = ~hash + (hash << 15); |
| 1015 mov(scratch, r0); |
| 1016 not_(r0); |
| 1017 shl(scratch, 15); |
| 1018 add(r0, scratch); |
| 1019 // hash = hash ^ (hash >> 12); |
| 1020 mov(scratch, r0); |
| 1021 shr(scratch, 12); |
| 1022 xor_(r0, scratch); |
| 1023 // hash = hash + (hash << 2); |
| 1024 lea(r0, Operand(r0, r0, times_4, 0)); |
| 1025 // hash = hash ^ (hash >> 4); |
| 1026 mov(scratch, r0); |
| 1027 shr(scratch, 4); |
| 1028 xor_(r0, scratch); |
| 1029 // hash = hash * 2057; |
| 1030 imul(r0, r0, 2057); |
| 1031 // hash = hash ^ (hash >> 16); |
| 1032 mov(scratch, r0); |
| 1033 shr(scratch, 16); |
| 1034 xor_(r0, scratch); |
| 1035 } |
| 1036 |
| 1037 |
| 1038 |
962 void MacroAssembler::LoadFromNumberDictionary(Label* miss, | 1039 void MacroAssembler::LoadFromNumberDictionary(Label* miss, |
963 Register elements, | 1040 Register elements, |
964 Register key, | 1041 Register key, |
965 Register r0, | 1042 Register r0, |
966 Register r1, | 1043 Register r1, |
967 Register r2, | 1044 Register r2, |
968 Register result) { | 1045 Register result) { |
969 // Register use: | 1046 // Register use: |
970 // | 1047 // |
971 // elements - holds the slow-case elements of the receiver and is unchanged. | 1048 // elements - holds the slow-case elements of the receiver and is unchanged. |
972 // | 1049 // |
973 // key - holds the smi key on entry and is unchanged. | 1050 // key - holds the smi key on entry and is unchanged. |
974 // | 1051 // |
975 // Scratch registers: | 1052 // Scratch registers: |
976 // | 1053 // |
977 // r0 - holds the untagged key on entry and holds the hash once computed. | 1054 // r0 - holds the untagged key on entry and holds the hash once computed. |
978 // | 1055 // |
979 // r1 - used to hold the capacity mask of the dictionary | 1056 // r1 - used to hold the capacity mask of the dictionary |
980 // | 1057 // |
981 // r2 - used for the index into the dictionary. | 1058 // r2 - used for the index into the dictionary. |
982 // | 1059 // |
983 // result - holds the result on exit if the load succeeds and we fall through. | 1060 // result - holds the result on exit if the load succeeds and we fall through. |
984 | 1061 |
985 Label done; | 1062 Label done; |
986 | 1063 |
987 // Compute the hash code from the untagged key. This must be kept in sync | 1064 GetNumberHash(r0, r1); |
988 // with ComputeIntegerHash in utils.h. | |
989 // | |
990 // hash = ~hash + (hash << 15); | |
991 mov(r1, r0); | |
992 not_(r0); | |
993 shl(r1, 15); | |
994 add(r0, r1); | |
995 // hash = hash ^ (hash >> 12); | |
996 mov(r1, r0); | |
997 shr(r1, 12); | |
998 xor_(r0, r1); | |
999 // hash = hash + (hash << 2); | |
1000 lea(r0, Operand(r0, r0, times_4, 0)); | |
1001 // hash = hash ^ (hash >> 4); | |
1002 mov(r1, r0); | |
1003 shr(r1, 4); | |
1004 xor_(r0, r1); | |
1005 // hash = hash * 2057; | |
1006 imul(r0, r0, 2057); | |
1007 // hash = hash ^ (hash >> 16); | |
1008 mov(r1, r0); | |
1009 shr(r1, 16); | |
1010 xor_(r0, r1); | |
1011 | 1065 |
1012 // Compute capacity mask. | 1066 // Compute capacity mask. |
1013 mov(r1, FieldOperand(elements, NumberDictionary::kCapacityOffset)); | 1067 mov(r1, FieldOperand(elements, SeededNumberDictionary::kCapacityOffset)); |
1014 shr(r1, kSmiTagSize); // convert smi to int | 1068 shr(r1, kSmiTagSize); // convert smi to int |
1015 dec(r1); | 1069 dec(r1); |
1016 | 1070 |
1017 // Generate an unrolled loop that performs a few probes before giving up. | 1071 // Generate an unrolled loop that performs a few probes before giving up. |
1018 const int kProbes = 4; | 1072 const int kProbes = 4; |
1019 for (int i = 0; i < kProbes; i++) { | 1073 for (int i = 0; i < kProbes; i++) { |
1020 // Use r2 for index calculations and keep the hash intact in r0. | 1074 // Use r2 for index calculations and keep the hash intact in r0. |
1021 mov(r2, r0); | 1075 mov(r2, r0); |
1022 // Compute the masked index: (hash + i + i * i) & mask. | 1076 // Compute the masked index: (hash + i + i * i) & mask. |
1023 if (i > 0) { | 1077 if (i > 0) { |
1024 add(r2, Immediate(NumberDictionary::GetProbeOffset(i))); | 1078 add(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i))); |
1025 } | 1079 } |
1026 and_(r2, r1); | 1080 and_(r2, r1); |
1027 | 1081 |
1028 // Scale the index by multiplying by the entry size. | 1082 // Scale the index by multiplying by the entry size. |
1029 ASSERT(NumberDictionary::kEntrySize == 3); | 1083 ASSERT(SeededNumberDictionary::kEntrySize == 3); |
1030 lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 | 1084 lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 |
1031 | 1085 |
1032 // Check if the key matches. | 1086 // Check if the key matches. |
1033 cmp(key, FieldOperand(elements, | 1087 cmp(key, FieldOperand(elements, |
1034 r2, | 1088 r2, |
1035 times_pointer_size, | 1089 times_pointer_size, |
1036 NumberDictionary::kElementsStartOffset)); | 1090 SeededNumberDictionary::kElementsStartOffset)); |
1037 if (i != (kProbes - 1)) { | 1091 if (i != (kProbes - 1)) { |
1038 j(equal, &done); | 1092 j(equal, &done); |
1039 } else { | 1093 } else { |
1040 j(not_equal, miss); | 1094 j(not_equal, miss); |
1041 } | 1095 } |
1042 } | 1096 } |
1043 | 1097 |
1044 bind(&done); | 1098 bind(&done); |
1045 // Check that the value is a normal propety. | 1099 // Check that the value is a normal propety. |
1046 const int kDetailsOffset = | 1100 const int kDetailsOffset = |
1047 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; | 1101 SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; |
1048 ASSERT_EQ(NORMAL, 0); | 1102 ASSERT_EQ(NORMAL, 0); |
1049 test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), | 1103 test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), |
1050 Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize)); | 1104 Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize)); |
1051 j(not_zero, miss); | 1105 j(not_zero, miss); |
1052 | 1106 |
1053 // Get the value at the masked, scaled index. | 1107 // Get the value at the masked, scaled index. |
1054 const int kValueOffset = | 1108 const int kValueOffset = |
1055 NumberDictionary::kElementsStartOffset + kPointerSize; | 1109 SeededNumberDictionary::kElementsStartOffset + kPointerSize; |
1056 mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); | 1110 mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); |
1057 } | 1111 } |
1058 | 1112 |
1059 | 1113 |
1060 void MacroAssembler::LoadAllocationTopHelper(Register result, | 1114 void MacroAssembler::LoadAllocationTopHelper(Register result, |
1061 Register scratch, | 1115 Register scratch, |
1062 AllocationFlags flags) { | 1116 AllocationFlags flags) { |
1063 ExternalReference new_space_allocation_top = | 1117 ExternalReference new_space_allocation_top = |
1064 ExternalReference::new_space_allocation_top_address(isolate()); | 1118 ExternalReference::new_space_allocation_top_address(isolate()); |
1065 | 1119 |
(...skipping 1619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2685 cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset)); | 2739 cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset)); |
2686 Check(less_equal, "Live Bytes Count overflow chunk size"); | 2740 Check(less_equal, "Live Bytes Count overflow chunk size"); |
2687 } | 2741 } |
2688 | 2742 |
2689 bind(&done); | 2743 bind(&done); |
2690 } | 2744 } |
2691 | 2745 |
2692 } } // namespace v8::internal | 2746 } } // namespace v8::internal |
2693 | 2747 |
2694 #endif // V8_TARGET_ARCH_IA32 | 2748 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |