| 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 |