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 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) | 205 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) |
206 : AssemblerBase(isolate, buffer, buffer_size), | 206 : AssemblerBase(isolate, buffer, buffer_size), |
207 recorded_ast_id_(TypeFeedbackId::None()), | 207 recorded_ast_id_(TypeFeedbackId::None()), |
208 constant_pool_builder_(kLoadPtrMaxReachBits, kLoadDoubleMaxReachBits), | 208 constant_pool_builder_(kLoadPtrMaxReachBits, kLoadDoubleMaxReachBits), |
209 positions_recorder_(this) { | 209 positions_recorder_(this) { |
210 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); | 210 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); |
211 | 211 |
212 no_trampoline_pool_before_ = 0; | 212 no_trampoline_pool_before_ = 0; |
213 trampoline_pool_blocked_nesting_ = 0; | 213 trampoline_pool_blocked_nesting_ = 0; |
214 constant_pool_entry_sharing_blocked_nesting_ = 0; | 214 constant_pool_entry_sharing_blocked_nesting_ = 0; |
215 // We leave space (kMaxBlockTrampolineSectionSize) | 215 next_trampoline_check_ = kMaxInt; |
216 // for BlockTrampolinePoolScope buffer. | |
217 next_buffer_check_ = | |
218 FLAG_force_long_branches ? kMaxInt : kMaxCondBranchReach - | |
219 kMaxBlockTrampolineSectionSize; | |
220 internal_trampoline_exception_ = false; | 216 internal_trampoline_exception_ = false; |
221 last_bound_pos_ = 0; | 217 last_bound_pos_ = 0; |
222 optimizable_cmpi_pos_ = -1; | 218 optimizable_cmpi_pos_ = -1; |
223 trampoline_emitted_ = FLAG_force_long_branches; | 219 trampoline_emitted_ = FLAG_force_long_branches; |
224 unbound_labels_count_ = 0; | 220 tracked_branch_count_ = 0; |
225 ClearRecordedAstId(); | 221 ClearRecordedAstId(); |
226 relocations_.reserve(128); | 222 relocations_.reserve(128); |
227 } | 223 } |
228 | 224 |
229 | 225 |
230 void Assembler::GetCode(CodeDesc* desc) { | 226 void Assembler::GetCode(CodeDesc* desc) { |
231 // Emit constant pool if necessary. | 227 // Emit constant pool if necessary. |
232 int constant_pool_offset = EmitConstantPool(); | 228 int constant_pool_offset = EmitConstantPool(); |
233 | 229 |
234 EmitRelocations(); | 230 EmitRelocations(); |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 default: | 416 default: |
421 DCHECK(false); | 417 DCHECK(false); |
422 return -1; | 418 return -1; |
423 } | 419 } |
424 | 420 |
425 if (link == 0) return kEndOfChain; | 421 if (link == 0) return kEndOfChain; |
426 return pos + link; | 422 return pos + link; |
427 } | 423 } |
428 | 424 |
429 | 425 |
430 void Assembler::target_at_put(int pos, int target_pos) { | 426 void Assembler::target_at_put(int pos, int target_pos, bool* is_branch) { |
431 Instr instr = instr_at(pos); | 427 Instr instr = instr_at(pos); |
432 int opcode = instr & kOpcodeMask; | 428 int opcode = instr & kOpcodeMask; |
433 | 429 |
| 430 if (is_branch != nullptr) { |
| 431 *is_branch = (opcode == BX || opcode == BCX); |
| 432 } |
| 433 |
434 switch (opcode) { | 434 switch (opcode) { |
435 case BX: { | 435 case BX: { |
436 int imm26 = target_pos - pos; | 436 int imm26 = target_pos - pos; |
437 CHECK(is_int26(imm26) && (imm26 & (kAAMask | kLKMask)) == 0); | 437 CHECK(is_int26(imm26) && (imm26 & (kAAMask | kLKMask)) == 0); |
438 if (imm26 == kInstrSize && !(instr & kLKMask)) { | 438 if (imm26 == kInstrSize && !(instr & kLKMask)) { |
439 // Branch to next instr without link. | 439 // Branch to next instr without link. |
440 instr = ORI; // nop: ori, 0,0,0 | 440 instr = ORI; // nop: ori, 0,0,0 |
441 } else { | 441 } else { |
442 instr &= ((~kImm26Mask) | kAAMask | kLKMask); | 442 instr &= ((~kImm26Mask) | kAAMask | kLKMask); |
443 instr |= (imm26 & kImm26Mask); | 443 instr |= (imm26 & kImm26Mask); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
521 } | 521 } |
522 | 522 |
523 DCHECK(false); | 523 DCHECK(false); |
524 return 0; | 524 return 0; |
525 } | 525 } |
526 | 526 |
527 | 527 |
528 void Assembler::bind_to(Label* L, int pos) { | 528 void Assembler::bind_to(Label* L, int pos) { |
529 DCHECK(0 <= pos && pos <= pc_offset()); // must have a valid binding position | 529 DCHECK(0 <= pos && pos <= pc_offset()); // must have a valid binding position |
530 int32_t trampoline_pos = kInvalidSlotPos; | 530 int32_t trampoline_pos = kInvalidSlotPos; |
531 if (L->is_linked() && !trampoline_emitted_) { | 531 bool is_branch = false; |
532 unbound_labels_count_--; | |
533 next_buffer_check_ += kTrampolineSlotsSize; | |
534 } | |
535 | |
536 while (L->is_linked()) { | 532 while (L->is_linked()) { |
537 int fixup_pos = L->pos(); | 533 int fixup_pos = L->pos(); |
538 int32_t offset = pos - fixup_pos; | 534 int32_t offset = pos - fixup_pos; |
539 int maxReach = max_reach_from(fixup_pos); | 535 int maxReach = max_reach_from(fixup_pos); |
540 next(L); // call next before overwriting link with target at fixup_pos | 536 next(L); // call next before overwriting link with target at fixup_pos |
541 if (maxReach && is_intn(offset, maxReach) == false) { | 537 if (maxReach && is_intn(offset, maxReach) == false) { |
542 if (trampoline_pos == kInvalidSlotPos) { | 538 if (trampoline_pos == kInvalidSlotPos) { |
543 trampoline_pos = get_trampoline_entry(); | 539 trampoline_pos = get_trampoline_entry(); |
544 CHECK(trampoline_pos != kInvalidSlotPos); | 540 CHECK(trampoline_pos != kInvalidSlotPos); |
545 target_at_put(trampoline_pos, pos); | 541 target_at_put(trampoline_pos, pos); |
546 } | 542 } |
547 target_at_put(fixup_pos, trampoline_pos); | 543 target_at_put(fixup_pos, trampoline_pos); |
548 } else { | 544 } else { |
549 target_at_put(fixup_pos, pos); | 545 target_at_put(fixup_pos, pos, &is_branch); |
550 } | 546 } |
551 } | 547 } |
552 L->bind_to(pos); | 548 L->bind_to(pos); |
553 | 549 |
| 550 if (!trampoline_emitted_ && is_branch) { |
| 551 UntrackBranch(); |
| 552 } |
| 553 |
554 // Keep track of the last bound label so we don't eliminate any instructions | 554 // Keep track of the last bound label so we don't eliminate any instructions |
555 // before a bound label. | 555 // before a bound label. |
556 if (pos > last_bound_pos_) last_bound_pos_ = pos; | 556 if (pos > last_bound_pos_) last_bound_pos_ = pos; |
557 } | 557 } |
558 | 558 |
559 | 559 |
560 void Assembler::bind(Label* L) { | 560 void Assembler::bind(Label* L) { |
561 DCHECK(!L->is_bound()); // label can only be bound once | 561 DCHECK(!L->is_bound()); // label can only be bound once |
562 bind_to(L, pc_offset()); | 562 bind_to(L, pc_offset()); |
563 } | 563 } |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
666 position = L->pos(); | 666 position = L->pos(); |
667 } else { | 667 } else { |
668 if (L->is_linked()) { | 668 if (L->is_linked()) { |
669 position = L->pos(); // L's link | 669 position = L->pos(); // L's link |
670 } else { | 670 } else { |
671 // was: target_pos = kEndOfChain; | 671 // was: target_pos = kEndOfChain; |
672 // However, using self to mark the first reference | 672 // However, using self to mark the first reference |
673 // should avoid most instances of branch offset overflow. See | 673 // should avoid most instances of branch offset overflow. See |
674 // target_at() for where this is converted back to kEndOfChain. | 674 // target_at() for where this is converted back to kEndOfChain. |
675 position = pc_offset(); | 675 position = pc_offset(); |
676 if (!trampoline_emitted_) { | |
677 unbound_labels_count_++; | |
678 next_buffer_check_ -= kTrampolineSlotsSize; | |
679 } | |
680 } | 676 } |
681 L->link_to(pc_offset()); | 677 L->link_to(pc_offset()); |
682 } | 678 } |
683 | 679 |
684 return position; | 680 return position; |
685 } | 681 } |
686 | 682 |
687 | 683 |
688 // Branch instructions. | 684 // Branch instructions. |
689 | 685 |
(...skipping 1709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2399 BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize); | 2395 BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize); |
2400 } | 2396 } |
2401 | 2397 |
2402 | 2398 |
2403 void Assembler::CheckTrampolinePool() { | 2399 void Assembler::CheckTrampolinePool() { |
2404 // Some small sequences of instructions must not be broken up by the | 2400 // Some small sequences of instructions must not be broken up by the |
2405 // insertion of a trampoline pool; such sequences are protected by setting | 2401 // insertion of a trampoline pool; such sequences are protected by setting |
2406 // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_, | 2402 // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_, |
2407 // which are both checked here. Also, recursive calls to CheckTrampolinePool | 2403 // which are both checked here. Also, recursive calls to CheckTrampolinePool |
2408 // are blocked by trampoline_pool_blocked_nesting_. | 2404 // are blocked by trampoline_pool_blocked_nesting_. |
2409 if ((trampoline_pool_blocked_nesting_ > 0) || | 2405 if (trampoline_pool_blocked_nesting_ > 0) return; |
2410 (pc_offset() < no_trampoline_pool_before_)) { | 2406 if (pc_offset() < no_trampoline_pool_before_) { |
2411 // Emission is currently blocked; make sure we try again as soon as | 2407 next_trampoline_check_ = no_trampoline_pool_before_; |
2412 // possible. | |
2413 if (trampoline_pool_blocked_nesting_ > 0) { | |
2414 next_buffer_check_ = pc_offset() + kInstrSize; | |
2415 } else { | |
2416 next_buffer_check_ = no_trampoline_pool_before_; | |
2417 } | |
2418 return; | 2408 return; |
2419 } | 2409 } |
2420 | 2410 |
2421 DCHECK(!trampoline_emitted_); | 2411 DCHECK(!trampoline_emitted_); |
2422 DCHECK(unbound_labels_count_ >= 0); | 2412 if (tracked_branch_count_ > 0) { |
2423 if (unbound_labels_count_ > 0) { | 2413 int size = tracked_branch_count_ * kInstrSize; |
| 2414 |
| 2415 // As we are only going to emit trampoline once, we need to prevent any |
| 2416 // further emission. |
| 2417 trampoline_emitted_ = true; |
| 2418 next_trampoline_check_ = kMaxInt; |
| 2419 |
2424 // First we emit jump, then we emit trampoline pool. | 2420 // First we emit jump, then we emit trampoline pool. |
2425 { | 2421 b(size + kInstrSize, LeaveLK); |
2426 BlockTrampolinePoolScope block_trampoline_pool(this); | 2422 for (int i = size; i > 0; i -= kInstrSize) { |
2427 Label after_pool; | 2423 b(i, LeaveLK); |
2428 b(&after_pool); | 2424 } |
2429 | 2425 |
2430 int pool_start = pc_offset(); | 2426 trampoline_ = Trampoline(pc_offset() - size, tracked_branch_count_); |
2431 for (int i = 0; i < unbound_labels_count_; i++) { | |
2432 b(&after_pool); | |
2433 } | |
2434 bind(&after_pool); | |
2435 trampoline_ = Trampoline(pool_start, unbound_labels_count_); | |
2436 | |
2437 trampoline_emitted_ = true; | |
2438 // As we are only going to emit trampoline once, we need to prevent any | |
2439 // further emission. | |
2440 next_buffer_check_ = kMaxInt; | |
2441 } | |
2442 } else { | |
2443 // Number of branches to unbound label at this point is zero, so we can | |
2444 // move next buffer check to maximum. | |
2445 next_buffer_check_ = | |
2446 pc_offset() + kMaxCondBranchReach - kMaxBlockTrampolineSectionSize; | |
2447 } | 2427 } |
2448 return; | |
2449 } | 2428 } |
2450 | 2429 |
2451 | 2430 |
2452 } // namespace internal | 2431 } // namespace internal |
2453 } // namespace v8 | 2432 } // namespace v8 |
2454 | 2433 |
2455 #endif // V8_TARGET_ARCH_PPC | 2434 #endif // V8_TARGET_ARCH_PPC |
OLD | NEW |