| 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 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 set_dispr(disp, rmode); | 260 set_dispr(disp, rmode); |
| 261 } | 261 } |
| 262 | 262 |
| 263 | 263 |
| 264 bool Operand::is_reg(Register reg) const { | 264 bool Operand::is_reg(Register reg) const { |
| 265 return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only. | 265 return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only. |
| 266 && ((buf_[0] & 0x07) == reg.code()); // register codes match. | 266 && ((buf_[0] & 0x07) == reg.code()); // register codes match. |
| 267 } | 267 } |
| 268 | 268 |
| 269 // ----------------------------------------------------------------------------- | 269 // ----------------------------------------------------------------------------- |
| 270 // Implementation of Assembler | 270 // Implementation of Assembler. |
| 271 | 271 |
| 272 // Emit a single byte. Must always be inlined. | 272 // Emit a single byte. Must always be inlined. |
| 273 #define EMIT(x) \ | 273 #define EMIT(x) \ |
| 274 *pc_++ = (x) | 274 *pc_++ = (x) |
| 275 | 275 |
| 276 | 276 |
| 277 #ifdef GENERATED_CODE_COVERAGE | 277 #ifdef GENERATED_CODE_COVERAGE |
| 278 static void InitCoverageLog(); | 278 static void InitCoverageLog(); |
| 279 #endif | 279 #endif |
| 280 | 280 |
| 281 // spare_buffer_ | 281 // Spare buffer. |
| 282 byte* Assembler::spare_buffer_ = NULL; | 282 byte* Assembler::spare_buffer_ = NULL; |
| 283 | 283 |
| 284 Assembler::Assembler(void* buffer, int buffer_size) { | 284 Assembler::Assembler(void* buffer, int buffer_size) { |
| 285 if (buffer == NULL) { | 285 if (buffer == NULL) { |
| 286 // do our own buffer management | 286 // Do our own buffer management. |
| 287 if (buffer_size <= kMinimalBufferSize) { | 287 if (buffer_size <= kMinimalBufferSize) { |
| 288 buffer_size = kMinimalBufferSize; | 288 buffer_size = kMinimalBufferSize; |
| 289 | 289 |
| 290 if (spare_buffer_ != NULL) { | 290 if (spare_buffer_ != NULL) { |
| 291 buffer = spare_buffer_; | 291 buffer = spare_buffer_; |
| 292 spare_buffer_ = NULL; | 292 spare_buffer_ = NULL; |
| 293 } | 293 } |
| 294 } | 294 } |
| 295 if (buffer == NULL) { | 295 if (buffer == NULL) { |
| 296 buffer_ = NewArray<byte>(buffer_size); | 296 buffer_ = NewArray<byte>(buffer_size); |
| 297 } else { | 297 } else { |
| 298 buffer_ = static_cast<byte*>(buffer); | 298 buffer_ = static_cast<byte*>(buffer); |
| 299 } | 299 } |
| 300 buffer_size_ = buffer_size; | 300 buffer_size_ = buffer_size; |
| 301 own_buffer_ = true; | 301 own_buffer_ = true; |
| 302 } else { | 302 } else { |
| 303 // use externally provided buffer instead | 303 // Use externally provided buffer instead. |
| 304 ASSERT(buffer_size > 0); | 304 ASSERT(buffer_size > 0); |
| 305 buffer_ = static_cast<byte*>(buffer); | 305 buffer_ = static_cast<byte*>(buffer); |
| 306 buffer_size_ = buffer_size; | 306 buffer_size_ = buffer_size; |
| 307 own_buffer_ = false; | 307 own_buffer_ = false; |
| 308 } | 308 } |
| 309 | 309 |
| 310 // Clear the buffer in debug mode unless it was provided by the | 310 // Clear the buffer in debug mode unless it was provided by the |
| 311 // caller in which case we can't be sure it's okay to overwrite | 311 // caller in which case we can't be sure it's okay to overwrite |
| 312 // existing code in it; see CodePatcher::CodePatcher(...). | 312 // existing code in it; see CodePatcher::CodePatcher(...). |
| 313 #ifdef DEBUG | 313 #ifdef DEBUG |
| 314 if (own_buffer_) { | 314 if (own_buffer_) { |
| 315 memset(buffer_, 0xCC, buffer_size); // int3 | 315 memset(buffer_, 0xCC, buffer_size); // int3 |
| 316 } | 316 } |
| 317 #endif | 317 #endif |
| 318 | 318 |
| 319 // setup buffer pointers | 319 // Setup buffer pointers. |
| 320 ASSERT(buffer_ != NULL); | 320 ASSERT(buffer_ != NULL); |
| 321 pc_ = buffer_; | 321 pc_ = buffer_; |
| 322 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); | 322 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); |
| 323 | 323 |
| 324 last_pc_ = NULL; | 324 last_pc_ = NULL; |
| 325 current_statement_position_ = RelocInfo::kNoPosition; | 325 current_statement_position_ = RelocInfo::kNoPosition; |
| 326 current_position_ = RelocInfo::kNoPosition; | 326 current_position_ = RelocInfo::kNoPosition; |
| 327 written_statement_position_ = current_statement_position_; | 327 written_statement_position_ = current_statement_position_; |
| 328 written_position_ = current_position_; | 328 written_position_ = current_position_; |
| 329 #ifdef GENERATED_CODE_COVERAGE | 329 #ifdef GENERATED_CODE_COVERAGE |
| 330 InitCoverageLog(); | 330 InitCoverageLog(); |
| 331 #endif | 331 #endif |
| 332 } | 332 } |
| 333 | 333 |
| 334 | 334 |
| 335 Assembler::~Assembler() { | 335 Assembler::~Assembler() { |
| 336 if (own_buffer_) { | 336 if (own_buffer_) { |
| 337 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { | 337 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { |
| 338 spare_buffer_ = buffer_; | 338 spare_buffer_ = buffer_; |
| 339 } else { | 339 } else { |
| 340 DeleteArray(buffer_); | 340 DeleteArray(buffer_); |
| 341 } | 341 } |
| 342 } | 342 } |
| 343 } | 343 } |
| 344 | 344 |
| 345 | 345 |
| 346 void Assembler::GetCode(CodeDesc* desc) { | 346 void Assembler::GetCode(CodeDesc* desc) { |
| 347 // finalize code | 347 // Finalize code (at this point overflow() may be true, but the gap ensures |
| 348 // (at this point overflow() may be true, but the gap ensures that | 348 // that we are still not overlapping instructions and relocation info). |
| 349 // we are still not overlapping instructions and relocation info) | 349 ASSERT(pc_ <= reloc_info_writer.pos()); // No overlap. |
| 350 ASSERT(pc_ <= reloc_info_writer.pos()); // no overlap | 350 // Setup code descriptor. |
| 351 // setup desc | |
| 352 desc->buffer = buffer_; | 351 desc->buffer = buffer_; |
| 353 desc->buffer_size = buffer_size_; | 352 desc->buffer_size = buffer_size_; |
| 354 desc->instr_size = pc_offset(); | 353 desc->instr_size = pc_offset(); |
| 355 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); | 354 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); |
| 356 desc->origin = this; | 355 desc->origin = this; |
| 357 | 356 |
| 358 Counters::reloc_info_size.Increment(desc->reloc_size); | 357 Counters::reloc_info_size.Increment(desc->reloc_size); |
| 359 } | 358 } |
| 360 | 359 |
| 361 | 360 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 EnsureSpace ensure_space(this); | 427 EnsureSpace ensure_space(this); |
| 429 last_pc_ = pc_; | 428 last_pc_ = pc_; |
| 430 EMIT(0xFF); | 429 EMIT(0xFF); |
| 431 emit_operand(esi, src); | 430 emit_operand(esi, src); |
| 432 } | 431 } |
| 433 | 432 |
| 434 | 433 |
| 435 void Assembler::pop(Register dst) { | 434 void Assembler::pop(Register dst) { |
| 436 ASSERT(reloc_info_writer.last_pc() != NULL); | 435 ASSERT(reloc_info_writer.last_pc() != NULL); |
| 437 if (FLAG_push_pop_elimination && (reloc_info_writer.last_pc() <= last_pc_)) { | 436 if (FLAG_push_pop_elimination && (reloc_info_writer.last_pc() <= last_pc_)) { |
| 438 // (last_pc_ != NULL) is rolled into the above check | 437 // (last_pc_ != NULL) is rolled into the above check. |
| 439 // If a last_pc_ is set, we need to make sure that there has not been any | 438 // If a last_pc_ is set, we need to make sure that there has not been any |
| 440 // relocation information generated between the last instruction and this | 439 // relocation information generated between the last instruction and this |
| 441 // pop instruction. | 440 // pop instruction. |
| 442 byte instr = last_pc_[0]; | 441 byte instr = last_pc_[0]; |
| 443 if ((instr & ~0x7) == 0x50) { | 442 if ((instr & ~0x7) == 0x50) { |
| 444 int push_reg_code = instr & 0x7; | 443 int push_reg_code = instr & 0x7; |
| 445 if (push_reg_code == dst.code()) { | 444 if (push_reg_code == dst.code()) { |
| 446 pc_ = last_pc_; | 445 pc_ = last_pc_; |
| 447 if (FLAG_print_push_pop_elimination) { | 446 if (FLAG_print_push_pop_elimination) { |
| 448 PrintF("%d push/pop (same reg) eliminated\n", pc_offset()); | 447 PrintF("%d push/pop (same reg) eliminated\n", pc_offset()); |
| 449 } | 448 } |
| 450 } else { | 449 } else { |
| 451 // Convert 'push src; pop dst' to 'mov dst, src'. | 450 // Convert 'push src; pop dst' to 'mov dst, src'. |
| 452 last_pc_[0] = 0x8b; | 451 last_pc_[0] = 0x8b; |
| 453 Register src = { push_reg_code }; | 452 Register src = { push_reg_code }; |
| 454 EnsureSpace ensure_space(this); | 453 EnsureSpace ensure_space(this); |
| 455 emit_operand(dst, Operand(src)); | 454 emit_operand(dst, Operand(src)); |
| 456 if (FLAG_print_push_pop_elimination) { | 455 if (FLAG_print_push_pop_elimination) { |
| 457 PrintF("%d push/pop (reg->reg) eliminated\n", pc_offset()); | 456 PrintF("%d push/pop (reg->reg) eliminated\n", pc_offset()); |
| 458 } | 457 } |
| 459 } | 458 } |
| 460 last_pc_ = NULL; | 459 last_pc_ = NULL; |
| 461 return; | 460 return; |
| 462 } else if (instr == 0xff) { // push of an operand, convert to a move | 461 } else if (instr == 0xff) { // push of an operand, convert to a move |
| 463 byte op1 = last_pc_[1]; | 462 byte op1 = last_pc_[1]; |
| 464 // Check if the operation is really a push | 463 // Check if the operation is really a push. |
| 465 if ((op1 & 0x38) == (6 << 3)) { | 464 if ((op1 & 0x38) == (6 << 3)) { |
| 466 op1 = (op1 & ~0x38) | static_cast<byte>(dst.code() << 3); | 465 op1 = (op1 & ~0x38) | static_cast<byte>(dst.code() << 3); |
| 467 last_pc_[0] = 0x8b; | 466 last_pc_[0] = 0x8b; |
| 468 last_pc_[1] = op1; | 467 last_pc_[1] = op1; |
| 469 last_pc_ = NULL; | 468 last_pc_ = NULL; |
| 470 if (FLAG_print_push_pop_elimination) { | 469 if (FLAG_print_push_pop_elimination) { |
| 471 PrintF("%d push/pop (op->reg) eliminated\n", pc_offset()); | 470 PrintF("%d push/pop (op->reg) eliminated\n", pc_offset()); |
| 472 } | 471 } |
| 473 return; | 472 return; |
| 474 } | 473 } |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 740 USE(cc); | 739 USE(cc); |
| 741 USE(dst); | 740 USE(dst); |
| 742 USE(handle); | 741 USE(handle); |
| 743 } | 742 } |
| 744 | 743 |
| 745 | 744 |
| 746 void Assembler::cmov(Condition cc, Register dst, const Operand& src) { | 745 void Assembler::cmov(Condition cc, Register dst, const Operand& src) { |
| 747 ASSERT(CpuFeatures::IsEnabled(CMOV)); | 746 ASSERT(CpuFeatures::IsEnabled(CMOV)); |
| 748 EnsureSpace ensure_space(this); | 747 EnsureSpace ensure_space(this); |
| 749 last_pc_ = pc_; | 748 last_pc_ = pc_; |
| 750 // Opcode: 0f 40 + cc /r | 749 // Opcode: 0f 40 + cc /r. |
| 751 EMIT(0x0F); | 750 EMIT(0x0F); |
| 752 EMIT(0x40 + cc); | 751 EMIT(0x40 + cc); |
| 753 emit_operand(dst, src); | 752 emit_operand(dst, src); |
| 754 } | 753 } |
| 755 | 754 |
| 756 | 755 |
| 757 void Assembler::rep_movs() { | 756 void Assembler::rep_movs() { |
| 758 EnsureSpace ensure_space(this); | 757 EnsureSpace ensure_space(this); |
| 759 last_pc_ = pc_; | 758 last_pc_ = pc_; |
| 760 EMIT(0xF3); | 759 EMIT(0xF3); |
| 761 EMIT(0xA5); | 760 EMIT(0xA5); |
| 762 } | 761 } |
| 763 | 762 |
| 764 | 763 |
| 765 void Assembler::xchg(Register dst, Register src) { | 764 void Assembler::xchg(Register dst, Register src) { |
| 766 EnsureSpace ensure_space(this); | 765 EnsureSpace ensure_space(this); |
| 767 last_pc_ = pc_; | 766 last_pc_ = pc_; |
| 768 if (src.is(eax) || dst.is(eax)) { // Single-byte encoding | 767 if (src.is(eax) || dst.is(eax)) { // Single-byte encoding. |
| 769 EMIT(0x90 | (src.is(eax) ? dst.code() : src.code())); | 768 EMIT(0x90 | (src.is(eax) ? dst.code() : src.code())); |
| 770 } else { | 769 } else { |
| 771 EMIT(0x87); | 770 EMIT(0x87); |
| 772 EMIT(0xC0 | src.code() << 3 | dst.code()); | 771 EMIT(0xC0 | src.code() << 3 | dst.code()); |
| 773 } | 772 } |
| 774 } | 773 } |
| 775 | 774 |
| 776 | 775 |
| 777 void Assembler::adc(Register dst, int32_t imm32) { | 776 void Assembler::adc(Register dst, int32_t imm32) { |
| 778 EnsureSpace ensure_space(this); | 777 EnsureSpace ensure_space(this); |
| (...skipping 648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1427 while (L->is_linked()) { | 1426 while (L->is_linked()) { |
| 1428 Displacement disp = disp_at(L); | 1427 Displacement disp = disp_at(L); |
| 1429 int fixup_pos = L->pos(); | 1428 int fixup_pos = L->pos(); |
| 1430 if (disp.type() == Displacement::CODE_RELATIVE) { | 1429 if (disp.type() == Displacement::CODE_RELATIVE) { |
| 1431 // Relative to Code* heap object pointer. | 1430 // Relative to Code* heap object pointer. |
| 1432 long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag); | 1431 long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag); |
| 1433 } else { | 1432 } else { |
| 1434 if (disp.type() == Displacement::UNCONDITIONAL_JUMP) { | 1433 if (disp.type() == Displacement::UNCONDITIONAL_JUMP) { |
| 1435 ASSERT(byte_at(fixup_pos - 1) == 0xE9); // jmp expected | 1434 ASSERT(byte_at(fixup_pos - 1) == 0xE9); // jmp expected |
| 1436 } | 1435 } |
| 1437 // relative address, relative to point after address | 1436 // Relative address, relative to point after address. |
| 1438 int imm32 = pos - (fixup_pos + sizeof(int32_t)); | 1437 int imm32 = pos - (fixup_pos + sizeof(int32_t)); |
| 1439 long_at_put(fixup_pos, imm32); | 1438 long_at_put(fixup_pos, imm32); |
| 1440 } | 1439 } |
| 1441 disp.next(L); | 1440 disp.next(L); |
| 1442 } | 1441 } |
| 1443 L->bind_to(pos); | 1442 L->bind_to(pos); |
| 1444 } | 1443 } |
| 1445 | 1444 |
| 1446 | 1445 |
| 1447 void Assembler::link_to(Label* L, Label* appendix) { | 1446 void Assembler::link_to(Label* L, Label* appendix) { |
| 1448 EnsureSpace ensure_space(this); | 1447 EnsureSpace ensure_space(this); |
| 1449 last_pc_ = NULL; | 1448 last_pc_ = NULL; |
| 1450 if (appendix->is_linked()) { | 1449 if (appendix->is_linked()) { |
| 1451 if (L->is_linked()) { | 1450 if (L->is_linked()) { |
| 1452 // append appendix to L's list | 1451 // Append appendix to L's list. |
| 1453 Label p; | 1452 Label p; |
| 1454 Label q = *L; | 1453 Label q = *L; |
| 1455 do { | 1454 do { |
| 1456 p = q; | 1455 p = q; |
| 1457 Displacement disp = disp_at(&q); | 1456 Displacement disp = disp_at(&q); |
| 1458 disp.next(&q); | 1457 disp.next(&q); |
| 1459 } while (q.is_linked()); | 1458 } while (q.is_linked()); |
| 1460 Displacement disp = disp_at(&p); | 1459 Displacement disp = disp_at(&p); |
| 1461 disp.link_to(appendix); | 1460 disp.link_to(appendix); |
| 1462 disp_at_put(&p, disp); | 1461 disp_at_put(&p, disp); |
| 1463 p.Unuse(); // to avoid assertion failure in ~Label | 1462 p.Unuse(); // to avoid assertion failure in ~Label |
| 1464 } else { | 1463 } else { |
| 1465 // L is empty, simply use appendix | 1464 // L is empty, simply use appendix. |
| 1466 *L = *appendix; | 1465 *L = *appendix; |
| 1467 } | 1466 } |
| 1468 } | 1467 } |
| 1469 appendix->Unuse(); // appendix should not be used anymore | 1468 appendix->Unuse(); // appendix should not be used anymore |
| 1470 } | 1469 } |
| 1471 | 1470 |
| 1472 | 1471 |
| 1473 void Assembler::bind(Label* L) { | 1472 void Assembler::bind(Label* L) { |
| 1474 EnsureSpace ensure_space(this); | 1473 EnsureSpace ensure_space(this); |
| 1475 last_pc_ = NULL; | 1474 last_pc_ = NULL; |
| 1476 ASSERT(!L->is_bound()); // label can only be bound once | 1475 ASSERT(!L->is_bound()); // label can only be bound once |
| 1477 bind_to(L, pc_offset()); | 1476 bind_to(L, pc_offset()); |
| 1478 } | 1477 } |
| 1479 | 1478 |
| 1480 | 1479 |
| 1481 void Assembler::call(Label* L) { | 1480 void Assembler::call(Label* L) { |
| 1482 EnsureSpace ensure_space(this); | 1481 EnsureSpace ensure_space(this); |
| 1483 last_pc_ = pc_; | 1482 last_pc_ = pc_; |
| 1484 if (L->is_bound()) { | 1483 if (L->is_bound()) { |
| 1485 const int long_size = 5; | 1484 const int long_size = 5; |
| 1486 int offs = L->pos() - pc_offset(); | 1485 int offs = L->pos() - pc_offset(); |
| 1487 ASSERT(offs <= 0); | 1486 ASSERT(offs <= 0); |
| 1488 // 1110 1000 #32-bit disp | 1487 // 1110 1000 #32-bit disp. |
| 1489 EMIT(0xE8); | 1488 EMIT(0xE8); |
| 1490 emit(offs - long_size); | 1489 emit(offs - long_size); |
| 1491 } else { | 1490 } else { |
| 1492 // 1110 1000 #32-bit disp | 1491 // 1110 1000 #32-bit disp. |
| 1493 EMIT(0xE8); | 1492 EMIT(0xE8); |
| 1494 emit_disp(L, Displacement::OTHER); | 1493 emit_disp(L, Displacement::OTHER); |
| 1495 } | 1494 } |
| 1496 } | 1495 } |
| 1497 | 1496 |
| 1498 | 1497 |
| 1499 void Assembler::call(byte* entry, RelocInfo::Mode rmode) { | 1498 void Assembler::call(byte* entry, RelocInfo::Mode rmode) { |
| 1500 EnsureSpace ensure_space(this); | 1499 EnsureSpace ensure_space(this); |
| 1501 last_pc_ = pc_; | 1500 last_pc_ = pc_; |
| 1502 ASSERT(!RelocInfo::IsCodeTarget(rmode)); | 1501 ASSERT(!RelocInfo::IsCodeTarget(rmode)); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1525 | 1524 |
| 1526 void Assembler::jmp(Label* L) { | 1525 void Assembler::jmp(Label* L) { |
| 1527 EnsureSpace ensure_space(this); | 1526 EnsureSpace ensure_space(this); |
| 1528 last_pc_ = pc_; | 1527 last_pc_ = pc_; |
| 1529 if (L->is_bound()) { | 1528 if (L->is_bound()) { |
| 1530 const int short_size = 2; | 1529 const int short_size = 2; |
| 1531 const int long_size = 5; | 1530 const int long_size = 5; |
| 1532 int offs = L->pos() - pc_offset(); | 1531 int offs = L->pos() - pc_offset(); |
| 1533 ASSERT(offs <= 0); | 1532 ASSERT(offs <= 0); |
| 1534 if (is_int8(offs - short_size)) { | 1533 if (is_int8(offs - short_size)) { |
| 1535 // 1110 1011 #8-bit disp | 1534 // 1110 1011 #8-bit disp. |
| 1536 EMIT(0xEB); | 1535 EMIT(0xEB); |
| 1537 EMIT((offs - short_size) & 0xFF); | 1536 EMIT((offs - short_size) & 0xFF); |
| 1538 } else { | 1537 } else { |
| 1539 // 1110 1001 #32-bit disp | 1538 // 1110 1001 #32-bit disp. |
| 1540 EMIT(0xE9); | 1539 EMIT(0xE9); |
| 1541 emit(offs - long_size); | 1540 emit(offs - long_size); |
| 1542 } | 1541 } |
| 1543 } else { | 1542 } else { |
| 1544 // 1110 1001 #32-bit disp | 1543 // 1110 1001 #32-bit disp. |
| 1545 EMIT(0xE9); | 1544 EMIT(0xE9); |
| 1546 emit_disp(L, Displacement::UNCONDITIONAL_JUMP); | 1545 emit_disp(L, Displacement::UNCONDITIONAL_JUMP); |
| 1547 } | 1546 } |
| 1548 } | 1547 } |
| 1549 | 1548 |
| 1550 | 1549 |
| 1551 void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) { | 1550 void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) { |
| 1552 EnsureSpace ensure_space(this); | 1551 EnsureSpace ensure_space(this); |
| 1553 last_pc_ = pc_; | 1552 last_pc_ = pc_; |
| 1554 ASSERT(!RelocInfo::IsCodeTarget(rmode)); | 1553 ASSERT(!RelocInfo::IsCodeTarget(rmode)); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1604 emit_disp(L, Displacement::OTHER); | 1603 emit_disp(L, Displacement::OTHER); |
| 1605 } | 1604 } |
| 1606 } | 1605 } |
| 1607 | 1606 |
| 1608 | 1607 |
| 1609 void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint) { | 1608 void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint) { |
| 1610 EnsureSpace ensure_space(this); | 1609 EnsureSpace ensure_space(this); |
| 1611 last_pc_ = pc_; | 1610 last_pc_ = pc_; |
| 1612 ASSERT((0 <= cc) && (cc < 16)); | 1611 ASSERT((0 <= cc) && (cc < 16)); |
| 1613 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint); | 1612 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint); |
| 1614 // 0000 1111 1000 tttn #32-bit disp | 1613 // 0000 1111 1000 tttn #32-bit disp. |
| 1615 EMIT(0x0F); | 1614 EMIT(0x0F); |
| 1616 EMIT(0x80 | cc); | 1615 EMIT(0x80 | cc); |
| 1617 emit(entry - (pc_ + sizeof(int32_t)), rmode); | 1616 emit(entry - (pc_ + sizeof(int32_t)), rmode); |
| 1618 } | 1617 } |
| 1619 | 1618 |
| 1620 | 1619 |
| 1621 void Assembler::j(Condition cc, Handle<Code> code, Hint hint) { | 1620 void Assembler::j(Condition cc, Handle<Code> code, Hint hint) { |
| 1622 EnsureSpace ensure_space(this); | 1621 EnsureSpace ensure_space(this); |
| 1623 last_pc_ = pc_; | 1622 last_pc_ = pc_; |
| 1624 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint); | 1623 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint); |
| 1625 // 0000 1111 1000 tttn #32-bit disp | 1624 // 0000 1111 1000 tttn #32-bit disp |
| 1626 EMIT(0x0F); | 1625 EMIT(0x0F); |
| 1627 EMIT(0x80 | cc); | 1626 EMIT(0x80 | cc); |
| 1628 emit(reinterpret_cast<intptr_t>(code.location()), RelocInfo::CODE_TARGET); | 1627 emit(reinterpret_cast<intptr_t>(code.location()), RelocInfo::CODE_TARGET); |
| 1629 } | 1628 } |
| 1630 | 1629 |
| 1631 | 1630 |
| 1632 // FPU instructions | 1631 // FPU instructions. |
| 1633 | 1632 |
| 1634 void Assembler::fld(int i) { | 1633 void Assembler::fld(int i) { |
| 1635 EnsureSpace ensure_space(this); | 1634 EnsureSpace ensure_space(this); |
| 1636 last_pc_ = pc_; | 1635 last_pc_ = pc_; |
| 1637 emit_farith(0xD9, 0xC0, i); | 1636 emit_farith(0xD9, 0xC0, i); |
| 1638 } | 1637 } |
| 1639 | 1638 |
| 1640 | 1639 |
| 1641 void Assembler::fld1() { | 1640 void Assembler::fld1() { |
| 1642 EnsureSpace ensure_space(this); | 1641 EnsureSpace ensure_space(this); |
| (...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2218 if (current_position_ != written_position_ && | 2217 if (current_position_ != written_position_ && |
| 2219 current_position_ != written_statement_position_) { | 2218 current_position_ != written_statement_position_) { |
| 2220 EnsureSpace ensure_space(this); | 2219 EnsureSpace ensure_space(this); |
| 2221 RecordRelocInfo(RelocInfo::POSITION, current_position_); | 2220 RecordRelocInfo(RelocInfo::POSITION, current_position_); |
| 2222 written_position_ = current_position_; | 2221 written_position_ = current_position_; |
| 2223 } | 2222 } |
| 2224 } | 2223 } |
| 2225 | 2224 |
| 2226 | 2225 |
| 2227 void Assembler::GrowBuffer() { | 2226 void Assembler::GrowBuffer() { |
| 2228 ASSERT(overflow()); // should not call this otherwise | 2227 ASSERT(overflow()); |
| 2229 if (!own_buffer_) FATAL("external code buffer is too small"); | 2228 if (!own_buffer_) FATAL("external code buffer is too small"); |
| 2230 | 2229 |
| 2231 // compute new buffer size | 2230 // Compute new buffer size. |
| 2232 CodeDesc desc; // the new buffer | 2231 CodeDesc desc; // the new buffer |
| 2233 if (buffer_size_ < 4*KB) { | 2232 if (buffer_size_ < 4*KB) { |
| 2234 desc.buffer_size = 4*KB; | 2233 desc.buffer_size = 4*KB; |
| 2235 } else { | 2234 } else { |
| 2236 desc.buffer_size = 2*buffer_size_; | 2235 desc.buffer_size = 2*buffer_size_; |
| 2237 } | 2236 } |
| 2238 // Some internal data structures overflow for very large buffers, | 2237 // Some internal data structures overflow for very large buffers, |
| 2239 // they must ensure that kMaximalBufferSize is not too large. | 2238 // they must ensure that kMaximalBufferSize is not too large. |
| 2240 if ((desc.buffer_size > kMaximalBufferSize) || | 2239 if ((desc.buffer_size > kMaximalBufferSize) || |
| 2241 (desc.buffer_size > Heap::MaxOldGenerationSize())) { | 2240 (desc.buffer_size > Heap::MaxOldGenerationSize())) { |
| 2242 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer"); | 2241 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer"); |
| 2243 } | 2242 } |
| 2244 | 2243 |
| 2245 // setup new buffer | 2244 // Setup new buffer. |
| 2246 desc.buffer = NewArray<byte>(desc.buffer_size); | 2245 desc.buffer = NewArray<byte>(desc.buffer_size); |
| 2247 desc.instr_size = pc_offset(); | 2246 desc.instr_size = pc_offset(); |
| 2248 desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos()); | 2247 desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos()); |
| 2249 | 2248 |
| 2250 // Clear the buffer in debug mode. Use 'int3' instructions to make | 2249 // Clear the buffer in debug mode. Use 'int3' instructions to make |
| 2251 // sure to get into problems if we ever run uninitialized code. | 2250 // sure to get into problems if we ever run uninitialized code. |
| 2252 #ifdef DEBUG | 2251 #ifdef DEBUG |
| 2253 memset(desc.buffer, 0xCC, desc.buffer_size); | 2252 memset(desc.buffer, 0xCC, desc.buffer_size); |
| 2254 #endif | 2253 #endif |
| 2255 | 2254 |
| 2256 // copy the data | 2255 // Copy the data. |
| 2257 int pc_delta = desc.buffer - buffer_; | 2256 int pc_delta = desc.buffer - buffer_; |
| 2258 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_); | 2257 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_); |
| 2259 memmove(desc.buffer, buffer_, desc.instr_size); | 2258 memmove(desc.buffer, buffer_, desc.instr_size); |
| 2260 memmove(rc_delta + reloc_info_writer.pos(), | 2259 memmove(rc_delta + reloc_info_writer.pos(), |
| 2261 reloc_info_writer.pos(), desc.reloc_size); | 2260 reloc_info_writer.pos(), desc.reloc_size); |
| 2262 | 2261 |
| 2263 // switch buffers | 2262 // Switch buffers. |
| 2264 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { | 2263 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { |
| 2265 spare_buffer_ = buffer_; | 2264 spare_buffer_ = buffer_; |
| 2266 } else { | 2265 } else { |
| 2267 DeleteArray(buffer_); | 2266 DeleteArray(buffer_); |
| 2268 } | 2267 } |
| 2269 buffer_ = desc.buffer; | 2268 buffer_ = desc.buffer; |
| 2270 buffer_size_ = desc.buffer_size; | 2269 buffer_size_ = desc.buffer_size; |
| 2271 pc_ += pc_delta; | 2270 pc_ += pc_delta; |
| 2272 if (last_pc_ != NULL) { | 2271 if (last_pc_ != NULL) { |
| 2273 last_pc_ += pc_delta; | 2272 last_pc_ += pc_delta; |
| 2274 } | 2273 } |
| 2275 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, | 2274 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, |
| 2276 reloc_info_writer.last_pc() + pc_delta); | 2275 reloc_info_writer.last_pc() + pc_delta); |
| 2277 | 2276 |
| 2278 // relocate runtime entries | 2277 // Relocate runtime entries. |
| 2279 for (RelocIterator it(desc); !it.done(); it.next()) { | 2278 for (RelocIterator it(desc); !it.done(); it.next()) { |
| 2280 RelocInfo::Mode rmode = it.rinfo()->rmode(); | 2279 RelocInfo::Mode rmode = it.rinfo()->rmode(); |
| 2281 if (rmode == RelocInfo::RUNTIME_ENTRY) { | 2280 if (rmode == RelocInfo::RUNTIME_ENTRY) { |
| 2282 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc()); | 2281 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc()); |
| 2283 *p -= pc_delta; // relocate entry | 2282 *p -= pc_delta; // relocate entry |
| 2284 } else if (rmode == RelocInfo::INTERNAL_REFERENCE) { | 2283 } else if (rmode == RelocInfo::INTERNAL_REFERENCE) { |
| 2285 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc()); | 2284 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc()); |
| 2286 if (*p != 0) { // 0 means uninitialized. | 2285 if (*p != 0) { // 0 means uninitialized. |
| 2287 *p += pc_delta; | 2286 *p += pc_delta; |
| 2288 } | 2287 } |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2392 push_insn[1] = 13; // Skip over coverage insns. | 2391 push_insn[1] = 13; // Skip over coverage insns. |
| 2393 if (coverage_log != NULL) { | 2392 if (coverage_log != NULL) { |
| 2394 fprintf(coverage_log, "%s\n", file_line); | 2393 fprintf(coverage_log, "%s\n", file_line); |
| 2395 fflush(coverage_log); | 2394 fflush(coverage_log); |
| 2396 } | 2395 } |
| 2397 } | 2396 } |
| 2398 | 2397 |
| 2399 #endif | 2398 #endif |
| 2400 | 2399 |
| 2401 } } // namespace v8::internal | 2400 } } // namespace v8::internal |
| OLD | NEW |