Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: src/a64/assembler-a64.cc

Issue 169893002: A64: Let the MacroAssembler resolve branches to distant targets. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed Ulan's comments. Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // 2 //
3 // Redistribution and use in source and binary forms, with or without 3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are 4 // modification, are permitted provided that the following conditions are
5 // met: 5 // met:
6 // 6 //
7 // * Redistributions of source code must retain the above copyright 7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer. 8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above 9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following 10 // copyright notice, this list of conditions and the following
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 282
283 return !RelocInfo::IsNone(rmode_); 283 return !RelocInfo::IsNone(rmode_);
284 } 284 }
285 285
286 286
287 // Assembler 287 // Assembler
288 288
289 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) 289 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
290 : AssemblerBase(isolate, buffer, buffer_size), 290 : AssemblerBase(isolate, buffer, buffer_size),
291 recorded_ast_id_(TypeFeedbackId::None()), 291 recorded_ast_id_(TypeFeedbackId::None()),
292 unresolved_branches_(),
292 positions_recorder_(this) { 293 positions_recorder_(this) {
293 const_pool_blocked_nesting_ = 0; 294 const_pool_blocked_nesting_ = 0;
294 Reset(); 295 Reset();
295 } 296 }
296 297
297 298
298 Assembler::~Assembler() { 299 Assembler::~Assembler() {
299 ASSERT(num_pending_reloc_info_ == 0); 300 ASSERT(num_pending_reloc_info_ == 0);
300 ASSERT(const_pool_blocked_nesting_ == 0); 301 ASSERT(const_pool_blocked_nesting_ == 0);
301 } 302 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 while ((pc_offset() & (m - 1)) != 0) { 341 while ((pc_offset() & (m - 1)) != 0) {
341 nop(); 342 nop();
342 } 343 }
343 } 344 }
344 345
345 346
346 void Assembler::CheckLabelLinkChain(Label const * label) { 347 void Assembler::CheckLabelLinkChain(Label const * label) {
347 #ifdef DEBUG 348 #ifdef DEBUG
348 if (label->is_linked()) { 349 if (label->is_linked()) {
349 int linkoffset = label->pos(); 350 int linkoffset = label->pos();
350 bool start_of_chain = false; 351 bool end_of_chain = false;
351 while (!start_of_chain) { 352 while (!end_of_chain) {
352 Instruction * link = InstructionAt(linkoffset); 353 Instruction * link = InstructionAt(linkoffset);
353 int linkpcoffset = link->ImmPCOffset(); 354 int linkpcoffset = link->ImmPCOffset();
354 int prevlinkoffset = linkoffset + linkpcoffset; 355 int prevlinkoffset = linkoffset + linkpcoffset;
355 356
356 start_of_chain = (linkoffset == prevlinkoffset); 357 end_of_chain = (linkoffset == prevlinkoffset);
357 linkoffset = linkoffset + linkpcoffset; 358 linkoffset = linkoffset + linkpcoffset;
358 } 359 }
359 } 360 }
360 #endif 361 #endif
361 } 362 }
362 363
363 364
365 void Assembler::RemoveBranchFromLabelLinkChain(Instruction* branch,
366 Label* label,
367 Instruction* label_veneer) {
368 ASSERT(label->is_linked());
369
370 CheckLabelLinkChain(label);
371
372 Instruction* link = InstructionAt(label->pos());
373 Instruction* prev_link = link;
374 Instruction* next_link;
375 bool end_of_chain = false;
376
377 while (link != branch && !end_of_chain) {
378 next_link = link->ImmPCOffsetTarget();
379 end_of_chain = (link == next_link);
380 prev_link = link;
381 link = next_link;
382 }
383
384 ASSERT(branch == link);
385 next_link = branch->ImmPCOffsetTarget();
386
387 if (branch == prev_link) {
388 // The branch is the first instruction in the chain.
389 if (branch == next_link) {
390 // It is also the last instruction in the chain, so it is the only branch
391 // currently referring to this label.
392 label->Unuse();
393 } else {
394 label->link_to(reinterpret_cast<byte*>(next_link) - buffer_);
395 }
396
397 } else if (branch == next_link) {
398 // The branch is the last (but not also the first) instruction in the chain.
399 prev_link->SetImmPCOffsetTarget(prev_link);
400
401 } else {
402 // The branch is in the middle of the chain.
403 if (prev_link->IsTargetInImmPCOffsetRange(next_link)) {
404 prev_link->SetImmPCOffsetTarget(next_link);
405 } else if (label_veneer != NULL) {
406 // Use the veneer for all previous links in the chain.
407 prev_link->SetImmPCOffsetTarget(prev_link);
408
409 end_of_chain = false;
410 link = next_link;
411 while (!end_of_chain) {
412 next_link = link->ImmPCOffsetTarget();
413 end_of_chain = (link == next_link);
414 link->SetImmPCOffsetTarget(label_veneer);
415 link = next_link;
416 }
417 } else {
418 // The assert below will fire.
419 // Some other work could be attempted to fix up the chain, but it would be
420 // rather complicated. If we crash here, we may want to consider using an
421 // other mechanism than a chain of branches.
422 //
423 // Note that this situation currently should not happen, as we always call
424 // this function with a veneer to the target label.
425 // However this could happen with a MacroAssembler in the following state:
426 // [previous code]
427 // B(label);
428 // [20KB code]
429 // Tbz(label); // First tbz. Pointing to unconditional branch.
430 // [20KB code]
431 // Tbz(label); // Second tbz. Pointing to the first tbz.
432 // [more code]
433 // and this function is called to remove the first tbz from the label link
434 // chain. Since tbz has a range of +-32KB, the second tbz cannot point to
435 // the unconditional branch.
436 CHECK(prev_link->IsTargetInImmPCOffsetRange(next_link));
437 UNREACHABLE();
438 }
439 }
440
441 CheckLabelLinkChain(label);
442 }
443
444
364 void Assembler::bind(Label* label) { 445 void Assembler::bind(Label* label) {
365 // Bind label to the address at pc_. All instructions (most likely branches) 446 // Bind label to the address at pc_. All instructions (most likely branches)
366 // that are linked to this label will be updated to point to the newly-bound 447 // that are linked to this label will be updated to point to the newly-bound
367 // label. 448 // label.
368 449
369 ASSERT(!label->is_near_linked()); 450 ASSERT(!label->is_near_linked());
370 ASSERT(!label->is_bound()); 451 ASSERT(!label->is_bound());
371 452
372 // If the label is linked, the link chain looks something like this: 453 // If the label is linked, the link chain looks something like this:
373 // 454 //
(...skipping 29 matching lines...) Expand all
403 label->Unuse(); 484 label->Unuse();
404 } else { 485 } else {
405 // Update the label for the next iteration. 486 // Update the label for the next iteration.
406 label->link_to(prevlinkoffset); 487 label->link_to(prevlinkoffset);
407 } 488 }
408 } 489 }
409 label->bind_to(pc_offset()); 490 label->bind_to(pc_offset());
410 491
411 ASSERT(label->is_bound()); 492 ASSERT(label->is_bound());
412 ASSERT(!label->is_linked()); 493 ASSERT(!label->is_linked());
494
495 DeleteUnresolvedBranchInfoForLabel(label);
413 } 496 }
414 497
415 498
416 int Assembler::LinkAndGetByteOffsetTo(Label* label) { 499 int Assembler::LinkAndGetByteOffsetTo(Label* label) {
417 ASSERT(sizeof(*pc_) == 1); 500 ASSERT(sizeof(*pc_) == 1);
418 CheckLabelLinkChain(label); 501 CheckLabelLinkChain(label);
419 502
420 int offset; 503 int offset;
421 if (label->is_bound()) { 504 if (label->is_bound()) {
422 // The label is bound, so it does not need to be updated. Referring 505 // The label is bound, so it does not need to be updated. Referring
(...skipping 26 matching lines...) Expand all
449 offset = kStartOfLabelLinkChain; 532 offset = kStartOfLabelLinkChain;
450 } 533 }
451 // The instruction at pc is now the last link in the label's chain. 534 // The instruction at pc is now the last link in the label's chain.
452 label->link_to(pc_offset()); 535 label->link_to(pc_offset());
453 } 536 }
454 537
455 return offset; 538 return offset;
456 } 539 }
457 540
458 541
542 void Assembler::DeleteUnresolvedBranchInfoForLabel(Label* label) {
543 // Branches to this label will be resolved when the label is bound below.
544 std::multimap<int, FarBranchInfo>::iterator it_tmp, it;
545 it = unresolved_branches_.begin();
546 while (it != unresolved_branches_.end()) {
547 it_tmp = it++;
548 if (it_tmp->second.label_ == label) {
549 CHECK(it_tmp->first >= pc_offset());
550 unresolved_branches_.erase(it_tmp);
551 }
552 }
553 }
554
555
459 void Assembler::StartBlockConstPool() { 556 void Assembler::StartBlockConstPool() {
460 if (const_pool_blocked_nesting_++ == 0) { 557 if (const_pool_blocked_nesting_++ == 0) {
461 // Prevent constant pool checks happening by setting the next check to 558 // Prevent constant pool checks happening by setting the next check to
462 // the biggest possible offset. 559 // the biggest possible offset.
463 next_buffer_check_ = kMaxInt; 560 next_buffer_check_ = kMaxInt;
464 } 561 }
465 } 562 }
466 563
467 564
468 void Assembler::EndBlockConstPool() { 565 void Assembler::EndBlockConstPool() {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 616
520 void Assembler::ConstantPoolGuard() { 617 void Assembler::ConstantPoolGuard() {
521 #ifdef DEBUG 618 #ifdef DEBUG
522 // Currently this is only used after a constant pool marker. 619 // Currently this is only used after a constant pool marker.
523 ASSERT(is_const_pool_blocked()); 620 ASSERT(is_const_pool_blocked());
524 Instruction* instr = reinterpret_cast<Instruction*>(pc_); 621 Instruction* instr = reinterpret_cast<Instruction*>(pc_);
525 ASSERT(instr->preceding()->IsLdrLiteralX() && 622 ASSERT(instr->preceding()->IsLdrLiteralX() &&
526 instr->preceding()->Rt() == xzr.code()); 623 instr->preceding()->Rt() == xzr.code());
527 #endif 624 #endif
528 625
529 // Crash by branching to 0. lr now points near the fault. 626 // We must generate only one instruction.
530 // TODO(all): update the simulator to trap this pattern.
531 Emit(BLR | Rn(xzr)); 627 Emit(BLR | Rn(xzr));
532 } 628 }
533 629
534 630
535 void Assembler::br(const Register& xn) { 631 void Assembler::br(const Register& xn) {
536 positions_recorder()->WriteRecordedPositions(); 632 positions_recorder()->WriteRecordedPositions();
537 ASSERT(xn.Is64Bits()); 633 ASSERT(xn.Is64Bits());
538 Emit(BR | Rn(xn)); 634 Emit(BR | Rn(xn));
539 } 635 }
540 636
(...skipping 1966 matching lines...) Expand 10 before | Expand all | Expand 10 after
2507 // code. 2603 // code.
2508 #ifdef ENABLE_DEBUGGER_SUPPORT 2604 #ifdef ENABLE_DEBUGGER_SUPPORT
2509 RecordRelocInfo(RelocInfo::CONST_POOL, static_cast<intptr_t>(size)); 2605 RecordRelocInfo(RelocInfo::CONST_POOL, static_cast<intptr_t>(size));
2510 #endif 2606 #endif
2511 } 2607 }
2512 2608
2513 2609
2514 } } // namespace v8::internal 2610 } } // namespace v8::internal
2515 2611
2516 #endif // V8_TARGET_ARCH_A64 2612 #endif // V8_TARGET_ARCH_A64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698