| 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 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 *m = code_ & 0x1; | 160 *m = code_ & 0x1; |
| 161 *vm = code_ >> 1; | 161 *vm = code_ >> 1; |
| 162 } | 162 } |
| 163 | 163 |
| 164 int code_; | 164 int code_; |
| 165 }; | 165 }; |
| 166 | 166 |
| 167 | 167 |
| 168 // Double word VFP register. | 168 // Double word VFP register. |
| 169 struct DwVfpRegister { | 169 struct DwVfpRegister { |
| 170 // d0 has been excluded from allocation. This is following ia32 | |
| 171 // where xmm0 is excluded. This should be revisited. | |
| 172 // Currently d0 is used as a scratch register. | |
| 173 // d1 has also been excluded from allocation to be used as a scratch | |
| 174 // register as well. | |
| 175 static const int kNumRegisters = 16; | 170 static const int kNumRegisters = 16; |
| 176 static const int kNumAllocatableRegisters = 15; | 171 // A few double registers are reserved: one as a scratch register and one to |
| 172 // hold 0.0, that does not fit in the immediate field of vmov instructions. |
| 173 // d14: 0.0 |
| 174 // d15: scratch register. |
| 175 static const int kNumReservedRegisters = 2; |
| 176 static const int kNumAllocatableRegisters = kNumRegisters - |
| 177 kNumReservedRegisters; |
| 177 | 178 |
| 178 static int ToAllocationIndex(DwVfpRegister reg) { | 179 static int ToAllocationIndex(DwVfpRegister reg) { |
| 179 ASSERT(reg.code() != 0); | 180 ASSERT(reg.code() != 0); |
| 180 return reg.code() - 1; | 181 return reg.code() - 1; |
| 181 } | 182 } |
| 182 | 183 |
| 183 static DwVfpRegister FromAllocationIndex(int index) { | 184 static DwVfpRegister FromAllocationIndex(int index) { |
| 184 ASSERT(index >= 0 && index < kNumAllocatableRegisters); | 185 ASSERT(index >= 0 && index < kNumAllocatableRegisters); |
| 185 return from_code(index + 1); | 186 return from_code(index + 1); |
| 186 } | 187 } |
| 187 | 188 |
| 188 static const char* AllocationIndexToString(int index) { | 189 static const char* AllocationIndexToString(int index) { |
| 189 ASSERT(index >= 0 && index < kNumAllocatableRegisters); | 190 ASSERT(index >= 0 && index < kNumAllocatableRegisters); |
| 190 const char* const names[] = { | 191 const char* const names[] = { |
| 192 "d0", |
| 191 "d1", | 193 "d1", |
| 192 "d2", | 194 "d2", |
| 193 "d3", | 195 "d3", |
| 194 "d4", | 196 "d4", |
| 195 "d5", | 197 "d5", |
| 196 "d6", | 198 "d6", |
| 197 "d7", | 199 "d7", |
| 198 "d8", | 200 "d8", |
| 199 "d9", | 201 "d9", |
| 200 "d10", | 202 "d10", |
| 201 "d11", | 203 "d11", |
| 202 "d12", | 204 "d12", |
| 203 "d13", | 205 "d13" |
| 204 "d14", | |
| 205 "d15" | |
| 206 }; | 206 }; |
| 207 return names[index]; | 207 return names[index]; |
| 208 } | 208 } |
| 209 | 209 |
| 210 static DwVfpRegister from_code(int code) { | 210 static DwVfpRegister from_code(int code) { |
| 211 DwVfpRegister r = { code }; | 211 DwVfpRegister r = { code }; |
| 212 return r; | 212 return r; |
| 213 } | 213 } |
| 214 | 214 |
| 215 // Supporting d0 to d15, can be later extended to d31. | 215 // Supporting d0 to d15, can be later extended to d31. |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 const DwVfpRegister d7 = { 7 }; | 296 const DwVfpRegister d7 = { 7 }; |
| 297 const DwVfpRegister d8 = { 8 }; | 297 const DwVfpRegister d8 = { 8 }; |
| 298 const DwVfpRegister d9 = { 9 }; | 298 const DwVfpRegister d9 = { 9 }; |
| 299 const DwVfpRegister d10 = { 10 }; | 299 const DwVfpRegister d10 = { 10 }; |
| 300 const DwVfpRegister d11 = { 11 }; | 300 const DwVfpRegister d11 = { 11 }; |
| 301 const DwVfpRegister d12 = { 12 }; | 301 const DwVfpRegister d12 = { 12 }; |
| 302 const DwVfpRegister d13 = { 13 }; | 302 const DwVfpRegister d13 = { 13 }; |
| 303 const DwVfpRegister d14 = { 14 }; | 303 const DwVfpRegister d14 = { 14 }; |
| 304 const DwVfpRegister d15 = { 15 }; | 304 const DwVfpRegister d15 = { 15 }; |
| 305 | 305 |
| 306 // Aliases for double registers. |
| 307 const DwVfpRegister kFirstCalleeSavedDoubleReg = d8; |
| 308 const DwVfpRegister kLastCalleeSavedDoubleReg = d15; |
| 309 const DwVfpRegister kDoubleRegZero = d14; |
| 310 |
| 306 | 311 |
| 307 // Coprocessor register | 312 // Coprocessor register |
| 308 struct CRegister { | 313 struct CRegister { |
| 309 bool is_valid() const { return 0 <= code_ && code_ < 16; } | 314 bool is_valid() const { return 0 <= code_ && code_ < 16; } |
| 310 bool is(CRegister creg) const { return code_ == creg.code_; } | 315 bool is(CRegister creg) const { return code_ == creg.code_; } |
| 311 int code() const { | 316 int code() const { |
| 312 ASSERT(is_valid()); | 317 ASSERT(is_valid()); |
| 313 return code_; | 318 return code_; |
| 314 } | 319 } |
| 315 int bit() const { | 320 int bit() const { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 // ----------------------------------------------------------------------------- | 371 // ----------------------------------------------------------------------------- |
| 367 // Machine instruction Operands | 372 // Machine instruction Operands |
| 368 | 373 |
| 369 // Class Operand represents a shifter operand in data processing instructions | 374 // Class Operand represents a shifter operand in data processing instructions |
| 370 class Operand BASE_EMBEDDED { | 375 class Operand BASE_EMBEDDED { |
| 371 public: | 376 public: |
| 372 // immediate | 377 // immediate |
| 373 INLINE(explicit Operand(int32_t immediate, | 378 INLINE(explicit Operand(int32_t immediate, |
| 374 RelocInfo::Mode rmode = RelocInfo::NONE)); | 379 RelocInfo::Mode rmode = RelocInfo::NONE)); |
| 375 INLINE(explicit Operand(const ExternalReference& f)); | 380 INLINE(explicit Operand(const ExternalReference& f)); |
| 376 INLINE(explicit Operand(const char* s)); | |
| 377 explicit Operand(Handle<Object> handle); | 381 explicit Operand(Handle<Object> handle); |
| 378 INLINE(explicit Operand(Smi* value)); | 382 INLINE(explicit Operand(Smi* value)); |
| 379 | 383 |
| 380 // rm | 384 // rm |
| 381 INLINE(explicit Operand(Register rm)); | 385 INLINE(explicit Operand(Register rm)); |
| 382 | 386 |
| 383 // rm <shift_op> shift_imm | 387 // rm <shift_op> shift_imm |
| 384 explicit Operand(Register rm, ShiftOp shift_op, int shift_imm); | 388 explicit Operand(Register rm, ShiftOp shift_op, int shift_imm); |
| 385 | 389 |
| 386 // rm <shift_op> rs | 390 // rm <shift_op> rs |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 offset_ = offset; | 448 offset_ = offset; |
| 445 } | 449 } |
| 446 | 450 |
| 447 uint32_t offset() const { | 451 uint32_t offset() const { |
| 448 ASSERT(rm_.is(no_reg)); | 452 ASSERT(rm_.is(no_reg)); |
| 449 return offset_; | 453 return offset_; |
| 450 } | 454 } |
| 451 | 455 |
| 452 Register rn() const { return rn_; } | 456 Register rn() const { return rn_; } |
| 453 Register rm() const { return rm_; } | 457 Register rm() const { return rm_; } |
| 458 AddrMode am() const { return am_; } |
| 454 | 459 |
| 455 bool OffsetIsUint12Encodable() const { | 460 bool OffsetIsUint12Encodable() const { |
| 456 return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_); | 461 return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_); |
| 457 } | 462 } |
| 458 | 463 |
| 459 private: | 464 private: |
| 460 Register rn_; // base | 465 Register rn_; // base |
| 461 Register rm_; // register offset | 466 Register rm_; // register offset |
| 462 int32_t offset_; // valid if rm_ == no_reg | 467 int32_t offset_; // valid if rm_ == no_reg |
| 463 ShiftOp shift_op_; | 468 ShiftOp shift_op_; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 493 return IsSupported(f); | 498 return IsSupported(f); |
| 494 } | 499 } |
| 495 unsigned enabled = static_cast<unsigned>(isolate->enabled_cpu_features()); | 500 unsigned enabled = static_cast<unsigned>(isolate->enabled_cpu_features()); |
| 496 return (enabled & (1u << f)) != 0; | 501 return (enabled & (1u << f)) != 0; |
| 497 } | 502 } |
| 498 #endif | 503 #endif |
| 499 | 504 |
| 500 // Enable a specified feature within a scope. | 505 // Enable a specified feature within a scope. |
| 501 class Scope BASE_EMBEDDED { | 506 class Scope BASE_EMBEDDED { |
| 502 #ifdef DEBUG | 507 #ifdef DEBUG |
| 508 |
| 503 public: | 509 public: |
| 504 explicit Scope(CpuFeature f) { | 510 explicit Scope(CpuFeature f) { |
| 505 unsigned mask = 1u << f; | 511 unsigned mask = 1u << f; |
| 506 ASSERT(CpuFeatures::IsSupported(f)); | 512 ASSERT(CpuFeatures::IsSupported(f)); |
| 507 ASSERT(!Serializer::enabled() || | 513 ASSERT(!Serializer::enabled() || |
| 508 (CpuFeatures::found_by_runtime_probing_ & mask) == 0); | 514 (CpuFeatures::found_by_runtime_probing_ & mask) == 0); |
| 509 isolate_ = Isolate::UncheckedCurrent(); | 515 isolate_ = Isolate::UncheckedCurrent(); |
| 510 old_enabled_ = 0; | 516 old_enabled_ = 0; |
| 511 if (isolate_ != NULL) { | 517 if (isolate_ != NULL) { |
| 512 old_enabled_ = static_cast<unsigned>(isolate_->enabled_cpu_features()); | 518 old_enabled_ = static_cast<unsigned>(isolate_->enabled_cpu_features()); |
| 513 isolate_->set_enabled_cpu_features(old_enabled_ | mask); | 519 isolate_->set_enabled_cpu_features(old_enabled_ | mask); |
| 514 } | 520 } |
| 515 } | 521 } |
| 516 ~Scope() { | 522 ~Scope() { |
| 517 ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_); | 523 ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_); |
| 518 if (isolate_ != NULL) { | 524 if (isolate_ != NULL) { |
| 519 isolate_->set_enabled_cpu_features(old_enabled_); | 525 isolate_->set_enabled_cpu_features(old_enabled_); |
| 520 } | 526 } |
| 521 } | 527 } |
| 528 |
| 522 private: | 529 private: |
| 523 Isolate* isolate_; | 530 Isolate* isolate_; |
| 524 unsigned old_enabled_; | 531 unsigned old_enabled_; |
| 525 #else | 532 #else |
| 533 |
| 526 public: | 534 public: |
| 527 explicit Scope(CpuFeature f) {} | 535 explicit Scope(CpuFeature f) {} |
| 528 #endif | 536 #endif |
| 529 }; | 537 }; |
| 530 | 538 |
| 531 class TryForceFeatureScope BASE_EMBEDDED { | 539 class TryForceFeatureScope BASE_EMBEDDED { |
| 532 public: | 540 public: |
| 533 explicit TryForceFeatureScope(CpuFeature f) | 541 explicit TryForceFeatureScope(CpuFeature f) |
| 534 : old_supported_(CpuFeatures::supported_) { | 542 : old_supported_(CpuFeatures::supported_) { |
| 535 if (CanForce()) { | 543 if (CanForce()) { |
| (...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1125 } | 1133 } |
| 1126 | 1134 |
| 1127 void pop() { | 1135 void pop() { |
| 1128 add(sp, sp, Operand(kPointerSize)); | 1136 add(sp, sp, Operand(kPointerSize)); |
| 1129 } | 1137 } |
| 1130 | 1138 |
| 1131 // Jump unconditionally to given label. | 1139 // Jump unconditionally to given label. |
| 1132 void jmp(Label* L) { b(L, al); } | 1140 void jmp(Label* L) { b(L, al); } |
| 1133 | 1141 |
| 1134 // Check the code size generated from label to here. | 1142 // Check the code size generated from label to here. |
| 1135 int InstructionsGeneratedSince(Label* l) { | 1143 int SizeOfCodeGeneratedSince(Label* label) { |
| 1136 return (pc_offset() - l->pos()) / kInstrSize; | 1144 return pc_offset() - label->pos(); |
| 1145 } |
| 1146 |
| 1147 // Check the number of instructions generated from label to here. |
| 1148 int InstructionsGeneratedSince(Label* label) { |
| 1149 return SizeOfCodeGeneratedSince(label) / kInstrSize; |
| 1137 } | 1150 } |
| 1138 | 1151 |
| 1139 // Check whether an immediate fits an addressing mode 1 instruction. | 1152 // Check whether an immediate fits an addressing mode 1 instruction. |
| 1140 bool ImmediateFitsAddrMode1Instruction(int32_t imm32); | 1153 bool ImmediateFitsAddrMode1Instruction(int32_t imm32); |
| 1141 | 1154 |
| 1142 // Class for scoping postponing the constant pool generation. | 1155 // Class for scoping postponing the constant pool generation. |
| 1143 class BlockConstPoolScope { | 1156 class BlockConstPoolScope { |
| 1144 public: | 1157 public: |
| 1145 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) { | 1158 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) { |
| 1146 assem_->StartBlockConstPool(); | 1159 assem_->StartBlockConstPool(); |
| 1147 } | 1160 } |
| 1148 ~BlockConstPoolScope() { | 1161 ~BlockConstPoolScope() { |
| 1149 assem_->EndBlockConstPool(); | 1162 assem_->EndBlockConstPool(); |
| 1150 } | 1163 } |
| 1151 | 1164 |
| 1152 private: | 1165 private: |
| 1153 Assembler* assem_; | 1166 Assembler* assem_; |
| 1154 | 1167 |
| 1155 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope); | 1168 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope); |
| 1156 }; | 1169 }; |
| 1157 | 1170 |
| 1158 // Postpone the generation of the constant pool for the specified number of | |
| 1159 // instructions. | |
| 1160 void BlockConstPoolFor(int instructions); | |
| 1161 | |
| 1162 // Debugging | 1171 // Debugging |
| 1163 | 1172 |
| 1164 // Mark address of the ExitJSFrame code. | 1173 // Mark address of the ExitJSFrame code. |
| 1165 void RecordJSReturn(); | 1174 void RecordJSReturn(); |
| 1166 | 1175 |
| 1167 // Mark address of a debug break slot. | 1176 // Mark address of a debug break slot. |
| 1168 void RecordDebugBreakSlot(); | 1177 void RecordDebugBreakSlot(); |
| 1169 | 1178 |
| 1170 // Record the AST id of the CallIC being compiled, so that it can be placed | 1179 // Record the AST id of the CallIC being compiled, so that it can be placed |
| 1171 // in the relocation information. | 1180 // in the relocation information. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1211 static bool IsStrRegFpNegOffset(Instr instr); | 1220 static bool IsStrRegFpNegOffset(Instr instr); |
| 1212 static bool IsLdrRegFpNegOffset(Instr instr); | 1221 static bool IsLdrRegFpNegOffset(Instr instr); |
| 1213 static bool IsLdrPcImmediateOffset(Instr instr); | 1222 static bool IsLdrPcImmediateOffset(Instr instr); |
| 1214 static bool IsTstImmediate(Instr instr); | 1223 static bool IsTstImmediate(Instr instr); |
| 1215 static bool IsCmpRegister(Instr instr); | 1224 static bool IsCmpRegister(Instr instr); |
| 1216 static bool IsCmpImmediate(Instr instr); | 1225 static bool IsCmpImmediate(Instr instr); |
| 1217 static Register GetCmpImmediateRegister(Instr instr); | 1226 static Register GetCmpImmediateRegister(Instr instr); |
| 1218 static int GetCmpImmediateRawImmediate(Instr instr); | 1227 static int GetCmpImmediateRawImmediate(Instr instr); |
| 1219 static bool IsNop(Instr instr, int type = NON_MARKING_NOP); | 1228 static bool IsNop(Instr instr, int type = NON_MARKING_NOP); |
| 1220 | 1229 |
| 1221 // Buffer size and constant pool distance are checked together at regular | |
| 1222 // intervals of kBufferCheckInterval emitted bytes | |
| 1223 static const int kBufferCheckInterval = 1*KB/2; | |
| 1224 // Constants in pools are accessed via pc relative addressing, which can | 1230 // Constants in pools are accessed via pc relative addressing, which can |
| 1225 // reach +/-4KB thereby defining a maximum distance between the instruction | 1231 // reach +/-4KB thereby defining a maximum distance between the instruction |
| 1226 // and the accessed constant. We satisfy this constraint by limiting the | 1232 // and the accessed constant. |
| 1227 // distance between pools. | 1233 static const int kMaxDistToPool = 4*KB; |
| 1228 static const int kMaxDistBetweenPools = 4*KB - 2*kBufferCheckInterval; | 1234 static const int kMaxNumPendingRelocInfo = kMaxDistToPool/kInstrSize; |
| 1229 static const int kMaxNumPRInfo = kMaxDistBetweenPools/kInstrSize; | |
| 1230 | 1235 |
| 1231 // Check if is time to emit a constant pool for pending reloc info entries | 1236 // Postpone the generation of the constant pool for the specified number of |
| 1237 // instructions. |
| 1238 void BlockConstPoolFor(int instructions); |
| 1239 |
| 1240 // Check if is time to emit a constant pool. |
| 1232 void CheckConstPool(bool force_emit, bool require_jump); | 1241 void CheckConstPool(bool force_emit, bool require_jump); |
| 1233 | 1242 |
| 1234 protected: | 1243 protected: |
| 1235 // Relocation for a type-recording IC has the AST id added to it. This | 1244 // Relocation for a type-recording IC has the AST id added to it. This |
| 1236 // member variable is a way to pass the information from the call site to | 1245 // member variable is a way to pass the information from the call site to |
| 1237 // the relocation info. | 1246 // the relocation info. |
| 1238 unsigned ast_id_for_reloc_info_; | 1247 unsigned ast_id_for_reloc_info_; |
| 1239 | 1248 |
| 1240 bool emit_debug_code() const { return emit_debug_code_; } | 1249 bool emit_debug_code() const { return emit_debug_code_; } |
| 1241 | 1250 |
| 1242 int buffer_space() const { return reloc_info_writer.pos() - pc_; } | 1251 int buffer_space() const { return reloc_info_writer.pos() - pc_; } |
| 1243 | 1252 |
| 1244 // Read/patch instructions | 1253 // Read/patch instructions |
| 1245 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } | 1254 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } |
| 1246 void instr_at_put(int pos, Instr instr) { | 1255 void instr_at_put(int pos, Instr instr) { |
| 1247 *reinterpret_cast<Instr*>(buffer_ + pos) = instr; | 1256 *reinterpret_cast<Instr*>(buffer_ + pos) = instr; |
| 1248 } | 1257 } |
| 1249 | 1258 |
| 1250 // Decode branch instruction at pos and return branch target pos | 1259 // Decode branch instruction at pos and return branch target pos |
| 1251 int target_at(int pos); | 1260 int target_at(int pos); |
| 1252 | 1261 |
| 1253 // Patch branch instruction at pos to branch to given branch target pos | 1262 // Patch branch instruction at pos to branch to given branch target pos |
| 1254 void target_at_put(int pos, int target_pos); | 1263 void target_at_put(int pos, int target_pos); |
| 1255 | 1264 |
| 1256 // Block the emission of the constant pool before pc_offset | 1265 // Prevent contant pool emission until EndBlockConstPool is called. |
| 1257 void BlockConstPoolBefore(int pc_offset) { | 1266 // Call to this function can be nested but must be followed by an equal |
| 1258 if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset; | 1267 // number of call to EndBlockConstpool. |
| 1268 void StartBlockConstPool() { |
| 1269 if (const_pool_blocked_nesting_++ == 0) { |
| 1270 // Prevent constant pool checks happening by setting the next check to |
| 1271 // the biggest possible offset. |
| 1272 next_buffer_check_ = kMaxInt; |
| 1273 } |
| 1259 } | 1274 } |
| 1260 | 1275 |
| 1261 void StartBlockConstPool() { | 1276 // Resume constant pool emission. Need to be called as many time as |
| 1262 const_pool_blocked_nesting_++; | 1277 // StartBlockConstPool to have an effect. |
| 1278 void EndBlockConstPool() { |
| 1279 if (--const_pool_blocked_nesting_ == 0) { |
| 1280 // Check the constant pool hasn't been blocked for too long. |
| 1281 ASSERT((num_pending_reloc_info_ == 0) || |
| 1282 (pc_offset() < (first_const_pool_use_ + kMaxDistToPool))); |
| 1283 // Two cases: |
| 1284 // * no_const_pool_before_ >= next_buffer_check_ and the emission is |
| 1285 // still blocked |
| 1286 // * no_const_pool_before_ < next_buffer_check_ and the next emit will |
| 1287 // trigger a check. |
| 1288 next_buffer_check_ = no_const_pool_before_; |
| 1289 } |
| 1263 } | 1290 } |
| 1264 void EndBlockConstPool() { | 1291 |
| 1265 const_pool_blocked_nesting_--; | 1292 bool is_const_pool_blocked() const { |
| 1293 return (const_pool_blocked_nesting_ > 0) || |
| 1294 (pc_offset() < no_const_pool_before_); |
| 1266 } | 1295 } |
| 1267 bool is_const_pool_blocked() const { return const_pool_blocked_nesting_ > 0; } | |
| 1268 | 1296 |
| 1269 private: | 1297 private: |
| 1270 // Code buffer: | 1298 // Code buffer: |
| 1271 // The buffer into which code and relocation info are generated. | 1299 // The buffer into which code and relocation info are generated. |
| 1272 byte* buffer_; | 1300 byte* buffer_; |
| 1273 int buffer_size_; | 1301 int buffer_size_; |
| 1274 // True if the assembler owns the buffer, false if buffer is external. | 1302 // True if the assembler owns the buffer, false if buffer is external. |
| 1275 bool own_buffer_; | 1303 bool own_buffer_; |
| 1276 | 1304 |
| 1277 int next_buffer_check_; // pc offset of next buffer check | 1305 int next_buffer_check_; // pc offset of next buffer check |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1291 // necessary to emit the constant pool before the pool gets too far from the | 1319 // necessary to emit the constant pool before the pool gets too far from the |
| 1292 // location it is accessed from. In this case, we emit a jump over the emitted | 1320 // location it is accessed from. In this case, we emit a jump over the emitted |
| 1293 // constant pool. | 1321 // constant pool. |
| 1294 // Constants in the pool may be addresses of functions that gets relocated; | 1322 // Constants in the pool may be addresses of functions that gets relocated; |
| 1295 // if so, a relocation info entry is associated to the constant pool entry. | 1323 // if so, a relocation info entry is associated to the constant pool entry. |
| 1296 | 1324 |
| 1297 // Repeated checking whether the constant pool should be emitted is rather | 1325 // Repeated checking whether the constant pool should be emitted is rather |
| 1298 // expensive. By default we only check again once a number of instructions | 1326 // expensive. By default we only check again once a number of instructions |
| 1299 // has been generated. That also means that the sizing of the buffers is not | 1327 // has been generated. That also means that the sizing of the buffers is not |
| 1300 // an exact science, and that we rely on some slop to not overrun buffers. | 1328 // an exact science, and that we rely on some slop to not overrun buffers. |
| 1301 static const int kCheckConstIntervalInst = 32; | 1329 static const int kCheckPoolIntervalInst = 32; |
| 1302 static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize; | 1330 static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize; |
| 1303 | 1331 |
| 1304 | 1332 |
| 1305 // Pools are emitted after function return and in dead code at (more or less) | 1333 // Average distance beetween a constant pool and the first instruction |
| 1306 // regular intervals of kDistBetweenPools bytes | 1334 // accessing the constant pool. Longer distance should result in less I-cache |
| 1307 static const int kDistBetweenPools = 1*KB; | 1335 // pollution. |
| 1336 // In practice the distance will be smaller since constant pool emission is |
| 1337 // forced after function return and sometimes after unconditional branches. |
| 1338 static const int kAvgDistToPool = kMaxDistToPool - kCheckPoolInterval; |
| 1308 | 1339 |
| 1309 // Emission of the constant pool may be blocked in some code sequences. | 1340 // Emission of the constant pool may be blocked in some code sequences. |
| 1310 int const_pool_blocked_nesting_; // Block emission if this is not zero. | 1341 int const_pool_blocked_nesting_; // Block emission if this is not zero. |
| 1311 int no_const_pool_before_; // Block emission before this pc offset. | 1342 int no_const_pool_before_; // Block emission before this pc offset. |
| 1312 | 1343 |
| 1313 // Keep track of the last emitted pool to guarantee a maximal distance | 1344 // Keep track of the first instruction requiring a constant pool entry |
| 1314 int last_const_pool_end_; // pc offset following the last constant pool | 1345 // since the previous constant pool was emitted. |
| 1346 int first_const_pool_use_; |
| 1315 | 1347 |
| 1316 // Relocation info generation | 1348 // Relocation info generation |
| 1317 // Each relocation is encoded as a variable size value | 1349 // Each relocation is encoded as a variable size value |
| 1318 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; | 1350 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; |
| 1319 RelocInfoWriter reloc_info_writer; | 1351 RelocInfoWriter reloc_info_writer; |
| 1352 |
| 1320 // Relocation info records are also used during code generation as temporary | 1353 // Relocation info records are also used during code generation as temporary |
| 1321 // containers for constants and code target addresses until they are emitted | 1354 // containers for constants and code target addresses until they are emitted |
| 1322 // to the constant pool. These pending relocation info records are temporarily | 1355 // to the constant pool. These pending relocation info records are temporarily |
| 1323 // stored in a separate buffer until a constant pool is emitted. | 1356 // stored in a separate buffer until a constant pool is emitted. |
| 1324 // If every instruction in a long sequence is accessing the pool, we need one | 1357 // If every instruction in a long sequence is accessing the pool, we need one |
| 1325 // pending relocation entry per instruction. | 1358 // pending relocation entry per instruction. |
| 1326 RelocInfo prinfo_[kMaxNumPRInfo]; // the buffer of pending relocation info | 1359 |
| 1327 int num_prinfo_; // number of pending reloc info entries in the buffer | 1360 // the buffer of pending relocation info |
| 1361 RelocInfo pending_reloc_info_[kMaxNumPendingRelocInfo]; |
| 1362 // number of pending reloc info entries in the buffer |
| 1363 int num_pending_reloc_info_; |
| 1328 | 1364 |
| 1329 // The bound position, before this we cannot do instruction elimination. | 1365 // The bound position, before this we cannot do instruction elimination. |
| 1330 int last_bound_pos_; | 1366 int last_bound_pos_; |
| 1331 | 1367 |
| 1332 // Code emission | 1368 // Code emission |
| 1333 inline void CheckBuffer(); | 1369 inline void CheckBuffer(); |
| 1334 void GrowBuffer(); | 1370 void GrowBuffer(); |
| 1335 inline void emit(Instr x); | 1371 inline void emit(Instr x); |
| 1336 | 1372 |
| 1337 // Instruction generation | 1373 // Instruction generation |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1366 public: | 1402 public: |
| 1367 explicit EnsureSpace(Assembler* assembler) { | 1403 explicit EnsureSpace(Assembler* assembler) { |
| 1368 assembler->CheckBuffer(); | 1404 assembler->CheckBuffer(); |
| 1369 } | 1405 } |
| 1370 }; | 1406 }; |
| 1371 | 1407 |
| 1372 | 1408 |
| 1373 } } // namespace v8::internal | 1409 } } // namespace v8::internal |
| 1374 | 1410 |
| 1375 #endif // V8_ARM_ASSEMBLER_ARM_H_ | 1411 #endif // V8_ARM_ASSEMBLER_ARM_H_ |
| OLD | NEW |