| 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 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 if (kDebug && own_buffer_) { | 309 if (kDebug && own_buffer_) { |
| 310 memset(buffer_, 0xCC, buffer_size); // int3 | 310 memset(buffer_, 0xCC, buffer_size); // int3 |
| 311 } | 311 } |
| 312 | 312 |
| 313 // setup buffer pointers | 313 // setup buffer pointers |
| 314 ASSERT(buffer_ != NULL); | 314 ASSERT(buffer_ != NULL); |
| 315 pc_ = buffer_; | 315 pc_ = buffer_; |
| 316 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); | 316 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); |
| 317 | 317 |
| 318 last_pc_ = NULL; | 318 last_pc_ = NULL; |
| 319 last_bound_pos_ = 0; | |
| 320 last_position_ = RelocInfo::kNoPosition; | 319 last_position_ = RelocInfo::kNoPosition; |
| 321 last_statement_position_ = RelocInfo::kNoPosition; | 320 last_statement_position_ = RelocInfo::kNoPosition; |
| 322 } | 321 } |
| 323 | 322 |
| 324 | 323 |
| 325 Assembler::~Assembler() { | 324 Assembler::~Assembler() { |
| 326 if (own_buffer_) { | 325 if (own_buffer_) { |
| 327 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { | 326 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { |
| 328 spare_buffer_ = buffer_; | 327 spare_buffer_ = buffer_; |
| 329 } else { | 328 } else { |
| 330 DeleteArray(buffer_); | 329 DeleteArray(buffer_); |
| 331 } | 330 } |
| 332 } | 331 } |
| 333 } | 332 } |
| 334 | 333 |
| 335 | 334 |
| 336 void Assembler::GetCode(CodeDesc* desc) { | 335 void Assembler::GetCode(CodeDesc* desc) { |
| 337 // finalize code | 336 // finalize code |
| 338 if (unbound_label_.is_linked()) | |
| 339 bind_to(&unbound_label_, binding_pos_); | |
| 340 | |
| 341 // (at this point overflow() may be true, but the gap ensures that | 337 // (at this point overflow() may be true, but the gap ensures that |
| 342 // we are still not overlapping instructions and relocation info) | 338 // we are still not overlapping instructions and relocation info) |
| 343 ASSERT(pc_ <= reloc_info_writer.pos()); // no overlap | 339 ASSERT(pc_ <= reloc_info_writer.pos()); // no overlap |
| 344 // setup desc | 340 // setup desc |
| 345 desc->buffer = buffer_; | 341 desc->buffer = buffer_; |
| 346 desc->buffer_size = buffer_size_; | 342 desc->buffer_size = buffer_size_; |
| 347 desc->instr_size = pc_offset(); | 343 desc->instr_size = pc_offset(); |
| 348 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); | 344 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); |
| 349 | 345 |
| 350 Counters::reloc_info_size.Increment(desc->reloc_size); | 346 Counters::reloc_info_size.Increment(desc->reloc_size); |
| (...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1222 int fixup_pos = L->pos(); | 1218 int fixup_pos = L->pos(); |
| 1223 if (disp.type() == Displacement::UNCONDITIONAL_JUMP) { | 1219 if (disp.type() == Displacement::UNCONDITIONAL_JUMP) { |
| 1224 ASSERT(byte_at(fixup_pos - 1) == 0xE9); // jmp expected | 1220 ASSERT(byte_at(fixup_pos - 1) == 0xE9); // jmp expected |
| 1225 } | 1221 } |
| 1226 // relative address, relative to point after address | 1222 // relative address, relative to point after address |
| 1227 int imm32 = pos - (fixup_pos + sizeof(int32_t)); | 1223 int imm32 = pos - (fixup_pos + sizeof(int32_t)); |
| 1228 long_at_put(fixup_pos, imm32); | 1224 long_at_put(fixup_pos, imm32); |
| 1229 disp.next(L); | 1225 disp.next(L); |
| 1230 } | 1226 } |
| 1231 L->bind_to(pos); | 1227 L->bind_to(pos); |
| 1232 | |
| 1233 // do not eliminate jump instructions before the last bound position | |
| 1234 if (pos > last_bound_pos_) | |
| 1235 last_bound_pos_ = pos; | |
| 1236 } | 1228 } |
| 1237 | 1229 |
| 1238 | 1230 |
| 1239 void Assembler::link_to(Label* L, Label* appendix) { | 1231 void Assembler::link_to(Label* L, Label* appendix) { |
| 1240 EnsureSpace ensure_space(this); | 1232 EnsureSpace ensure_space(this); |
| 1241 last_pc_ = NULL; | 1233 last_pc_ = NULL; |
| 1242 if (appendix->is_linked()) { | 1234 if (appendix->is_linked()) { |
| 1243 if (L->is_linked()) { | 1235 if (L->is_linked()) { |
| 1244 // append appendix to L's list | 1236 // append appendix to L's list |
| 1245 Label p; | 1237 Label p; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1259 } | 1251 } |
| 1260 } | 1252 } |
| 1261 appendix->Unuse(); // appendix should not be used anymore | 1253 appendix->Unuse(); // appendix should not be used anymore |
| 1262 } | 1254 } |
| 1263 | 1255 |
| 1264 | 1256 |
| 1265 void Assembler::bind(Label* L) { | 1257 void Assembler::bind(Label* L) { |
| 1266 EnsureSpace ensure_space(this); | 1258 EnsureSpace ensure_space(this); |
| 1267 last_pc_ = NULL; | 1259 last_pc_ = NULL; |
| 1268 ASSERT(!L->is_bound()); // label can only be bound once | 1260 ASSERT(!L->is_bound()); // label can only be bound once |
| 1269 if (FLAG_eliminate_jumps) { | |
| 1270 // Resolve unbound label. | |
| 1271 if (unbound_label_.is_linked()) { | |
| 1272 // Unbound label exists => link it with L if same binding | |
| 1273 // position, otherwise fix it. | |
| 1274 if (binding_pos_ == pc_offset()) { | |
| 1275 // Link it to L's list. | |
| 1276 link_to(L, &unbound_label_); | |
| 1277 } else { | |
| 1278 // Otherwise bind unbound label. | |
| 1279 ASSERT(binding_pos_ < pc_offset()); | |
| 1280 bind_to(&unbound_label_, binding_pos_); | |
| 1281 } | |
| 1282 } | |
| 1283 ASSERT(!unbound_label_.is_linked()); | |
| 1284 // try to eliminate jumps to next instruction | |
| 1285 const int absolute_jump_size = 5; | |
| 1286 // Do not remove an already bound jump target. | |
| 1287 while (last_bound_pos_ < pc_offset() && | |
| 1288 reloc_info_writer.last_pc() <= pc_ - absolute_jump_size && | |
| 1289 L->is_linked() && | |
| 1290 (L->pos() + static_cast<int>(sizeof(int32_t)) == pc_offset()) && | |
| 1291 (disp_at(L).type() == Displacement::UNCONDITIONAL_JUMP)) { | |
| 1292 // Previous instruction is jump jumping immediately after it => | |
| 1293 // eliminate it. | |
| 1294 // jmp expected. | |
| 1295 ASSERT(byte_at(pc_offset() - absolute_jump_size) == 0xE9); | |
| 1296 if (FLAG_print_jump_elimination) { | |
| 1297 PrintF("@ %d jump to next eliminated\n", L->pos()); | |
| 1298 } | |
| 1299 // Remove first entry from label list. | |
| 1300 Displacement disp = disp_at(L); | |
| 1301 disp.next(L); | |
| 1302 // Eliminate instruction (set code pointers back). | |
| 1303 pc_ -= absolute_jump_size; | |
| 1304 // Make sure not to skip relocation information when rewinding. | |
| 1305 ASSERT(reloc_info_writer.last_pc() <= pc_); | |
| 1306 } | |
| 1307 // Delay fixup of L => store it as unbound label. | |
| 1308 unbound_label_ = *L; | |
| 1309 binding_pos_ = pc_offset(); | |
| 1310 L->Unuse(); | |
| 1311 } | |
| 1312 bind_to(L, pc_offset()); | 1261 bind_to(L, pc_offset()); |
| 1313 } | 1262 } |
| 1314 | 1263 |
| 1315 | 1264 |
| 1316 void Assembler::call(Label* L) { | 1265 void Assembler::call(Label* L) { |
| 1317 EnsureSpace ensure_space(this); | 1266 EnsureSpace ensure_space(this); |
| 1318 last_pc_ = pc_; | 1267 last_pc_ = pc_; |
| 1319 if (L->is_bound()) { | 1268 if (L->is_bound()) { |
| 1320 const int long_size = 5; | 1269 const int long_size = 5; |
| 1321 int offs = L->pos() - pc_offset(); | 1270 int offs = L->pos() - pc_offset(); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1369 if (is_int8(offs - short_size)) { | 1318 if (is_int8(offs - short_size)) { |
| 1370 // 1110 1011 #8-bit disp | 1319 // 1110 1011 #8-bit disp |
| 1371 EMIT(0xEB); | 1320 EMIT(0xEB); |
| 1372 EMIT((offs - short_size) & 0xFF); | 1321 EMIT((offs - short_size) & 0xFF); |
| 1373 } else { | 1322 } else { |
| 1374 // 1110 1001 #32-bit disp | 1323 // 1110 1001 #32-bit disp |
| 1375 EMIT(0xE9); | 1324 EMIT(0xE9); |
| 1376 emit(offs - long_size); | 1325 emit(offs - long_size); |
| 1377 } | 1326 } |
| 1378 } else { | 1327 } else { |
| 1379 if (FLAG_eliminate_jumps && | |
| 1380 unbound_label_.is_linked() && | |
| 1381 binding_pos_ == pc_offset()) { | |
| 1382 // Current position is target of jumps | |
| 1383 if (FLAG_print_jump_elimination) { | |
| 1384 PrintF("eliminated jumps/calls to %d from ", binding_pos_); | |
| 1385 print(&unbound_label_); | |
| 1386 } | |
| 1387 link_to(L, &unbound_label_); | |
| 1388 } | |
| 1389 // 1110 1001 #32-bit disp | 1328 // 1110 1001 #32-bit disp |
| 1390 EMIT(0xE9); | 1329 EMIT(0xE9); |
| 1391 emit_disp(L, Displacement::UNCONDITIONAL_JUMP); | 1330 emit_disp(L, Displacement::UNCONDITIONAL_JUMP); |
| 1392 } | 1331 } |
| 1393 } | 1332 } |
| 1394 | 1333 |
| 1395 | 1334 |
| 1396 void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) { | 1335 void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) { |
| 1397 EnsureSpace ensure_space(this); | 1336 EnsureSpace ensure_space(this); |
| 1398 last_pc_ = pc_; | 1337 last_pc_ = pc_; |
| (...skipping 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2082 ASSERT(bound_label.is_bound()); | 2021 ASSERT(bound_label.is_bound()); |
| 2083 ASSERT(0 <= position); | 2022 ASSERT(0 <= position); |
| 2084 ASSERT(position + static_cast<int>(sizeof(uint32_t)) <= pc_offset()); | 2023 ASSERT(position + static_cast<int>(sizeof(uint32_t)) <= pc_offset()); |
| 2085 ASSERT(long_at(position) == 0); // only initialize once! | 2024 ASSERT(long_at(position) == 0); // only initialize once! |
| 2086 | 2025 |
| 2087 uint32_t label_loc = reinterpret_cast<uint32_t>(addr_at(bound_label.pos())); | 2026 uint32_t label_loc = reinterpret_cast<uint32_t>(addr_at(bound_label.pos())); |
| 2088 long_at_put(position, label_loc); | 2027 long_at_put(position, label_loc); |
| 2089 } | 2028 } |
| 2090 | 2029 |
| 2091 } } // namespace v8::internal | 2030 } } // namespace v8::internal |
| OLD | NEW |