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 |