| 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 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 const Instr kLdrRegFpOffsetPattern = | 476 const Instr kLdrRegFpOffsetPattern = |
| 477 al | B26 | L | Offset | Register::kCode_fp * B16; | 477 al | B26 | L | Offset | Register::kCode_fp * B16; |
| 478 const Instr kStrRegFpOffsetPattern = | 478 const Instr kStrRegFpOffsetPattern = |
| 479 al | B26 | Offset | Register::kCode_fp * B16; | 479 al | B26 | Offset | Register::kCode_fp * B16; |
| 480 const Instr kLdrRegFpNegOffsetPattern = | 480 const Instr kLdrRegFpNegOffsetPattern = |
| 481 al | B26 | L | NegOffset | Register::kCode_fp * B16; | 481 al | B26 | L | NegOffset | Register::kCode_fp * B16; |
| 482 const Instr kStrRegFpNegOffsetPattern = | 482 const Instr kStrRegFpNegOffsetPattern = |
| 483 al | B26 | NegOffset | Register::kCode_fp * B16; | 483 al | B26 | NegOffset | Register::kCode_fp * B16; |
| 484 const Instr kLdrStrInstrTypeMask = 0xffff0000; | 484 const Instr kLdrStrInstrTypeMask = 0xffff0000; |
| 485 | 485 |
| 486 | |
| 487 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) | 486 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) |
| 488 : AssemblerBase(isolate, buffer, buffer_size), | 487 : AssemblerBase(isolate, buffer, buffer_size), |
| 489 recorded_ast_id_(TypeFeedbackId::None()), | 488 recorded_ast_id_(TypeFeedbackId::None()), |
| 490 pending_32_bit_constants_(&pending_32_bit_constants_buffer_[0]), | 489 pending_32_bit_constants_(), |
| 491 pending_64_bit_constants_(&pending_64_bit_constants_buffer_[0]), | 490 pending_64_bit_constants_(), |
| 492 constant_pool_builder_(kLdrMaxReachBits, kVldrMaxReachBits), | 491 constant_pool_builder_(kLdrMaxReachBits, kVldrMaxReachBits), |
| 493 positions_recorder_(this) { | 492 positions_recorder_(this) { |
| 493 pending_32_bit_constants_.reserve(kMinNumPendingConstants); |
| 494 pending_64_bit_constants_.reserve(kMinNumPendingConstants); |
| 494 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); | 495 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); |
| 495 num_pending_32_bit_constants_ = 0; | |
| 496 num_pending_64_bit_constants_ = 0; | |
| 497 next_buffer_check_ = 0; | 496 next_buffer_check_ = 0; |
| 498 const_pool_blocked_nesting_ = 0; | 497 const_pool_blocked_nesting_ = 0; |
| 499 no_const_pool_before_ = 0; | 498 no_const_pool_before_ = 0; |
| 500 first_const_pool_32_use_ = -1; | 499 first_const_pool_32_use_ = -1; |
| 501 first_const_pool_64_use_ = -1; | 500 first_const_pool_64_use_ = -1; |
| 502 last_bound_pos_ = 0; | 501 last_bound_pos_ = 0; |
| 503 ClearRecordedAstId(); | 502 ClearRecordedAstId(); |
| 504 } | 503 } |
| 505 | 504 |
| 506 | 505 |
| 507 Assembler::~Assembler() { | 506 Assembler::~Assembler() { |
| 508 DCHECK(const_pool_blocked_nesting_ == 0); | 507 DCHECK(const_pool_blocked_nesting_ == 0); |
| 509 if (pending_32_bit_constants_ != &pending_32_bit_constants_buffer_[0]) { | |
| 510 delete[] pending_32_bit_constants_; | |
| 511 } | |
| 512 if (pending_64_bit_constants_ != &pending_64_bit_constants_buffer_[0]) { | |
| 513 delete[] pending_64_bit_constants_; | |
| 514 } | |
| 515 } | 508 } |
| 516 | 509 |
| 517 | 510 |
| 518 void Assembler::GetCode(CodeDesc* desc) { | 511 void Assembler::GetCode(CodeDesc* desc) { |
| 519 reloc_info_writer.Finish(); | 512 reloc_info_writer.Finish(); |
| 520 | 513 |
| 521 // Emit constant pool if necessary. | 514 // Emit constant pool if necessary. |
| 522 int constant_pool_offset = 0; | 515 int constant_pool_offset = 0; |
| 523 if (FLAG_enable_embedded_constant_pool) { | 516 if (FLAG_enable_embedded_constant_pool) { |
| 524 constant_pool_offset = EmitEmbeddedConstantPool(); | 517 constant_pool_offset = EmitEmbeddedConstantPool(); |
| 525 } else { | 518 } else { |
| 526 CheckConstPool(true, false); | 519 CheckConstPool(true, false); |
| 527 DCHECK(num_pending_32_bit_constants_ == 0); | 520 DCHECK(pending_32_bit_constants_.empty()); |
| 528 DCHECK(num_pending_64_bit_constants_ == 0); | 521 DCHECK(pending_64_bit_constants_.empty()); |
| 529 } | 522 } |
| 530 // Set up code descriptor. | 523 // Set up code descriptor. |
| 531 desc->buffer = buffer_; | 524 desc->buffer = buffer_; |
| 532 desc->buffer_size = buffer_size_; | 525 desc->buffer_size = buffer_size_; |
| 533 desc->instr_size = pc_offset(); | 526 desc->instr_size = pc_offset(); |
| 534 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); | 527 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); |
| 535 desc->constant_pool_size = | 528 desc->constant_pool_size = |
| 536 (constant_pool_offset ? desc->instr_size - constant_pool_offset : 0); | 529 (constant_pool_offset ? desc->instr_size - constant_pool_offset : 0); |
| 537 desc->origin = this; | 530 desc->origin = this; |
| 538 } | 531 } |
| (...skipping 3334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3873 | 3866 |
| 3874 // None of our relocation types are pc relative pointing outside the code | 3867 // None of our relocation types are pc relative pointing outside the code |
| 3875 // buffer nor pc absolute pointing inside the code buffer, so there is no need | 3868 // buffer nor pc absolute pointing inside the code buffer, so there is no need |
| 3876 // to relocate any emitted relocation entries. | 3869 // to relocate any emitted relocation entries. |
| 3877 } | 3870 } |
| 3878 | 3871 |
| 3879 | 3872 |
| 3880 void Assembler::db(uint8_t data) { | 3873 void Assembler::db(uint8_t data) { |
| 3881 // db is used to write raw data. The constant pool should be emitted or | 3874 // db is used to write raw data. The constant pool should be emitted or |
| 3882 // blocked before using db. | 3875 // blocked before using db. |
| 3883 DCHECK(is_const_pool_blocked() || (num_pending_32_bit_constants_ == 0)); | 3876 DCHECK(is_const_pool_blocked() || pending_32_bit_constants_.empty()); |
| 3884 DCHECK(is_const_pool_blocked() || (num_pending_64_bit_constants_ == 0)); | 3877 DCHECK(is_const_pool_blocked() || pending_64_bit_constants_.empty()); |
| 3885 CheckBuffer(); | 3878 CheckBuffer(); |
| 3886 *reinterpret_cast<uint8_t*>(pc_) = data; | 3879 *reinterpret_cast<uint8_t*>(pc_) = data; |
| 3887 pc_ += sizeof(uint8_t); | 3880 pc_ += sizeof(uint8_t); |
| 3888 } | 3881 } |
| 3889 | 3882 |
| 3890 | 3883 |
| 3891 void Assembler::dd(uint32_t data) { | 3884 void Assembler::dd(uint32_t data) { |
| 3892 // dd is used to write raw data. The constant pool should be emitted or | 3885 // dd is used to write raw data. The constant pool should be emitted or |
| 3893 // blocked before using dd. | 3886 // blocked before using dd. |
| 3894 DCHECK(is_const_pool_blocked() || (num_pending_32_bit_constants_ == 0)); | 3887 DCHECK(is_const_pool_blocked() || pending_32_bit_constants_.empty()); |
| 3895 DCHECK(is_const_pool_blocked() || (num_pending_64_bit_constants_ == 0)); | 3888 DCHECK(is_const_pool_blocked() || pending_64_bit_constants_.empty()); |
| 3896 CheckBuffer(); | 3889 CheckBuffer(); |
| 3897 *reinterpret_cast<uint32_t*>(pc_) = data; | 3890 *reinterpret_cast<uint32_t*>(pc_) = data; |
| 3898 pc_ += sizeof(uint32_t); | 3891 pc_ += sizeof(uint32_t); |
| 3899 } | 3892 } |
| 3900 | 3893 |
| 3901 | 3894 |
| 3902 void Assembler::dq(uint64_t value) { | 3895 void Assembler::dq(uint64_t value) { |
| 3903 // dq is used to write raw data. The constant pool should be emitted or | 3896 // dq is used to write raw data. The constant pool should be emitted or |
| 3904 // blocked before using dq. | 3897 // blocked before using dq. |
| 3905 DCHECK(is_const_pool_blocked() || (num_pending_32_bit_constants_ == 0)); | 3898 DCHECK(is_const_pool_blocked() || pending_32_bit_constants_.empty()); |
| 3906 DCHECK(is_const_pool_blocked() || (num_pending_64_bit_constants_ == 0)); | 3899 DCHECK(is_const_pool_blocked() || pending_64_bit_constants_.empty()); |
| 3907 CheckBuffer(); | 3900 CheckBuffer(); |
| 3908 *reinterpret_cast<uint64_t*>(pc_) = value; | 3901 *reinterpret_cast<uint64_t*>(pc_) = value; |
| 3909 pc_ += sizeof(uint64_t); | 3902 pc_ += sizeof(uint64_t); |
| 3910 } | 3903 } |
| 3911 | 3904 |
| 3912 | 3905 |
| 3913 void Assembler::emit_code_stub_address(Code* stub) { | 3906 void Assembler::emit_code_stub_address(Code* stub) { |
| 3914 CheckBuffer(); | 3907 CheckBuffer(); |
| 3915 *reinterpret_cast<uint32_t*>(pc_) = | 3908 *reinterpret_cast<uint32_t*>(pc_) = |
| 3916 reinterpret_cast<uint32_t>(stub->instruction_start()); | 3909 reinterpret_cast<uint32_t>(stub->instruction_start()); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3937 | 3930 |
| 3938 ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position, | 3931 ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position, |
| 3939 RelocInfo::Mode rmode, | 3932 RelocInfo::Mode rmode, |
| 3940 intptr_t value) { | 3933 intptr_t value) { |
| 3941 DCHECK(rmode != RelocInfo::COMMENT && rmode != RelocInfo::POSITION && | 3934 DCHECK(rmode != RelocInfo::COMMENT && rmode != RelocInfo::POSITION && |
| 3942 rmode != RelocInfo::STATEMENT_POSITION && | 3935 rmode != RelocInfo::STATEMENT_POSITION && |
| 3943 rmode != RelocInfo::CONST_POOL && rmode != RelocInfo::NONE64); | 3936 rmode != RelocInfo::CONST_POOL && rmode != RelocInfo::NONE64); |
| 3944 bool sharing_ok = RelocInfo::IsNone(rmode) || | 3937 bool sharing_ok = RelocInfo::IsNone(rmode) || |
| 3945 !(serializer_enabled() || rmode < RelocInfo::CELL); | 3938 !(serializer_enabled() || rmode < RelocInfo::CELL); |
| 3946 if (FLAG_enable_embedded_constant_pool) { | 3939 if (FLAG_enable_embedded_constant_pool) { |
| 3947 return constant_pool_builder_.AddEntry(position, value, sharing_ok); | 3940 return constant_pool_builder_.AddEntry(position, value, sharing_ok, rmode); |
| 3948 } else { | 3941 } else { |
| 3949 DCHECK(num_pending_32_bit_constants_ < kMaxNumPending32Constants); | 3942 DCHECK(pending_32_bit_constants_.size() < kMaxNumPending32Constants); |
| 3950 if (num_pending_32_bit_constants_ == 0) { | 3943 if (pending_32_bit_constants_.empty()) { |
| 3951 first_const_pool_32_use_ = position; | 3944 first_const_pool_32_use_ = position; |
| 3952 } else if (num_pending_32_bit_constants_ == kMinNumPendingConstants && | 3945 } else if (pending_32_bit_constants_.size() == kMinNumPendingConstants) { |
| 3953 pending_32_bit_constants_ == | 3946 pending_32_bit_constants_.reserve(kMaxNumPending32Constants); |
| 3954 &pending_32_bit_constants_buffer_[0]) { | |
| 3955 // Inline buffer is full, switch to dynamically allocated buffer. | |
| 3956 pending_32_bit_constants_ = | |
| 3957 new ConstantPoolEntry[kMaxNumPending32Constants]; | |
| 3958 std::copy(&pending_32_bit_constants_buffer_[0], | |
| 3959 &pending_32_bit_constants_buffer_[kMinNumPendingConstants], | |
| 3960 &pending_32_bit_constants_[0]); | |
| 3961 } | 3947 } |
| 3962 ConstantPoolEntry entry(position, value, sharing_ok); | 3948 ConstantPoolEntry entry(position, value, sharing_ok, rmode); |
| 3963 pending_32_bit_constants_[num_pending_32_bit_constants_++] = entry; | 3949 pending_32_bit_constants_.push_back(entry); |
| 3964 | 3950 |
| 3965 // Make sure the constant pool is not emitted in place of the next | 3951 // Make sure the constant pool is not emitted in place of the next |
| 3966 // instruction for which we just recorded relocation info. | 3952 // instruction for which we just recorded relocation info. |
| 3967 BlockConstPoolFor(1); | 3953 BlockConstPoolFor(1); |
| 3968 return ConstantPoolEntry::REGULAR; | 3954 return ConstantPoolEntry::REGULAR; |
| 3969 } | 3955 } |
| 3970 } | 3956 } |
| 3971 | 3957 |
| 3972 | 3958 |
| 3973 ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position, | 3959 ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position, |
| 3974 double value) { | 3960 double value) { |
| 3975 if (FLAG_enable_embedded_constant_pool) { | 3961 if (FLAG_enable_embedded_constant_pool) { |
| 3976 return constant_pool_builder_.AddEntry(position, value); | 3962 return constant_pool_builder_.AddEntry(position, value); |
| 3977 } else { | 3963 } else { |
| 3978 DCHECK(num_pending_64_bit_constants_ < kMaxNumPending64Constants); | 3964 DCHECK(pending_64_bit_constants_.size() < kMaxNumPending64Constants); |
| 3979 if (num_pending_64_bit_constants_ == 0) { | 3965 if (pending_64_bit_constants_.empty()) { |
| 3980 first_const_pool_64_use_ = position; | 3966 first_const_pool_64_use_ = position; |
| 3981 } else if (num_pending_64_bit_constants_ == kMinNumPendingConstants && | 3967 } else if (pending_64_bit_constants_.size() == kMinNumPendingConstants) { |
| 3982 pending_64_bit_constants_ == | |
| 3983 &pending_64_bit_constants_buffer_[0]) { | |
| 3984 // Inline buffer is full, switch to dynamically allocated buffer. | 3968 // Inline buffer is full, switch to dynamically allocated buffer. |
| 3985 pending_64_bit_constants_ = | 3969 pending_64_bit_constants_.reserve(kMaxNumPending64Constants); |
| 3986 new ConstantPoolEntry[kMaxNumPending64Constants]; | |
| 3987 std::copy(&pending_64_bit_constants_buffer_[0], | |
| 3988 &pending_64_bit_constants_buffer_[kMinNumPendingConstants], | |
| 3989 &pending_64_bit_constants_[0]); | |
| 3990 } | 3970 } |
| 3991 ConstantPoolEntry entry(position, value); | 3971 ConstantPoolEntry entry(position, value); |
| 3992 pending_64_bit_constants_[num_pending_64_bit_constants_++] = entry; | 3972 pending_64_bit_constants_.push_back(entry); |
| 3993 | 3973 |
| 3994 // Make sure the constant pool is not emitted in place of the next | 3974 // Make sure the constant pool is not emitted in place of the next |
| 3995 // instruction for which we just recorded relocation info. | 3975 // instruction for which we just recorded relocation info. |
| 3996 BlockConstPoolFor(1); | 3976 BlockConstPoolFor(1); |
| 3997 return ConstantPoolEntry::REGULAR; | 3977 return ConstantPoolEntry::REGULAR; |
| 3998 } | 3978 } |
| 3999 } | 3979 } |
| 4000 | 3980 |
| 4001 | 3981 |
| 4002 void Assembler::BlockConstPoolFor(int instructions) { | 3982 void Assembler::BlockConstPoolFor(int instructions) { |
| 4003 if (FLAG_enable_embedded_constant_pool) { | 3983 if (FLAG_enable_embedded_constant_pool) { |
| 4004 // Should be a no-op if using an embedded constant pool. | 3984 // Should be a no-op if using an embedded constant pool. |
| 4005 DCHECK(num_pending_32_bit_constants_ == 0); | 3985 DCHECK(pending_32_bit_constants_.empty()); |
| 4006 DCHECK(num_pending_64_bit_constants_ == 0); | 3986 DCHECK(pending_64_bit_constants_.empty()); |
| 4007 return; | 3987 return; |
| 4008 } | 3988 } |
| 4009 | 3989 |
| 4010 int pc_limit = pc_offset() + instructions * kInstrSize; | 3990 int pc_limit = pc_offset() + instructions * kInstrSize; |
| 4011 if (no_const_pool_before_ < pc_limit) { | 3991 if (no_const_pool_before_ < pc_limit) { |
| 4012 // Max pool start (if we need a jump and an alignment). | 3992 // Max pool start (if we need a jump and an alignment). |
| 4013 #ifdef DEBUG | 3993 #ifdef DEBUG |
| 4014 int start = pc_limit + kInstrSize + 2 * kPointerSize; | 3994 int start = pc_limit + kInstrSize + 2 * kPointerSize; |
| 4015 DCHECK((num_pending_32_bit_constants_ == 0) || | 3995 DCHECK(pending_32_bit_constants_.empty() || |
| 4016 (start - first_const_pool_32_use_ + | 3996 (start - first_const_pool_32_use_ + |
| 4017 num_pending_64_bit_constants_ * kDoubleSize < | 3997 pending_64_bit_constants_.size() * kDoubleSize < |
| 4018 kMaxDistToIntPool)); | 3998 kMaxDistToIntPool)); |
| 4019 DCHECK((num_pending_64_bit_constants_ == 0) || | 3999 DCHECK(pending_64_bit_constants_.empty() || |
| 4020 (start - first_const_pool_64_use_ < kMaxDistToFPPool)); | 4000 (start - first_const_pool_64_use_ < kMaxDistToFPPool)); |
| 4021 #endif | 4001 #endif |
| 4022 no_const_pool_before_ = pc_limit; | 4002 no_const_pool_before_ = pc_limit; |
| 4023 } | 4003 } |
| 4024 | 4004 |
| 4025 if (next_buffer_check_ < no_const_pool_before_) { | 4005 if (next_buffer_check_ < no_const_pool_before_) { |
| 4026 next_buffer_check_ = no_const_pool_before_; | 4006 next_buffer_check_ = no_const_pool_before_; |
| 4027 } | 4007 } |
| 4028 } | 4008 } |
| 4029 | 4009 |
| 4030 | 4010 |
| 4031 void Assembler::CheckConstPool(bool force_emit, bool require_jump) { | 4011 void Assembler::CheckConstPool(bool force_emit, bool require_jump) { |
| 4032 if (FLAG_enable_embedded_constant_pool) { | 4012 if (FLAG_enable_embedded_constant_pool) { |
| 4033 // Should be a no-op if using an embedded constant pool. | 4013 // Should be a no-op if using an embedded constant pool. |
| 4034 DCHECK(num_pending_32_bit_constants_ == 0); | 4014 DCHECK(pending_32_bit_constants_.empty()); |
| 4035 DCHECK(num_pending_64_bit_constants_ == 0); | 4015 DCHECK(pending_64_bit_constants_.empty()); |
| 4036 return; | 4016 return; |
| 4037 } | 4017 } |
| 4038 | 4018 |
| 4039 // Some short sequence of instruction mustn't be broken up by constant pool | 4019 // Some short sequence of instruction mustn't be broken up by constant pool |
| 4040 // emission, such sequences are protected by calls to BlockConstPoolFor and | 4020 // emission, such sequences are protected by calls to BlockConstPoolFor and |
| 4041 // BlockConstPoolScope. | 4021 // BlockConstPoolScope. |
| 4042 if (is_const_pool_blocked()) { | 4022 if (is_const_pool_blocked()) { |
| 4043 // Something is wrong if emission is forced and blocked at the same time. | 4023 // Something is wrong if emission is forced and blocked at the same time. |
| 4044 DCHECK(!force_emit); | 4024 DCHECK(!force_emit); |
| 4045 return; | 4025 return; |
| 4046 } | 4026 } |
| 4047 | 4027 |
| 4048 // There is nothing to do if there are no pending constant pool entries. | 4028 // There is nothing to do if there are no pending constant pool entries. |
| 4049 if ((num_pending_32_bit_constants_ == 0) && | 4029 if (pending_32_bit_constants_.empty() && pending_64_bit_constants_.empty()) { |
| 4050 (num_pending_64_bit_constants_ == 0)) { | |
| 4051 // Calculate the offset of the next check. | 4030 // Calculate the offset of the next check. |
| 4052 next_buffer_check_ = pc_offset() + kCheckPoolInterval; | 4031 next_buffer_check_ = pc_offset() + kCheckPoolInterval; |
| 4053 return; | 4032 return; |
| 4054 } | 4033 } |
| 4055 | 4034 |
| 4056 // Check that the code buffer is large enough before emitting the constant | 4035 // Check that the code buffer is large enough before emitting the constant |
| 4057 // pool (include the jump over the pool and the constant pool marker and | 4036 // pool (include the jump over the pool and the constant pool marker and |
| 4058 // the gap to the relocation information). | 4037 // the gap to the relocation information). |
| 4059 int jump_instr = require_jump ? kInstrSize : 0; | 4038 int jump_instr = require_jump ? kInstrSize : 0; |
| 4060 int size_up_to_marker = jump_instr + kInstrSize; | 4039 int size_up_to_marker = jump_instr + kInstrSize; |
| 4061 int estimated_size_after_marker = | 4040 int estimated_size_after_marker = |
| 4062 num_pending_32_bit_constants_ * kPointerSize; | 4041 pending_32_bit_constants_.size() * kPointerSize; |
| 4063 bool has_int_values = (num_pending_32_bit_constants_ > 0); | 4042 bool has_int_values = !pending_32_bit_constants_.empty(); |
| 4064 bool has_fp_values = (num_pending_64_bit_constants_ > 0); | 4043 bool has_fp_values = !pending_64_bit_constants_.empty(); |
| 4065 bool require_64_bit_align = false; | 4044 bool require_64_bit_align = false; |
| 4066 if (has_fp_values) { | 4045 if (has_fp_values) { |
| 4067 require_64_bit_align = | 4046 require_64_bit_align = |
| 4068 !IsAligned(reinterpret_cast<intptr_t>(pc_ + size_up_to_marker), | 4047 !IsAligned(reinterpret_cast<intptr_t>(pc_ + size_up_to_marker), |
| 4069 kDoubleAlignment); | 4048 kDoubleAlignment); |
| 4070 if (require_64_bit_align) { | 4049 if (require_64_bit_align) { |
| 4071 estimated_size_after_marker += kInstrSize; | 4050 estimated_size_after_marker += kInstrSize; |
| 4072 } | 4051 } |
| 4073 estimated_size_after_marker += num_pending_64_bit_constants_ * kDoubleSize; | 4052 estimated_size_after_marker += |
| 4053 pending_64_bit_constants_.size() * kDoubleSize; |
| 4074 } | 4054 } |
| 4075 int estimated_size = size_up_to_marker + estimated_size_after_marker; | 4055 int estimated_size = size_up_to_marker + estimated_size_after_marker; |
| 4076 | 4056 |
| 4077 // We emit a constant pool when: | 4057 // We emit a constant pool when: |
| 4078 // * requested to do so by parameter force_emit (e.g. after each function). | 4058 // * requested to do so by parameter force_emit (e.g. after each function). |
| 4079 // * the distance from the first instruction accessing the constant pool to | 4059 // * the distance from the first instruction accessing the constant pool to |
| 4080 // any of the constant pool entries will exceed its limit the next | 4060 // any of the constant pool entries will exceed its limit the next |
| 4081 // time the pool is checked. This is overly restrictive, but we don't emit | 4061 // time the pool is checked. This is overly restrictive, but we don't emit |
| 4082 // constant pool entries in-order so it's conservatively correct. | 4062 // constant pool entries in-order so it's conservatively correct. |
| 4083 // * the instruction doesn't require a jump after itself to jump over the | 4063 // * the instruction doesn't require a jump after itself to jump over the |
| 4084 // constant pool, and we're getting close to running out of range. | 4064 // constant pool, and we're getting close to running out of range. |
| 4085 if (!force_emit) { | 4065 if (!force_emit) { |
| 4086 DCHECK(has_fp_values || has_int_values); | 4066 DCHECK(has_fp_values || has_int_values); |
| 4087 bool need_emit = false; | 4067 bool need_emit = false; |
| 4088 if (has_fp_values) { | 4068 if (has_fp_values) { |
| 4089 // The 64-bit constants are always emitted before the 32-bit constants, so | 4069 // The 64-bit constants are always emitted before the 32-bit constants, so |
| 4090 // we can ignore the effect of the 32-bit constants on estimated_size. | 4070 // we can ignore the effect of the 32-bit constants on estimated_size. |
| 4091 int dist64 = pc_offset() + estimated_size - | 4071 int dist64 = pc_offset() + estimated_size - |
| 4092 num_pending_32_bit_constants_ * kPointerSize - | 4072 pending_32_bit_constants_.size() * kPointerSize - |
| 4093 first_const_pool_64_use_; | 4073 first_const_pool_64_use_; |
| 4094 if ((dist64 >= kMaxDistToFPPool - kCheckPoolInterval) || | 4074 if ((dist64 >= kMaxDistToFPPool - kCheckPoolInterval) || |
| 4095 (!require_jump && (dist64 >= kMaxDistToFPPool / 2))) { | 4075 (!require_jump && (dist64 >= kMaxDistToFPPool / 2))) { |
| 4096 need_emit = true; | 4076 need_emit = true; |
| 4097 } | 4077 } |
| 4098 } | 4078 } |
| 4099 if (has_int_values) { | 4079 if (has_int_values) { |
| 4100 int dist32 = pc_offset() + estimated_size - first_const_pool_32_use_; | 4080 int dist32 = pc_offset() + estimated_size - first_const_pool_32_use_; |
| 4101 if ((dist32 >= kMaxDistToIntPool - kCheckPoolInterval) || | 4081 if ((dist32 >= kMaxDistToIntPool - kCheckPoolInterval) || |
| 4102 (!require_jump && (dist32 >= kMaxDistToIntPool / 2))) { | 4082 (!require_jump && (dist32 >= kMaxDistToIntPool / 2))) { |
| 4103 need_emit = true; | 4083 need_emit = true; |
| 4104 } | 4084 } |
| 4105 } | 4085 } |
| 4106 if (!need_emit) return; | 4086 if (!need_emit) return; |
| 4107 } | 4087 } |
| 4108 | 4088 |
| 4109 // Deduplicate constants. | 4089 // Deduplicate constants. |
| 4110 int size_after_marker = estimated_size_after_marker; | 4090 int size_after_marker = estimated_size_after_marker; |
| 4111 for (int i = 0; i < num_pending_64_bit_constants_; i++) { | 4091 for (int i = 0; i < pending_64_bit_constants_.size(); i++) { |
| 4112 ConstantPoolEntry& entry = pending_64_bit_constants_[i]; | 4092 ConstantPoolEntry& entry = pending_64_bit_constants_[i]; |
| 4113 DCHECK(!entry.is_merged()); | 4093 DCHECK(!entry.is_merged()); |
| 4114 for (int j = 0; j < i; j++) { | 4094 for (int j = 0; j < i; j++) { |
| 4115 if (entry.value64() == pending_64_bit_constants_[j].value64()) { | 4095 if (entry.value64() == pending_64_bit_constants_[j].value64()) { |
| 4116 DCHECK(!pending_64_bit_constants_[j].is_merged()); | 4096 DCHECK(!pending_64_bit_constants_[j].is_merged()); |
| 4117 entry.set_merged_index(j); | 4097 entry.set_merged_index(j); |
| 4118 size_after_marker -= kDoubleSize; | 4098 size_after_marker -= kDoubleSize; |
| 4119 break; | 4099 break; |
| 4120 } | 4100 } |
| 4121 } | 4101 } |
| 4122 } | 4102 } |
| 4123 | 4103 |
| 4124 for (int i = 0; i < num_pending_32_bit_constants_; i++) { | 4104 for (int i = 0; i < pending_32_bit_constants_.size(); i++) { |
| 4125 ConstantPoolEntry& entry = pending_32_bit_constants_[i]; | 4105 ConstantPoolEntry& entry = pending_32_bit_constants_[i]; |
| 4126 DCHECK(!entry.is_merged()); | 4106 DCHECK(!entry.is_merged()); |
| 4127 if (!entry.sharing_ok()) continue; | 4107 if (!entry.sharing_ok()) continue; |
| 4128 for (int j = 0; j < i; j++) { | 4108 for (int j = 0; j < i; j++) { |
| 4129 if (entry.value() == pending_32_bit_constants_[j].value()) { | 4109 if (entry.MayBeMergedWith(pending_32_bit_constants_[j])) { |
| 4130 DCHECK(!pending_32_bit_constants_[j].is_merged()); | 4110 DCHECK(!pending_32_bit_constants_[j].is_merged()); |
| 4131 entry.set_merged_index(j); | 4111 entry.set_merged_index(j); |
| 4132 size_after_marker -= kPointerSize; | 4112 size_after_marker -= kPointerSize; |
| 4133 break; | 4113 break; |
| 4134 } | 4114 } |
| 4135 } | 4115 } |
| 4136 } | 4116 } |
| 4137 | 4117 |
| 4138 int size = size_up_to_marker + size_after_marker; | 4118 int size = size_up_to_marker + size_after_marker; |
| 4139 | 4119 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 4159 // The data size helps disassembly know what to print. | 4139 // The data size helps disassembly know what to print. |
| 4160 emit(kConstantPoolMarker | | 4140 emit(kConstantPoolMarker | |
| 4161 EncodeConstantPoolLength(size_after_marker / kPointerSize)); | 4141 EncodeConstantPoolLength(size_after_marker / kPointerSize)); |
| 4162 | 4142 |
| 4163 if (require_64_bit_align) { | 4143 if (require_64_bit_align) { |
| 4164 emit(kConstantPoolMarker); | 4144 emit(kConstantPoolMarker); |
| 4165 } | 4145 } |
| 4166 | 4146 |
| 4167 // Emit 64-bit constant pool entries first: their range is smaller than | 4147 // Emit 64-bit constant pool entries first: their range is smaller than |
| 4168 // 32-bit entries. | 4148 // 32-bit entries. |
| 4169 for (int i = 0; i < num_pending_64_bit_constants_; i++) { | 4149 for (int i = 0; i < pending_64_bit_constants_.size(); i++) { |
| 4170 ConstantPoolEntry& entry = pending_64_bit_constants_[i]; | 4150 ConstantPoolEntry& entry = pending_64_bit_constants_[i]; |
| 4171 | 4151 |
| 4172 Instr instr = instr_at(entry.position()); | 4152 Instr instr = instr_at(entry.position()); |
| 4173 // Instruction to patch must be 'vldr rd, [pc, #offset]' with offset == 0. | 4153 // Instruction to patch must be 'vldr rd, [pc, #offset]' with offset == 0. |
| 4174 DCHECK((IsVldrDPcImmediateOffset(instr) && | 4154 DCHECK((IsVldrDPcImmediateOffset(instr) && |
| 4175 GetVldrDRegisterImmediateOffset(instr) == 0)); | 4155 GetVldrDRegisterImmediateOffset(instr) == 0)); |
| 4176 | 4156 |
| 4177 int delta = pc_offset() - entry.position() - kPcLoadDelta; | 4157 int delta = pc_offset() - entry.position() - kPcLoadDelta; |
| 4178 DCHECK(is_uint10(delta)); | 4158 DCHECK(is_uint10(delta)); |
| 4179 | 4159 |
| 4180 if (entry.is_merged()) { | 4160 if (entry.is_merged()) { |
| 4181 ConstantPoolEntry& merged = | 4161 ConstantPoolEntry& merged = |
| 4182 pending_64_bit_constants_[entry.merged_index()]; | 4162 pending_64_bit_constants_[entry.merged_index()]; |
| 4183 DCHECK(entry.value64() == merged.value64()); | 4163 DCHECK(entry.value64() == merged.value64()); |
| 4184 Instr merged_instr = instr_at(merged.position()); | 4164 Instr merged_instr = instr_at(merged.position()); |
| 4185 DCHECK(IsVldrDPcImmediateOffset(merged_instr)); | 4165 DCHECK(IsVldrDPcImmediateOffset(merged_instr)); |
| 4186 delta = GetVldrDRegisterImmediateOffset(merged_instr); | 4166 delta = GetVldrDRegisterImmediateOffset(merged_instr); |
| 4187 delta += merged.position() - entry.position(); | 4167 delta += merged.position() - entry.position(); |
| 4188 } | 4168 } |
| 4189 instr_at_put(entry.position(), | 4169 instr_at_put(entry.position(), |
| 4190 SetVldrDRegisterImmediateOffset(instr, delta)); | 4170 SetVldrDRegisterImmediateOffset(instr, delta)); |
| 4191 if (!entry.is_merged()) { | 4171 if (!entry.is_merged()) { |
| 4192 DCHECK(IsAligned(reinterpret_cast<intptr_t>(pc_), kDoubleAlignment)); | 4172 DCHECK(IsAligned(reinterpret_cast<intptr_t>(pc_), kDoubleAlignment)); |
| 4193 dq(entry.value64()); | 4173 dq(entry.value64()); |
| 4194 } | 4174 } |
| 4195 } | 4175 } |
| 4196 | 4176 |
| 4197 // Emit 32-bit constant pool entries. | 4177 // Emit 32-bit constant pool entries. |
| 4198 for (int i = 0; i < num_pending_32_bit_constants_; i++) { | 4178 for (int i = 0; i < pending_32_bit_constants_.size(); i++) { |
| 4199 ConstantPoolEntry& entry = pending_32_bit_constants_[i]; | 4179 ConstantPoolEntry& entry = pending_32_bit_constants_[i]; |
| 4200 Instr instr = instr_at(entry.position()); | 4180 Instr instr = instr_at(entry.position()); |
| 4201 | 4181 |
| 4202 // 64-bit loads shouldn't get here. | 4182 // 64-bit loads shouldn't get here. |
| 4203 DCHECK(!IsVldrDPcImmediateOffset(instr)); | 4183 DCHECK(!IsVldrDPcImmediateOffset(instr)); |
| 4204 DCHECK(!IsMovW(instr)); | 4184 DCHECK(!IsMovW(instr)); |
| 4205 DCHECK(IsLdrPcImmediateOffset(instr) && | 4185 DCHECK(IsLdrPcImmediateOffset(instr) && |
| 4206 GetLdrRegisterImmediateOffset(instr) == 0); | 4186 GetLdrRegisterImmediateOffset(instr) == 0); |
| 4207 | 4187 |
| 4208 int delta = pc_offset() - entry.position() - kPcLoadDelta; | 4188 int delta = pc_offset() - entry.position() - kPcLoadDelta; |
| 4209 DCHECK(is_uint12(delta)); | 4189 DCHECK(is_uint12(delta)); |
| 4210 // 0 is the smallest delta: | 4190 // 0 is the smallest delta: |
| 4211 // ldr rd, [pc, #0] | 4191 // ldr rd, [pc, #0] |
| 4212 // constant pool marker | 4192 // constant pool marker |
| 4213 // data | 4193 // data |
| 4214 | 4194 |
| 4215 if (entry.is_merged()) { | 4195 if (entry.is_merged()) { |
| 4216 DCHECK(entry.sharing_ok()); | 4196 DCHECK(entry.sharing_ok()); |
| 4217 ConstantPoolEntry& merged = | 4197 ConstantPoolEntry& merged = |
| 4218 pending_32_bit_constants_[entry.merged_index()]; | 4198 pending_32_bit_constants_[entry.merged_index()]; |
| 4219 DCHECK(entry.value() == merged.value()); | 4199 DCHECK(entry.MayBeMergedWith(merged)); |
| 4220 Instr merged_instr = instr_at(merged.position()); | 4200 Instr merged_instr = instr_at(merged.position()); |
| 4221 DCHECK(IsLdrPcImmediateOffset(merged_instr)); | 4201 DCHECK(IsLdrPcImmediateOffset(merged_instr)); |
| 4222 delta = GetLdrRegisterImmediateOffset(merged_instr); | 4202 delta = GetLdrRegisterImmediateOffset(merged_instr); |
| 4223 delta += merged.position() - entry.position(); | 4203 delta += merged.position() - entry.position(); |
| 4224 } | 4204 } |
| 4225 instr_at_put(entry.position(), | 4205 instr_at_put(entry.position(), |
| 4226 SetLdrRegisterImmediateOffset(instr, delta)); | 4206 SetLdrRegisterImmediateOffset(instr, delta)); |
| 4227 if (!entry.is_merged()) { | 4207 if (!entry.is_merged()) { |
| 4228 emit(entry.value()); | 4208 emit(entry.value()); |
| 4229 } | 4209 } |
| 4230 } | 4210 } |
| 4231 | 4211 |
| 4232 num_pending_32_bit_constants_ = 0; | 4212 pending_32_bit_constants_.clear(); |
| 4233 num_pending_64_bit_constants_ = 0; | 4213 pending_64_bit_constants_.clear(); |
| 4234 first_const_pool_32_use_ = -1; | 4214 first_const_pool_32_use_ = -1; |
| 4235 first_const_pool_64_use_ = -1; | 4215 first_const_pool_64_use_ = -1; |
| 4236 | 4216 |
| 4237 RecordComment("]"); | 4217 RecordComment("]"); |
| 4238 | 4218 |
| 4239 DCHECK_EQ(size, SizeOfCodeGeneratedSince(&size_check)); | 4219 DCHECK_EQ(size, SizeOfCodeGeneratedSince(&size_check)); |
| 4240 | 4220 |
| 4241 if (after_pool.is_linked()) { | 4221 if (after_pool.is_linked()) { |
| 4242 bind(&after_pool); | 4222 bind(&after_pool); |
| 4243 } | 4223 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4300 DCHECK(is_uint12(offset)); | 4280 DCHECK(is_uint12(offset)); |
| 4301 instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset)); | 4281 instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset)); |
| 4302 } | 4282 } |
| 4303 } | 4283 } |
| 4304 | 4284 |
| 4305 | 4285 |
| 4306 } // namespace internal | 4286 } // namespace internal |
| 4307 } // namespace v8 | 4287 } // namespace v8 |
| 4308 | 4288 |
| 4309 #endif // V8_TARGET_ARCH_ARM | 4289 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |