OLD | NEW |
---|---|
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
2 // All Rights Reserved. | 2 // All Rights Reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions |
6 // are met: | 6 // are met: |
7 // | 7 // |
8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
10 // | 10 // |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
222 bool RelocInfo::IsCodedSpecially() { | 222 bool RelocInfo::IsCodedSpecially() { |
223 // The deserializer needs to know whether a pointer is specially coded. Being | 223 // The deserializer needs to know whether a pointer is specially coded. Being |
224 // specially coded on ARM means that it is a movw/movt instruction, or is an | 224 // specially coded on ARM means that it is a movw/movt instruction, or is an |
225 // out of line constant pool entry. These only occur if | 225 // out of line constant pool entry. These only occur if |
226 // FLAG_enable_ool_constant_pool is true. | 226 // FLAG_enable_ool_constant_pool is true. |
227 return FLAG_enable_ool_constant_pool; | 227 return FLAG_enable_ool_constant_pool; |
228 } | 228 } |
229 | 229 |
230 | 230 |
231 bool RelocInfo::IsInConstantPool() { | 231 bool RelocInfo::IsInConstantPool() { |
232 if (FLAG_enable_ool_constant_pool) { | 232 return Assembler::is_constant_pool_load(pc_); |
233 return Assembler::IsLdrPpImmediateOffset(Memory::int32_at(pc_)); | |
234 } else { | |
235 return Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc_)); | |
236 } | |
237 } | 233 } |
238 | 234 |
239 | 235 |
240 void RelocInfo::PatchCode(byte* instructions, int instruction_count) { | 236 void RelocInfo::PatchCode(byte* instructions, int instruction_count) { |
241 // Patch the code at the current address with the supplied instructions. | 237 // Patch the code at the current address with the supplied instructions. |
242 Instr* pc = reinterpret_cast<Instr*>(pc_); | 238 Instr* pc = reinterpret_cast<Instr*>(pc_); |
243 Instr* instr = reinterpret_cast<Instr*>(instructions); | 239 Instr* instr = reinterpret_cast<Instr*>(instructions); |
244 for (int i = 0; i < instruction_count; i++) { | 240 for (int i = 0; i < instruction_count; i++) { |
245 *(pc + i) = *(instr + i); | 241 *(pc + i) = *(instr + i); |
246 } | 242 } |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
407 // ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r)) | 403 // ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r)) |
408 // register r is not encoded. | 404 // register r is not encoded. |
409 const Instr kPopRegPattern = | 405 const Instr kPopRegPattern = |
410 al | B26 | L | 4 | PostIndex | kRegister_sp_Code * B16; | 406 al | B26 | L | 4 | PostIndex | kRegister_sp_Code * B16; |
411 // ldr rd, [pc, #offset] | 407 // ldr rd, [pc, #offset] |
412 const Instr kLdrPCImmedMask = 15 * B24 | 7 * B20 | 15 * B16; | 408 const Instr kLdrPCImmedMask = 15 * B24 | 7 * B20 | 15 * B16; |
413 const Instr kLdrPCImmedPattern = 5 * B24 | L | kRegister_pc_Code * B16; | 409 const Instr kLdrPCImmedPattern = 5 * B24 | L | kRegister_pc_Code * B16; |
414 // ldr rd, [pp, #offset] | 410 // ldr rd, [pp, #offset] |
415 const Instr kLdrPpImmedMask = 15 * B24 | 7 * B20 | 15 * B16; | 411 const Instr kLdrPpImmedMask = 15 * B24 | 7 * B20 | 15 * B16; |
416 const Instr kLdrPpImmedPattern = 5 * B24 | L | kRegister_r8_Code * B16; | 412 const Instr kLdrPpImmedPattern = 5 * B24 | L | kRegister_r8_Code * B16; |
413 // ldr rd, [pp, rn] | |
414 const Instr kLdrPpRegMask = 15 * B24 | 7 * B20 | 15 * B16; | |
415 const Instr kLdrPpRegPattern = 7 * B24 | L | kRegister_r8_Code * B16; | |
417 // vldr dd, [pc, #offset] | 416 // vldr dd, [pc, #offset] |
418 const Instr kVldrDPCMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8; | 417 const Instr kVldrDPCMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8; |
419 const Instr kVldrDPCPattern = 13 * B24 | L | kRegister_pc_Code * B16 | 11 * B8; | 418 const Instr kVldrDPCPattern = 13 * B24 | L | kRegister_pc_Code * B16 | 11 * B8; |
420 // vldr dd, [pp, #offset] | 419 // vldr dd, [pp, #offset] |
421 const Instr kVldrDPpMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8; | 420 const Instr kVldrDPpMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8; |
422 const Instr kVldrDPpPattern = 13 * B24 | L | kRegister_r8_Code * B16 | 11 * B8; | 421 const Instr kVldrDPpPattern = 13 * B24 | L | kRegister_r8_Code * B16 | 11 * B8; |
423 // blxcc rm | 422 // blxcc rm |
424 const Instr kBlxRegMask = | 423 const Instr kBlxRegMask = |
425 15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4; | 424 15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4; |
426 const Instr kBlxRegPattern = | 425 const Instr kBlxRegPattern = |
427 B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | BLX; | 426 B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | BLX; |
428 const Instr kBlxIp = al | kBlxRegPattern | ip.code(); | 427 const Instr kBlxIp = al | kBlxRegPattern | ip.code(); |
429 const Instr kMovMvnMask = 0x6d * B21 | 0xf * B16; | 428 const Instr kMovMvnMask = 0x6d * B21 | 0xf * B16; |
430 const Instr kMovMvnPattern = 0xd * B21; | 429 const Instr kMovMvnPattern = 0xd * B21; |
431 const Instr kMovMvnFlip = B22; | 430 const Instr kMovMvnFlip = B22; |
432 const Instr kMovLeaveCCMask = 0xdff * B16; | 431 const Instr kMovLeaveCCMask = 0xdff * B16; |
433 const Instr kMovLeaveCCPattern = 0x1a0 * B16; | 432 const Instr kMovLeaveCCPattern = 0x1a0 * B16; |
433 const Instr kMovwPattern = 0x30 * B20; | |
434 const Instr kMovtPattern = 0x34 * B20; | |
434 const Instr kMovwLeaveCCFlip = 0x5 * B21; | 435 const Instr kMovwLeaveCCFlip = 0x5 * B21; |
435 const Instr kCmpCmnMask = 0xdd * B20 | 0xf * B12; | 436 const Instr kCmpCmnMask = 0xdd * B20 | 0xf * B12; |
436 const Instr kCmpCmnPattern = 0x15 * B20; | 437 const Instr kCmpCmnPattern = 0x15 * B20; |
437 const Instr kCmpCmnFlip = B21; | 438 const Instr kCmpCmnFlip = B21; |
438 const Instr kAddSubFlip = 0x6 * B21; | 439 const Instr kAddSubFlip = 0x6 * B21; |
439 const Instr kAndBicFlip = 0xe * B21; | 440 const Instr kAndBicFlip = 0xe * B21; |
440 | 441 |
441 // A mask for the Rd register for push, pop, ldr, str instructions. | 442 // A mask for the Rd register for push, pop, ldr, str instructions. |
442 const Instr kLdrRegFpOffsetPattern = | 443 const Instr kLdrRegFpOffsetPattern = |
443 al | B26 | L | Offset | kRegister_fp_Code * B16; | 444 al | B26 | L | Offset | kRegister_fp_Code * B16; |
(...skipping 14 matching lines...) Expand all Loading... | |
458 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); | 459 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); |
459 num_pending_32_bit_reloc_info_ = 0; | 460 num_pending_32_bit_reloc_info_ = 0; |
460 num_pending_64_bit_reloc_info_ = 0; | 461 num_pending_64_bit_reloc_info_ = 0; |
461 next_buffer_check_ = 0; | 462 next_buffer_check_ = 0; |
462 const_pool_blocked_nesting_ = 0; | 463 const_pool_blocked_nesting_ = 0; |
463 no_const_pool_before_ = 0; | 464 no_const_pool_before_ = 0; |
464 first_const_pool_32_use_ = -1; | 465 first_const_pool_32_use_ = -1; |
465 first_const_pool_64_use_ = -1; | 466 first_const_pool_64_use_ = -1; |
466 last_bound_pos_ = 0; | 467 last_bound_pos_ = 0; |
467 constant_pool_available_ = !FLAG_enable_ool_constant_pool; | 468 constant_pool_available_ = !FLAG_enable_ool_constant_pool; |
468 constant_pool_full_ = false; | |
469 ClearRecordedAstId(); | 469 ClearRecordedAstId(); |
470 } | 470 } |
471 | 471 |
472 | 472 |
473 Assembler::~Assembler() { | 473 Assembler::~Assembler() { |
474 ASSERT(const_pool_blocked_nesting_ == 0); | 474 ASSERT(const_pool_blocked_nesting_ == 0); |
475 } | 475 } |
476 | 476 |
477 | 477 |
478 void Assembler::GetCode(CodeDesc* desc) { | 478 void Assembler::GetCode(CodeDesc* desc) { |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
629 | 629 |
630 Instr Assembler::GetConsantPoolLoadPattern() { | 630 Instr Assembler::GetConsantPoolLoadPattern() { |
631 if (FLAG_enable_ool_constant_pool) { | 631 if (FLAG_enable_ool_constant_pool) { |
632 return kLdrPpImmedPattern; | 632 return kLdrPpImmedPattern; |
633 } else { | 633 } else { |
634 return kLdrPCImmedPattern; | 634 return kLdrPCImmedPattern; |
635 } | 635 } |
636 } | 636 } |
637 | 637 |
638 | 638 |
639 Instr Assembler::GetConsantPoolLoadMask() { | |
640 if (FLAG_enable_ool_constant_pool) { | |
641 return kLdrPpImmedMask; | |
642 } else { | |
643 return kLdrPCImmedMask; | |
644 } | |
645 } | |
646 | |
647 | |
639 bool Assembler::IsPush(Instr instr) { | 648 bool Assembler::IsPush(Instr instr) { |
640 return ((instr & ~kRdMask) == kPushRegPattern); | 649 return ((instr & ~kRdMask) == kPushRegPattern); |
641 } | 650 } |
642 | 651 |
643 | 652 |
644 bool Assembler::IsPop(Instr instr) { | 653 bool Assembler::IsPop(Instr instr) { |
645 return ((instr & ~kRdMask) == kPopRegPattern); | 654 return ((instr & ~kRdMask) == kPopRegPattern); |
646 } | 655 } |
647 | 656 |
648 | 657 |
(...skipping 24 matching lines...) Expand all Loading... | |
673 } | 682 } |
674 | 683 |
675 | 684 |
676 bool Assembler::IsLdrPpImmediateOffset(Instr instr) { | 685 bool Assembler::IsLdrPpImmediateOffset(Instr instr) { |
677 // Check the instruction is indeed a | 686 // Check the instruction is indeed a |
678 // ldr<cond> <Rd>, [pp +/- offset_12]. | 687 // ldr<cond> <Rd>, [pp +/- offset_12]. |
679 return (instr & kLdrPpImmedMask) == kLdrPpImmedPattern; | 688 return (instr & kLdrPpImmedMask) == kLdrPpImmedPattern; |
680 } | 689 } |
681 | 690 |
682 | 691 |
692 bool Assembler::IsLdrPpRegOffset(Instr instr) { | |
693 // Check the instruction is indeed a | |
694 // ldr<cond> <Rd>, [pp, +/- <Rm>]. | |
695 return (instr & kLdrPpRegMask) == kLdrPpRegPattern; | |
696 } | |
697 | |
698 | |
699 Instr Assembler::GetLdrPpRegOffsetPattern() { | |
700 return kLdrPpRegPattern; | |
701 } | |
702 | |
703 | |
683 bool Assembler::IsVldrDPcImmediateOffset(Instr instr) { | 704 bool Assembler::IsVldrDPcImmediateOffset(Instr instr) { |
684 // Check the instruction is indeed a | 705 // Check the instruction is indeed a |
685 // vldr<cond> <Dd>, [pc +/- offset_10]. | 706 // vldr<cond> <Dd>, [pc +/- offset_10]. |
686 return (instr & kVldrDPCMask) == kVldrDPCPattern; | 707 return (instr & kVldrDPCMask) == kVldrDPCPattern; |
687 } | 708 } |
688 | 709 |
689 | 710 |
690 bool Assembler::IsVldrDPpImmediateOffset(Instr instr) { | 711 bool Assembler::IsVldrDPpImmediateOffset(Instr instr) { |
691 // Check the instruction is indeed a | 712 // Check the instruction is indeed a |
692 // vldr<cond> <Dd>, [pp +/- offset_10]. | 713 // vldr<cond> <Dd>, [pp +/- offset_10]. |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
974 // immediate fits, change the opcode. | 995 // immediate fits, change the opcode. |
975 if (instr != NULL) { | 996 if (instr != NULL) { |
976 if ((*instr & kMovMvnMask) == kMovMvnPattern) { | 997 if ((*instr & kMovMvnMask) == kMovMvnPattern) { |
977 if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) { | 998 if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) { |
978 *instr ^= kMovMvnFlip; | 999 *instr ^= kMovMvnFlip; |
979 return true; | 1000 return true; |
980 } else if ((*instr & kMovLeaveCCMask) == kMovLeaveCCPattern) { | 1001 } else if ((*instr & kMovLeaveCCMask) == kMovLeaveCCPattern) { |
981 if (CpuFeatures::IsSupported(ARMv7)) { | 1002 if (CpuFeatures::IsSupported(ARMv7)) { |
982 if (imm32 < 0x10000) { | 1003 if (imm32 < 0x10000) { |
983 *instr ^= kMovwLeaveCCFlip; | 1004 *instr ^= kMovwLeaveCCFlip; |
984 *instr |= EncodeMovwImmediate(imm32); | 1005 *instr |= Assembler::EncodeMovwImmediate(imm32); |
985 *rotate_imm = *immed_8 = 0; // Not used for movw. | 1006 *rotate_imm = *immed_8 = 0; // Not used for movw. |
986 return true; | 1007 return true; |
987 } | 1008 } |
988 } | 1009 } |
989 } | 1010 } |
990 } else if ((*instr & kCmpCmnMask) == kCmpCmnPattern) { | 1011 } else if ((*instr & kCmpCmnMask) == kCmpCmnPattern) { |
991 if (fits_shifter(-static_cast<int>(imm32), rotate_imm, immed_8, NULL)) { | 1012 if (fits_shifter(-static_cast<int>(imm32), rotate_imm, immed_8, NULL)) { |
992 *instr ^= kCmpCmnFlip; | 1013 *instr ^= kCmpCmnFlip; |
993 return true; | 1014 return true; |
994 } | 1015 } |
(...skipping 28 matching lines...) Expand all Loading... | |
1023 return assembler->serializer_enabled(); | 1044 return assembler->serializer_enabled(); |
1024 } else if (RelocInfo::IsNone(rmode_)) { | 1045 } else if (RelocInfo::IsNone(rmode_)) { |
1025 return false; | 1046 return false; |
1026 } | 1047 } |
1027 return true; | 1048 return true; |
1028 } | 1049 } |
1029 | 1050 |
1030 | 1051 |
1031 static bool use_mov_immediate_load(const Operand& x, | 1052 static bool use_mov_immediate_load(const Operand& x, |
1032 const Assembler* assembler) { | 1053 const Assembler* assembler) { |
1033 if (assembler != NULL && !assembler->can_use_constant_pool()) { | 1054 if (assembler != NULL && !assembler->is_constant_pool_available()) { |
1034 // If there is no constant pool available, we must use an mov immediate. | 1055 // If there is no constant pool available, we must use an mov immediate. |
1035 // TODO(rmcilroy): enable ARMv6 support. | 1056 // TODO(rmcilroy): enable ARMv6 support. |
1036 ASSERT(CpuFeatures::IsSupported(ARMv7)); | 1057 ASSERT(CpuFeatures::IsSupported(ARMv7)); |
1037 return true; | 1058 return true; |
1038 } else if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) && | 1059 } else if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) && |
1039 (assembler == NULL || !assembler->predictable_code_size())) { | 1060 (assembler == NULL || !assembler->predictable_code_size())) { |
1040 // Prefer movw / movt to constant pool if it is more efficient on the CPU. | 1061 // Prefer movw / movt to constant pool if it is more efficient on the CPU. |
1041 return true; | 1062 return true; |
1042 } else if (x.must_output_reloc_info(assembler)) { | 1063 } else if (x.must_output_reloc_info(assembler)) { |
1043 // Prefer constant pool if data is likely to be patched. | 1064 // Prefer constant pool if data is likely to be patched. |
1044 return false; | 1065 return false; |
1045 } else { | 1066 } else { |
1046 // Otherwise, use immediate load if movw / movt is available. | 1067 // Otherwise, use immediate load if movw / movt is available. |
1047 return CpuFeatures::IsSupported(ARMv7); | 1068 return CpuFeatures::IsSupported(ARMv7); |
1048 } | 1069 } |
1049 } | 1070 } |
1050 | 1071 |
1051 | 1072 |
1052 bool Operand::is_single_instruction(const Assembler* assembler, | 1073 int Operand::instructions_required(const Assembler* assembler, |
ulan
2014/07/01 13:29:47
It is possible to accidentally misuse this functio
rmcilroy
2014/07/02 16:35:54
Yes, this would theoretically be possible. I've ad
| |
1053 Instr instr) const { | 1074 Instr instr) const { |
1054 if (rm_.is_valid()) return true; | 1075 if (rm_.is_valid()) return 1; |
1055 uint32_t dummy1, dummy2; | 1076 uint32_t dummy1, dummy2; |
1056 if (must_output_reloc_info(assembler) || | 1077 if (must_output_reloc_info(assembler) || |
1057 !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) { | 1078 !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) { |
1058 // The immediate operand cannot be encoded as a shifter operand, or use of | 1079 // The immediate operand cannot be encoded as a shifter operand, or use of |
1059 // constant pool is required. For a mov instruction not setting the | 1080 // constant pool is required. First account for the instructions required |
1060 // condition code additional instruction conventions can be used. | 1081 // for the constant pool or immediate load |
1061 if ((instr & ~kCondMask) == 13*B21) { // mov, S not set | 1082 int instructions; |
1062 return !use_mov_immediate_load(*this, assembler); | 1083 if (use_mov_immediate_load(*this, assembler)) { |
1084 instructions = 2; // A movw, movt immediate load. | |
1085 } else if (assembler != NULL && assembler->use_extended_constant_pool()) { | |
1086 instructions = 3; // An extended constant pool load. | |
1063 } else { | 1087 } else { |
1064 // If this is not a mov or mvn instruction there will always an additional | 1088 instructions = 1; // A small constant pool load. |
1065 // instructions - either mov or ldr. The mov might actually be two | |
1066 // instructions mov or movw followed by movt so including the actual | |
1067 // instruction two or three instructions will be generated. | |
1068 return false; | |
1069 } | 1089 } |
1090 | |
1091 if ((instr & ~kCondMask) != 13*B21) { // mov, S not set | |
1092 // For a mov or mvn instruction which doesn't set the condition | |
1093 // code, the constant pool or immediate load is enough, otherwise we need | |
1094 // to account for the actual instruction being requested. | |
1095 instructions += 1; | |
1096 } | |
1097 return instructions; | |
1070 } else { | 1098 } else { |
1071 // No use of constant pool and the immediate operand can be encoded as a | 1099 // No use of constant pool and the immediate operand can be encoded as a |
1072 // shifter operand. | 1100 // shifter operand. |
1073 return true; | 1101 return 1; |
1074 } | 1102 } |
1075 } | 1103 } |
1076 | 1104 |
1077 | 1105 |
1078 void Assembler::move_32_bit_immediate(Register rd, | 1106 void Assembler::move_32_bit_immediate(Register rd, |
1079 const Operand& x, | 1107 const Operand& x, |
1080 Condition cond) { | 1108 Condition cond) { |
1081 RelocInfo rinfo(pc_, x.rmode_, x.imm32_, NULL); | 1109 RelocInfo rinfo(pc_, x.rmode_, x.imm32_, NULL); |
1082 if (x.must_output_reloc_info(this)) { | 1110 if (x.must_output_reloc_info(this)) { |
1083 RecordRelocInfo(rinfo); | 1111 RecordRelocInfo(rinfo); |
1084 } | 1112 } |
1085 | 1113 |
1086 if (use_mov_immediate_load(x, this)) { | 1114 if (use_mov_immediate_load(x, this)) { |
1087 Register target = rd.code() == pc.code() ? ip : rd; | 1115 Register target = rd.code() == pc.code() ? ip : rd; |
1088 // TODO(rmcilroy): add ARMv6 support for immediate loads. | 1116 // TODO(rmcilroy): add ARMv6 support for immediate loads. |
1089 ASSERT(CpuFeatures::IsSupported(ARMv7)); | 1117 ASSERT(CpuFeatures::IsSupported(ARMv7)); |
1090 if (!FLAG_enable_ool_constant_pool && | 1118 if (!FLAG_enable_ool_constant_pool && |
1091 x.must_output_reloc_info(this)) { | 1119 x.must_output_reloc_info(this)) { |
1092 // Make sure the movw/movt doesn't get separated. | 1120 // Make sure the movw/movt doesn't get separated. |
1093 BlockConstPoolFor(2); | 1121 BlockConstPoolFor(2); |
1094 } | 1122 } |
1095 movw(target, static_cast<uint32_t>(x.imm32_ & 0xffff), cond); | 1123 movw(target, static_cast<uint32_t>(x.imm32_ & 0xffff), cond); |
1096 movt(target, static_cast<uint32_t>(x.imm32_) >> 16, cond); | 1124 movt(target, static_cast<uint32_t>(x.imm32_) >> 16, cond); |
1097 if (target.code() != rd.code()) { | 1125 if (target.code() != rd.code()) { |
1098 mov(rd, target, LeaveCC, cond); | 1126 mov(rd, target, LeaveCC, cond); |
1099 } | 1127 } |
1100 } else { | 1128 } else { |
1101 ASSERT(can_use_constant_pool()); | 1129 ASSERT(is_constant_pool_available()); |
1102 ConstantPoolAddEntry(rinfo); | 1130 ConstantPoolArray::LayoutSection section = ConstantPoolAddEntry(rinfo); |
1103 ldr(rd, MemOperand(FLAG_enable_ool_constant_pool ? pp : pc, 0), cond); | 1131 if (section == ConstantPoolArray::EXTENDED_SECTION) { |
1132 ASSERT(FLAG_enable_ool_constant_pool); | |
1133 Register target = rd.code() == pc.code() ? ip : rd; | |
1134 // Emit instructions to load constant pool offset. | |
1135 movw(target, 0, cond); | |
1136 movt(target, 0, cond); | |
1137 // Load from constant pool at offset. | |
1138 ldr(rd, MemOperand(pp, target), cond); | |
1139 } else { | |
1140 ASSERT(section == ConstantPoolArray::SMALL_SECTION); | |
1141 ldr(rd, MemOperand(FLAG_enable_ool_constant_pool ? pp : pc, 0), cond); | |
1142 } | |
1104 } | 1143 } |
1105 } | 1144 } |
1106 | 1145 |
1107 | 1146 |
1108 void Assembler::addrmod1(Instr instr, | 1147 void Assembler::addrmod1(Instr instr, |
1109 Register rn, | 1148 Register rn, |
1110 Register rd, | 1149 Register rd, |
1111 const Operand& x) { | 1150 const Operand& x) { |
1112 CheckBuffer(); | 1151 CheckBuffer(); |
1113 ASSERT((instr & ~(kCondMask | kOpCodeMask | S)) == 0); | 1152 ASSERT((instr & ~(kCondMask | kOpCodeMask | S)) == 0); |
(...skipping 1283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2397 if (CpuFeatures::IsSupported(VFP3) && FitsVMOVDoubleImmediate(imm, &enc)) { | 2436 if (CpuFeatures::IsSupported(VFP3) && FitsVMOVDoubleImmediate(imm, &enc)) { |
2398 // The double can be encoded in the instruction. | 2437 // The double can be encoded in the instruction. |
2399 // | 2438 // |
2400 // Dd = immediate | 2439 // Dd = immediate |
2401 // Instruction details available in ARM DDI 0406C.b, A8-936. | 2440 // Instruction details available in ARM DDI 0406C.b, A8-936. |
2402 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) | | 2441 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) | |
2403 // Vd(15-12) | 101(11-9) | sz=1(8) | imm4L(3-0) | 2442 // Vd(15-12) | 101(11-9) | sz=1(8) | imm4L(3-0) |
2404 int vd, d; | 2443 int vd, d; |
2405 dst.split_code(&vd, &d); | 2444 dst.split_code(&vd, &d); |
2406 emit(al | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc); | 2445 emit(al | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc); |
2407 } else if (FLAG_enable_vldr_imm && can_use_constant_pool()) { | 2446 } else if (FLAG_enable_vldr_imm && is_constant_pool_available()) { |
2408 // TODO(jfb) Temporarily turned off until we have constant blinding or | 2447 // TODO(jfb) Temporarily turned off until we have constant blinding or |
2409 // some equivalent mitigation: an attacker can otherwise control | 2448 // some equivalent mitigation: an attacker can otherwise control |
2410 // generated data which also happens to be executable, a Very Bad | 2449 // generated data which also happens to be executable, a Very Bad |
2411 // Thing indeed. | 2450 // Thing indeed. |
2412 // Blinding gets tricky because we don't have xor, we probably | 2451 // Blinding gets tricky because we don't have xor, we probably |
2413 // need to add/subtract without losing precision, which requires a | 2452 // need to add/subtract without losing precision, which requires a |
2414 // cookie value that Lithium is probably better positioned to | 2453 // cookie value that Lithium is probably better positioned to |
2415 // choose. | 2454 // choose. |
2416 // We could also add a few peepholes here like detecting 0.0 and | 2455 // We could also add a few peepholes here like detecting 0.0 and |
2417 // -0.0 and doing a vmov from the sequestered d14, forcing denorms | 2456 // -0.0 and doing a vmov from the sequestered d14, forcing denorms |
2418 // to zero (we set flush-to-zero), and normalizing NaN values. | 2457 // to zero (we set flush-to-zero), and normalizing NaN values. |
2419 // We could also detect redundant values. | 2458 // We could also detect redundant values. |
2420 // The code could also randomize the order of values, though | 2459 // The code could also randomize the order of values, though |
2421 // that's tricky because vldr has a limited reach. Furthermore | 2460 // that's tricky because vldr has a limited reach. Furthermore |
2422 // it breaks load locality. | 2461 // it breaks load locality. |
2423 RelocInfo rinfo(pc_, imm); | 2462 RelocInfo rinfo(pc_, imm); |
2424 ConstantPoolAddEntry(rinfo); | 2463 ConstantPoolArray::LayoutSection section = ConstantPoolAddEntry(rinfo); |
2425 vldr(dst, MemOperand(FLAG_enable_ool_constant_pool ? pp : pc, 0)); | 2464 if (section == ConstantPoolArray::EXTENDED_SECTION) { |
2465 ASSERT(FLAG_enable_ool_constant_pool); | |
2466 // Emit instructions to load constant pool offset. | |
2467 movw(ip, 0); | |
2468 movt(ip, 0); | |
2469 // Load from constant pool at offset. | |
2470 vldr(dst, MemOperand(pp, ip)); | |
2471 } else { | |
2472 ASSERT(section == ConstantPoolArray::SMALL_SECTION); | |
2473 vldr(dst, MemOperand(FLAG_enable_ool_constant_pool ? pp : pc, 0)); | |
2474 } | |
2426 } else { | 2475 } else { |
2427 // Synthesise the double from ARM immediates. | 2476 // Synthesise the double from ARM immediates. |
2428 uint32_t lo, hi; | 2477 uint32_t lo, hi; |
2429 DoubleAsTwoUInt32(imm, &lo, &hi); | 2478 DoubleAsTwoUInt32(imm, &lo, &hi); |
2430 | 2479 |
2431 if (scratch.is(no_reg)) { | 2480 if (scratch.is(no_reg)) { |
2432 if (dst.code() < 16) { | 2481 if (dst.code() < 16) { |
2433 const LowDwVfpRegister loc = LowDwVfpRegister::from_code(dst.code()); | 2482 const LowDwVfpRegister loc = LowDwVfpRegister::from_code(dst.code()); |
2434 // Move the low part of the double into the lower of the corresponsing S | 2483 // Move the low part of the double into the lower of the corresponsing S |
2435 // registers of D register dst. | 2484 // registers of D register dst. |
(...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3030 // a type. | 3079 // a type. |
3031 ASSERT(0 <= type && type <= 14); // mov pc, pc isn't a nop. | 3080 ASSERT(0 <= type && type <= 14); // mov pc, pc isn't a nop. |
3032 emit(al | 13*B21 | type*B12 | type); | 3081 emit(al | 13*B21 | type*B12 | type); |
3033 } | 3082 } |
3034 | 3083 |
3035 | 3084 |
3036 bool Assembler::IsMovT(Instr instr) { | 3085 bool Assembler::IsMovT(Instr instr) { |
3037 instr &= ~(((kNumberOfConditions - 1) << 28) | // Mask off conditions | 3086 instr &= ~(((kNumberOfConditions - 1) << 28) | // Mask off conditions |
3038 ((kNumRegisters-1)*B12) | // mask out register | 3087 ((kNumRegisters-1)*B12) | // mask out register |
3039 EncodeMovwImmediate(0xFFFF)); // mask out immediate value | 3088 EncodeMovwImmediate(0xFFFF)); // mask out immediate value |
3040 return instr == 0x34*B20; | 3089 return instr == kMovtPattern; |
3041 } | 3090 } |
3042 | 3091 |
3043 | 3092 |
3044 bool Assembler::IsMovW(Instr instr) { | 3093 bool Assembler::IsMovW(Instr instr) { |
3045 instr &= ~(((kNumberOfConditions - 1) << 28) | // Mask off conditions | 3094 instr &= ~(((kNumberOfConditions - 1) << 28) | // Mask off conditions |
3046 ((kNumRegisters-1)*B12) | // mask out destination | 3095 ((kNumRegisters-1)*B12) | // mask out destination |
3047 EncodeMovwImmediate(0xFFFF)); // mask out immediate value | 3096 EncodeMovwImmediate(0xFFFF)); // mask out immediate value |
3048 return instr == 0x30*B20; | 3097 return instr == kMovwPattern; |
3049 } | 3098 } |
3050 | 3099 |
3051 | 3100 |
3101 Instr Assembler::GetMovTPattern() { | |
3102 return kMovtPattern; | |
3103 } | |
3104 | |
3105 | |
3106 Instr Assembler::GetMovWPattern() { | |
3107 return kMovwPattern; | |
3108 } | |
3109 | |
3110 | |
3111 Instr Assembler::EncodeMovwImmediate(uint32_t immediate) { | |
3112 ASSERT(immediate < 0x10000); | |
3113 return ((immediate & 0xf000) << 4) | (immediate & 0xfff); | |
3114 } | |
3115 | |
3116 | |
3117 Instr Assembler::PatchMovwImmediate(Instr instruction, uint32_t immediate) { | |
3118 instruction &= ~EncodeMovwImmediate(0xffff); | |
3119 return instruction | EncodeMovwImmediate(immediate); | |
3120 } | |
3121 | |
3122 | |
3052 bool Assembler::IsNop(Instr instr, int type) { | 3123 bool Assembler::IsNop(Instr instr, int type) { |
3053 ASSERT(0 <= type && type <= 14); // mov pc, pc isn't a nop. | 3124 ASSERT(0 <= type && type <= 14); // mov pc, pc isn't a nop. |
3054 // Check for mov rx, rx where x = type. | 3125 // Check for mov rx, rx where x = type. |
3055 return instr == (al | 13*B21 | type*B12 | type); | 3126 return instr == (al | 13*B21 | type*B12 | type); |
3056 } | 3127 } |
3057 | 3128 |
3058 | 3129 |
3059 bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) { | 3130 bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) { |
3060 uint32_t dummy1; | 3131 uint32_t dummy1; |
3061 uint32_t dummy2; | 3132 uint32_t dummy2; |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3208 NULL); | 3279 NULL); |
3209 ClearRecordedAstId(); | 3280 ClearRecordedAstId(); |
3210 reloc_info_writer.Write(&reloc_info_with_ast_id); | 3281 reloc_info_writer.Write(&reloc_info_with_ast_id); |
3211 } else { | 3282 } else { |
3212 reloc_info_writer.Write(&rinfo); | 3283 reloc_info_writer.Write(&rinfo); |
3213 } | 3284 } |
3214 } | 3285 } |
3215 } | 3286 } |
3216 | 3287 |
3217 | 3288 |
3218 void Assembler::ConstantPoolAddEntry(const RelocInfo& rinfo) { | 3289 ConstantPoolArray::LayoutSection Assembler::ConstantPoolAddEntry( |
3290 const RelocInfo& rinfo) { | |
3219 if (FLAG_enable_ool_constant_pool) { | 3291 if (FLAG_enable_ool_constant_pool) { |
3220 constant_pool_builder_.AddEntry(this, rinfo); | 3292 return constant_pool_builder_.AddEntry(this, rinfo); |
3221 } else { | 3293 } else { |
3222 if (rinfo.rmode() == RelocInfo::NONE64) { | 3294 if (rinfo.rmode() == RelocInfo::NONE64) { |
3223 ASSERT(num_pending_64_bit_reloc_info_ < kMaxNumPending64RelocInfo); | 3295 ASSERT(num_pending_64_bit_reloc_info_ < kMaxNumPending64RelocInfo); |
3224 if (num_pending_64_bit_reloc_info_ == 0) { | 3296 if (num_pending_64_bit_reloc_info_ == 0) { |
3225 first_const_pool_64_use_ = pc_offset(); | 3297 first_const_pool_64_use_ = pc_offset(); |
3226 } | 3298 } |
3227 pending_64_bit_reloc_info_[num_pending_64_bit_reloc_info_++] = rinfo; | 3299 pending_64_bit_reloc_info_[num_pending_64_bit_reloc_info_++] = rinfo; |
3228 } else { | 3300 } else { |
3229 ASSERT(num_pending_32_bit_reloc_info_ < kMaxNumPending32RelocInfo); | 3301 ASSERT(num_pending_32_bit_reloc_info_ < kMaxNumPending32RelocInfo); |
3230 if (num_pending_32_bit_reloc_info_ == 0) { | 3302 if (num_pending_32_bit_reloc_info_ == 0) { |
3231 first_const_pool_32_use_ = pc_offset(); | 3303 first_const_pool_32_use_ = pc_offset(); |
3232 } | 3304 } |
3233 pending_32_bit_reloc_info_[num_pending_32_bit_reloc_info_++] = rinfo; | 3305 pending_32_bit_reloc_info_[num_pending_32_bit_reloc_info_++] = rinfo; |
3234 } | 3306 } |
3235 // Make sure the constant pool is not emitted in place of the next | 3307 // Make sure the constant pool is not emitted in place of the next |
3236 // instruction for which we just recorded relocation info. | 3308 // instruction for which we just recorded relocation info. |
3237 BlockConstPoolFor(1); | 3309 BlockConstPoolFor(1); |
3310 return ConstantPoolArray::SMALL_SECTION; | |
3238 } | 3311 } |
3239 } | 3312 } |
3240 | 3313 |
3241 | 3314 |
3242 void Assembler::BlockConstPoolFor(int instructions) { | 3315 void Assembler::BlockConstPoolFor(int instructions) { |
3243 if (FLAG_enable_ool_constant_pool) { | 3316 if (FLAG_enable_ool_constant_pool) { |
3244 // Should be a no-op if using an out-of-line constant pool. | 3317 // Should be a no-op if using an out-of-line constant pool. |
3245 ASSERT(num_pending_32_bit_reloc_info_ == 0); | 3318 ASSERT(num_pending_32_bit_reloc_info_ == 0); |
3246 ASSERT(num_pending_64_bit_reloc_info_ == 0); | 3319 ASSERT(num_pending_64_bit_reloc_info_ == 0); |
3247 return; | 3320 return; |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3480 } | 3553 } |
3481 | 3554 |
3482 | 3555 |
3483 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { | 3556 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { |
3484 constant_pool_builder_.Populate(this, constant_pool); | 3557 constant_pool_builder_.Populate(this, constant_pool); |
3485 } | 3558 } |
3486 | 3559 |
3487 | 3560 |
3488 ConstantPoolBuilder::ConstantPoolBuilder() | 3561 ConstantPoolBuilder::ConstantPoolBuilder() |
3489 : entries_(), | 3562 : entries_(), |
3490 merged_indexes_(), | 3563 current_section_(ConstantPoolArray::SMALL_SECTION) {} |
3491 count_of_64bit_(0), | |
3492 count_of_code_ptr_(0), | |
3493 count_of_heap_ptr_(0), | |
3494 count_of_32bit_(0) { } | |
3495 | 3564 |
3496 | 3565 |
3497 bool ConstantPoolBuilder::IsEmpty() { | 3566 bool ConstantPoolBuilder::IsEmpty() { |
3498 return entries_.size() == 0; | 3567 return entries_.size() == 0; |
3499 } | 3568 } |
3500 | 3569 |
3501 | 3570 |
3502 bool ConstantPoolBuilder::Is64BitEntry(RelocInfo::Mode rmode) { | 3571 ConstantPoolArray::Type ConstantPoolBuilder::GetConstantPoolType( |
3503 return rmode == RelocInfo::NONE64; | 3572 RelocInfo::Mode rmode) { |
3573 if (rmode == RelocInfo::NONE64) { | |
3574 return ConstantPoolArray::INT64; | |
3575 } else if (!RelocInfo::IsGCRelocMode(rmode)) { | |
3576 return ConstantPoolArray::INT32; | |
3577 } else if (RelocInfo::IsCodeTarget(rmode)) { | |
3578 return ConstantPoolArray::CODE_PTR; | |
3579 } else { | |
3580 ASSERT(RelocInfo::IsGCRelocMode(rmode) && !RelocInfo::IsCodeTarget(rmode)); | |
3581 return ConstantPoolArray::HEAP_PTR; | |
3582 } | |
3504 } | 3583 } |
3505 | 3584 |
3506 | 3585 |
3507 bool ConstantPoolBuilder::Is32BitEntry(RelocInfo::Mode rmode) { | 3586 ConstantPoolArray::LayoutSection ConstantPoolBuilder::AddEntry( |
3508 return !RelocInfo::IsGCRelocMode(rmode) && rmode != RelocInfo::NONE64; | 3587 Assembler* assm, const RelocInfo& rinfo) { |
3509 } | |
3510 | |
3511 | |
3512 bool ConstantPoolBuilder::IsCodePtrEntry(RelocInfo::Mode rmode) { | |
3513 return RelocInfo::IsCodeTarget(rmode); | |
3514 } | |
3515 | |
3516 | |
3517 bool ConstantPoolBuilder::IsHeapPtrEntry(RelocInfo::Mode rmode) { | |
3518 return RelocInfo::IsGCRelocMode(rmode) && !RelocInfo::IsCodeTarget(rmode); | |
3519 } | |
3520 | |
3521 | |
3522 void ConstantPoolBuilder::AddEntry(Assembler* assm, | |
3523 const RelocInfo& rinfo) { | |
3524 RelocInfo::Mode rmode = rinfo.rmode(); | 3588 RelocInfo::Mode rmode = rinfo.rmode(); |
3525 ASSERT(rmode != RelocInfo::COMMENT && | 3589 ASSERT(rmode != RelocInfo::COMMENT && |
3526 rmode != RelocInfo::POSITION && | 3590 rmode != RelocInfo::POSITION && |
3527 rmode != RelocInfo::STATEMENT_POSITION && | 3591 rmode != RelocInfo::STATEMENT_POSITION && |
3528 rmode != RelocInfo::CONST_POOL); | 3592 rmode != RelocInfo::CONST_POOL); |
3529 | 3593 |
3530 | 3594 |
3531 // Try to merge entries which won't be patched. | 3595 // Try to merge entries which won't be patched. |
3532 int merged_index = -1; | 3596 int merged_index = -1; |
3597 ConstantPoolArray::LayoutSection entry_section = current_section_; | |
3533 if (RelocInfo::IsNone(rmode) || | 3598 if (RelocInfo::IsNone(rmode) || |
3534 (!assm->serializer_enabled() && (rmode >= RelocInfo::CELL))) { | 3599 (!assm->serializer_enabled() && (rmode >= RelocInfo::CELL))) { |
3535 size_t i; | 3600 size_t i; |
3536 std::vector<RelocInfo>::const_iterator it; | 3601 std::vector<ConstantPoolEntry>::const_iterator it; |
3537 for (it = entries_.begin(), i = 0; it != entries_.end(); it++, i++) { | 3602 for (it = entries_.begin(), i = 0; it != entries_.end(); it++, i++) { |
3538 if (RelocInfo::IsEqual(rinfo, *it)) { | 3603 if (RelocInfo::IsEqual(rinfo, it->rinfo_)) { |
3604 // Merge with found entry. | |
3539 merged_index = i; | 3605 merged_index = i; |
3606 entry_section = entries_[i].section_; | |
3540 break; | 3607 break; |
3541 } | 3608 } |
3542 } | 3609 } |
3543 } | 3610 } |
3544 | 3611 ASSERT(entry_section <= current_section_); |
3545 entries_.push_back(rinfo); | 3612 entries_.push_back(ConstantPoolEntry(rinfo, entry_section, merged_index)); |
3546 merged_indexes_.push_back(merged_index); | |
3547 | 3613 |
3548 if (merged_index == -1) { | 3614 if (merged_index == -1) { |
3549 // Not merged, so update the appropriate count. | 3615 // Not merged, so update the appropriate count. |
3550 if (Is64BitEntry(rmode)) { | 3616 number_of_entries_[entry_section].increment(GetConstantPoolType(rmode)); |
3551 count_of_64bit_++; | |
3552 } else if (Is32BitEntry(rmode)) { | |
3553 count_of_32bit_++; | |
3554 } else if (IsCodePtrEntry(rmode)) { | |
3555 count_of_code_ptr_++; | |
3556 } else { | |
3557 ASSERT(IsHeapPtrEntry(rmode)); | |
3558 count_of_heap_ptr_++; | |
3559 } | |
3560 } | 3617 } |
3561 | 3618 |
3562 // Check if we still have room for another entry given Arm's ldr and vldr | 3619 // Check if we still have room for another entry in the small section |
3563 // immediate offset range. | 3620 // given Arm's ldr and vldr immediate offset range. |
3564 // TODO(rmcilroy): Avoid creating a new object here when we support | 3621 if (current_section_ == ConstantPoolArray::SMALL_SECTION && |
3565 // extended constant pools. | 3622 !(is_uint12(ConstantPoolArray::SizeFor(*small_entries())) && |
3566 ConstantPoolArray::NumberOfEntries total(count_of_64bit_, | 3623 is_uint10(ConstantPoolArray::MaxInt64Offset( |
3567 count_of_code_ptr_, | 3624 small_entries()->count_of(ConstantPoolArray::INT64))))) { |
3568 count_of_heap_ptr_, | 3625 current_section_ = ConstantPoolArray::EXTENDED_SECTION; |
3569 count_of_32bit_); | |
3570 ConstantPoolArray::NumberOfEntries int64_counts(count_of_64bit_, 0, 0, 0); | |
3571 if (!(is_uint12(ConstantPoolArray::SizeFor(total)) && | |
3572 is_uint10(ConstantPoolArray::SizeFor(int64_counts)))) { | |
3573 assm->set_constant_pool_full(); | |
3574 } | 3626 } |
3627 return entry_section; | |
3575 } | 3628 } |
3576 | 3629 |
3577 | 3630 |
3578 void ConstantPoolBuilder::Relocate(int pc_delta) { | 3631 void ConstantPoolBuilder::Relocate(int pc_delta) { |
3579 for (std::vector<RelocInfo>::iterator rinfo = entries_.begin(); | 3632 for (std::vector<ConstantPoolEntry>::iterator entry = entries_.begin(); |
3580 rinfo != entries_.end(); rinfo++) { | 3633 entry != entries_.end(); entry++) { |
3581 ASSERT(rinfo->rmode() != RelocInfo::JS_RETURN); | 3634 ASSERT(entry->rinfo_.rmode() != RelocInfo::JS_RETURN); |
3582 rinfo->set_pc(rinfo->pc() + pc_delta); | 3635 entry->rinfo_.set_pc(entry->rinfo_.pc() + pc_delta); |
3583 } | 3636 } |
3584 } | 3637 } |
3585 | 3638 |
3586 | 3639 |
3587 Handle<ConstantPoolArray> ConstantPoolBuilder::New(Isolate* isolate) { | 3640 Handle<ConstantPoolArray> ConstantPoolBuilder::New(Isolate* isolate) { |
3588 if (IsEmpty()) { | 3641 if (IsEmpty()) { |
3589 return isolate->factory()->empty_constant_pool_array(); | 3642 return isolate->factory()->empty_constant_pool_array(); |
3643 } else if (extended_entries()->is_empty()) { | |
3644 return isolate->factory()->NewConstantPoolArray(*small_entries()); | |
3590 } else { | 3645 } else { |
3591 ConstantPoolArray::NumberOfEntries small(count_of_64bit_, | 3646 ASSERT(current_section_ == ConstantPoolArray::EXTENDED_SECTION); |
3592 count_of_code_ptr_, | 3647 return isolate->factory()->NewExtendedConstantPoolArray( |
3593 count_of_heap_ptr_, | 3648 *small_entries(), *extended_entries()); |
3594 count_of_32bit_); | |
3595 return isolate->factory()->NewConstantPoolArray(small); | |
3596 } | 3649 } |
3597 } | 3650 } |
3598 | 3651 |
3599 | 3652 |
3600 void ConstantPoolBuilder::Populate(Assembler* assm, | 3653 void ConstantPoolBuilder::Populate(Assembler* assm, |
3601 ConstantPoolArray* constant_pool) { | 3654 ConstantPoolArray* constant_pool) { |
3602 ASSERT(count_of_64bit_ == constant_pool->number_of_entries( | 3655 ASSERT_EQ(extended_entries()->is_empty(), |
3603 ConstantPoolArray::INT64, ConstantPoolArray::SMALL_SECTION)); | 3656 !constant_pool->is_extended_layout()); |
3604 ASSERT(count_of_code_ptr_ == constant_pool->number_of_entries( | 3657 ASSERT(small_entries()->equals(ConstantPoolArray::NumberOfEntries( |
3605 ConstantPoolArray::CODE_PTR, ConstantPoolArray::SMALL_SECTION)); | 3658 constant_pool, ConstantPoolArray::SMALL_SECTION))); |
3606 ASSERT(count_of_heap_ptr_ == constant_pool->number_of_entries( | 3659 if (constant_pool->is_extended_layout()) { |
3607 ConstantPoolArray::HEAP_PTR, ConstantPoolArray::SMALL_SECTION)); | 3660 ASSERT(extended_entries()->equals(ConstantPoolArray::NumberOfEntries( |
3608 ASSERT(count_of_32bit_ == constant_pool->number_of_entries( | 3661 constant_pool, ConstantPoolArray::EXTENDED_SECTION))); |
3609 ConstantPoolArray::INT32, ConstantPoolArray::SMALL_SECTION)); | 3662 } |
3610 ASSERT(entries_.size() == merged_indexes_.size()); | |
3611 | 3663 |
3612 int index_64bit = 0; | 3664 ConstantPoolArray::NumberOfEntries small_idx; |
3613 int index_code_ptr = count_of_64bit_; | 3665 ConstantPoolArray::NumberOfEntries extended_idx; |
3614 int index_heap_ptr = count_of_64bit_ + count_of_code_ptr_; | 3666 for (std::vector<ConstantPoolEntry>::iterator entry = entries_.begin(); |
3615 int index_32bit = count_of_64bit_ + count_of_code_ptr_ + count_of_heap_ptr_; | 3667 entry != entries_.end(); entry++) { |
3616 | 3668 RelocInfo rinfo = entry->rinfo_; |
3617 size_t i; | 3669 RelocInfo::Mode rmode = entry->rinfo_.rmode(); |
3618 std::vector<RelocInfo>::const_iterator rinfo; | 3670 ConstantPoolArray::Type type = GetConstantPoolType(rmode); |
3619 for (rinfo = entries_.begin(), i = 0; rinfo != entries_.end(); rinfo++, i++) { | |
3620 RelocInfo::Mode rmode = rinfo->rmode(); | |
3621 | 3671 |
3622 // Update constant pool if necessary and get the entry's offset. | 3672 // Update constant pool if necessary and get the entry's offset. |
3623 int offset; | 3673 int offset; |
3624 if (merged_indexes_[i] == -1) { | 3674 if (entry->merged_index_ == -1) { |
3625 if (Is64BitEntry(rmode)) { | 3675 int index; |
3626 offset = constant_pool->OffsetOfElementAt(index_64bit) - kHeapObjectTag; | 3676 if (entry->section_ == ConstantPoolArray::EXTENDED_SECTION) { |
3627 constant_pool->set(index_64bit++, rinfo->data64()); | 3677 index = small_entries()->total_count() + |
3628 } else if (Is32BitEntry(rmode)) { | 3678 extended_entries()->base_of(type) + extended_idx.count_of(type); |
3629 offset = constant_pool->OffsetOfElementAt(index_32bit) - kHeapObjectTag; | 3679 extended_idx.increment(type); |
3630 constant_pool->set(index_32bit++, static_cast<int32_t>(rinfo->data())); | |
3631 } else if (IsCodePtrEntry(rmode)) { | |
3632 offset = constant_pool->OffsetOfElementAt(index_code_ptr) - | |
3633 kHeapObjectTag; | |
3634 constant_pool->set(index_code_ptr++, | |
3635 reinterpret_cast<Address>(rinfo->data())); | |
3636 } else { | 3680 } else { |
3637 ASSERT(IsHeapPtrEntry(rmode)); | 3681 ASSERT(entry->section_ == ConstantPoolArray::SMALL_SECTION); |
3638 offset = constant_pool->OffsetOfElementAt(index_heap_ptr) - | 3682 index = small_entries()->base_of(type) + small_idx.count_of(type); |
3639 kHeapObjectTag; | 3683 small_idx.increment(type); |
3640 constant_pool->set(index_heap_ptr++, | |
3641 reinterpret_cast<Object *>(rinfo->data())); | |
3642 } | 3684 } |
3643 merged_indexes_[i] = offset; // Stash offset for merged entries. | 3685 if (type == ConstantPoolArray::INT64) { |
3686 constant_pool->set(index, rinfo.data64()); | |
3687 } else if (type == ConstantPoolArray::INT32) { | |
3688 constant_pool->set(index, static_cast<int32_t>(rinfo.data())); | |
3689 } else if (type == ConstantPoolArray::CODE_PTR) { | |
3690 constant_pool->set(index, reinterpret_cast<Address>(rinfo.data())); | |
3691 } else { | |
3692 ASSERT(type == ConstantPoolArray::HEAP_PTR); | |
3693 constant_pool->set(index, reinterpret_cast<Object *>(rinfo.data())); | |
3694 } | |
3695 offset = constant_pool->OffsetOfElementAt(index) - kHeapObjectTag; | |
3696 entry->merged_index_ = offset; // Stash offset for merged entries. | |
3644 } else { | 3697 } else { |
3645 size_t merged_index = static_cast<size_t>(merged_indexes_[i]); | 3698 ASSERT(entry->merged_index_ < (entry - entries_.begin())); |
3646 ASSERT(merged_index < merged_indexes_.size() && merged_index < i); | 3699 offset = entries_[entry->merged_index_].merged_index_; |
3647 offset = merged_indexes_[merged_index]; | |
3648 } | 3700 } |
3649 | 3701 |
3650 // Patch vldr/ldr instruction with correct offset. | 3702 // Patch vldr/ldr instruction with correct offset. |
3651 Instr instr = assm->instr_at(rinfo->pc()); | 3703 Instr instr = assm->instr_at(rinfo.pc()); |
3652 if (Is64BitEntry(rmode)) { | 3704 if (entry->section_ == ConstantPoolArray::EXTENDED_SECTION) { |
3705 // Instructions to patch must be 'movw rd, [#0]' and 'movt rd, [#0]. | |
3706 Instr next_instr = assm->instr_at(rinfo.pc() + Assembler::kInstrSize); | |
3707 ASSERT((Assembler::IsMovW(instr) && | |
3708 Instruction::ImmedMovwMovtValue(instr) == 0)); | |
3709 ASSERT((Assembler::IsMovT(next_instr) && | |
3710 Instruction::ImmedMovwMovtValue(instr) == 0)); | |
ulan
2014/07/01 13:29:47
Instruction::ImmedMovwMovtValue(next_instr) == 0
rmcilroy
2014/07/02 16:35:54
Good catch, thanks!
| |
3711 assm->instr_at_put(rinfo.pc(), | |
3712 Assembler::PatchMovwImmediate(instr, offset & 0xffff)); | |
3713 assm->instr_at_put(rinfo.pc() + Assembler::kInstrSize, | |
3714 Assembler::PatchMovwImmediate(next_instr, offset >> 16)); | |
3715 } else if (type == ConstantPoolArray::INT64) { | |
3653 // Instruction to patch must be 'vldr rd, [pp, #0]'. | 3716 // Instruction to patch must be 'vldr rd, [pp, #0]'. |
3654 ASSERT((Assembler::IsVldrDPpImmediateOffset(instr) && | 3717 ASSERT((Assembler::IsVldrDPpImmediateOffset(instr) && |
3655 Assembler::GetVldrDRegisterImmediateOffset(instr) == 0)); | 3718 Assembler::GetVldrDRegisterImmediateOffset(instr) == 0)); |
3656 ASSERT(is_uint10(offset)); | 3719 ASSERT(is_uint10(offset)); |
3657 assm->instr_at_put(rinfo->pc(), | 3720 assm->instr_at_put(rinfo.pc(), |
3658 Assembler::SetVldrDRegisterImmediateOffset(instr, offset)); | 3721 Assembler::SetVldrDRegisterImmediateOffset(instr, offset)); |
3659 } else { | 3722 } else { |
3660 // Instruction to patch must be 'ldr rd, [pp, #0]'. | 3723 // Instruction to patch must be 'ldr rd, [pp, #0]'. |
3661 ASSERT((Assembler::IsLdrPpImmediateOffset(instr) && | 3724 ASSERT((Assembler::IsLdrPpImmediateOffset(instr) && |
3662 Assembler::GetLdrRegisterImmediateOffset(instr) == 0)); | 3725 Assembler::GetLdrRegisterImmediateOffset(instr) == 0)); |
3663 ASSERT(is_uint12(offset)); | 3726 ASSERT(is_uint12(offset)); |
3664 assm->instr_at_put(rinfo->pc(), | 3727 assm->instr_at_put(rinfo.pc(), |
3665 Assembler::SetLdrRegisterImmediateOffset(instr, offset)); | 3728 Assembler::SetLdrRegisterImmediateOffset(instr, offset)); |
3666 } | 3729 } |
3667 } | 3730 } |
3668 | 3731 |
3669 ASSERT((index_64bit == count_of_64bit_) && | 3732 ASSERT(small_idx.equals(*small_entries())); |
3670 (index_code_ptr == (index_64bit + count_of_code_ptr_)) && | 3733 ASSERT(extended_idx.equals(*extended_entries())); |
3671 (index_heap_ptr == (index_code_ptr + count_of_heap_ptr_)) && | |
3672 (index_32bit == (index_heap_ptr + count_of_32bit_))); | |
3673 } | 3734 } |
3674 | 3735 |
3675 | 3736 |
3676 } } // namespace v8::internal | 3737 } } // namespace v8::internal |
3677 | 3738 |
3678 #endif // V8_TARGET_ARCH_ARM | 3739 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |