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

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

Issue 10225005: Revert r8309 "ARM: Clean up literal pool generation." because of crashes. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 8 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
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 ASSERT(buffer_size > 0); 317 ASSERT(buffer_size > 0);
318 buffer_ = static_cast<byte*>(buffer); 318 buffer_ = static_cast<byte*>(buffer);
319 buffer_size_ = buffer_size; 319 buffer_size_ = buffer_size;
320 own_buffer_ = false; 320 own_buffer_ = false;
321 } 321 }
322 322
323 // Set up buffer pointers. 323 // Set up buffer pointers.
324 ASSERT(buffer_ != NULL); 324 ASSERT(buffer_ != NULL);
325 pc_ = buffer_; 325 pc_ = buffer_;
326 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); 326 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
327 num_pending_reloc_info_ = 0; 327 num_prinfo_ = 0;
328 next_buffer_check_ = 0; 328 next_buffer_check_ = 0;
329 const_pool_blocked_nesting_ = 0; 329 const_pool_blocked_nesting_ = 0;
330 no_const_pool_before_ = 0; 330 no_const_pool_before_ = 0;
331 first_const_pool_use_ = -1; 331 last_const_pool_end_ = 0;
332 last_bound_pos_ = 0; 332 last_bound_pos_ = 0;
333 ClearRecordedAstId(); 333 ClearRecordedAstId();
334 } 334 }
335 335
336 336
337 Assembler::~Assembler() { 337 Assembler::~Assembler() {
338 ASSERT(const_pool_blocked_nesting_ == 0); 338 ASSERT(const_pool_blocked_nesting_ == 0);
339 if (own_buffer_) { 339 if (own_buffer_) {
340 if (isolate()->assembler_spare_buffer() == NULL && 340 if (isolate()->assembler_spare_buffer() == NULL &&
341 buffer_size_ == kMinimalBufferSize) { 341 buffer_size_ == kMinimalBufferSize) {
342 isolate()->set_assembler_spare_buffer(buffer_); 342 isolate()->set_assembler_spare_buffer(buffer_);
343 } else { 343 } else {
344 DeleteArray(buffer_); 344 DeleteArray(buffer_);
345 } 345 }
346 } 346 }
347 } 347 }
348 348
349 349
350 void Assembler::GetCode(CodeDesc* desc) { 350 void Assembler::GetCode(CodeDesc* desc) {
351 // Emit constant pool if necessary. 351 // Emit constant pool if necessary.
352 CheckConstPool(true, false); 352 CheckConstPool(true, false);
353 ASSERT(num_pending_reloc_info_ == 0); 353 ASSERT(num_prinfo_ == 0);
354 354
355 // Set up code descriptor. 355 // Set up code descriptor.
356 desc->buffer = buffer_; 356 desc->buffer = buffer_;
357 desc->buffer_size = buffer_size_; 357 desc->buffer_size = buffer_size_;
358 desc->instr_size = pc_offset(); 358 desc->instr_size = pc_offset();
359 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 359 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
360 } 360 }
361 361
362 362
363 void Assembler::Align(int m) { 363 void Assembler::Align(int m) {
(...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 // Immediate shift. 870 // Immediate shift.
871 instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code(); 871 instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
872 } else { 872 } else {
873 // Register shift. 873 // Register shift.
874 ASSERT(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc)); 874 ASSERT(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc));
875 instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code(); 875 instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code();
876 } 876 }
877 emit(instr | rn.code()*B16 | rd.code()*B12); 877 emit(instr | rn.code()*B16 | rd.code()*B12);
878 if (rn.is(pc) || x.rm_.is(pc)) { 878 if (rn.is(pc) || x.rm_.is(pc)) {
879 // Block constant pool emission for one instruction after reading pc. 879 // Block constant pool emission for one instruction after reading pc.
880 BlockConstPoolFor(1); 880 BlockConstPoolBefore(pc_offset() + kInstrSize);
881 } 881 }
882 } 882 }
883 883
884 884
885 void Assembler::addrmod2(Instr instr, Register rd, const MemOperand& x) { 885 void Assembler::addrmod2(Instr instr, Register rd, const MemOperand& x) {
886 ASSERT((instr & ~(kCondMask | B | L)) == B26); 886 ASSERT((instr & ~(kCondMask | B | L)) == B26);
887 int am = x.am_; 887 int am = x.am_;
888 if (!x.rm_.is_valid()) { 888 if (!x.rm_.is_valid()) {
889 // Immediate offset. 889 // Immediate offset.
890 int offset_12 = x.offset_; 890 int offset_12 = x.offset_;
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
994 if (L->is_linked()) { 994 if (L->is_linked()) {
995 target_pos = L->pos(); // L's link 995 target_pos = L->pos(); // L's link
996 } else { 996 } else {
997 target_pos = kEndOfChain; 997 target_pos = kEndOfChain;
998 } 998 }
999 L->link_to(pc_offset()); 999 L->link_to(pc_offset());
1000 } 1000 }
1001 1001
1002 // Block the emission of the constant pool, since the branch instruction must 1002 // Block the emission of the constant pool, since the branch instruction must
1003 // be emitted at the pc offset recorded by the label. 1003 // be emitted at the pc offset recorded by the label.
1004 BlockConstPoolFor(1); 1004 BlockConstPoolBefore(pc_offset() + kInstrSize);
1005 return target_pos - (pc_offset() + kPcLoadDelta); 1005 return target_pos - (pc_offset() + kPcLoadDelta);
1006 } 1006 }
1007 1007
1008 1008
1009 void Assembler::label_at_put(Label* L, int at_offset) { 1009 void Assembler::label_at_put(Label* L, int at_offset) {
1010 int target_pos; 1010 int target_pos;
1011 if (L->is_bound()) { 1011 if (L->is_bound()) {
1012 target_pos = L->pos(); 1012 target_pos = L->pos();
1013 } else { 1013 } else {
1014 if (L->is_linked()) { 1014 if (L->is_linked()) {
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after
1490 addrmod4(cond | B27 | am, base, src); 1490 addrmod4(cond | B27 | am, base, src);
1491 } 1491 }
1492 1492
1493 1493
1494 // Exception-generating instructions and debugging support. 1494 // Exception-generating instructions and debugging support.
1495 // Stops with a non-negative code less than kNumOfWatchedStops support 1495 // Stops with a non-negative code less than kNumOfWatchedStops support
1496 // enabling/disabling and a counter feature. See simulator-arm.h . 1496 // enabling/disabling and a counter feature. See simulator-arm.h .
1497 void Assembler::stop(const char* msg, Condition cond, int32_t code) { 1497 void Assembler::stop(const char* msg, Condition cond, int32_t code) {
1498 #ifndef __arm__ 1498 #ifndef __arm__
1499 ASSERT(code >= kDefaultStopCode); 1499 ASSERT(code >= kDefaultStopCode);
1500 { 1500 // The Simulator will handle the stop instruction and get the message address.
1501 // The Simulator will handle the stop instruction and get the message 1501 // It expects to find the address just after the svc instruction.
1502 // address. It expects to find the address just after the svc instruction. 1502 BlockConstPoolFor(2);
1503 BlockConstPoolScope block_const_pool(this); 1503 if (code >= 0) {
1504 if (code >= 0) { 1504 svc(kStopCode + code, cond);
1505 svc(kStopCode + code, cond); 1505 } else {
1506 } else { 1506 svc(kStopCode + kMaxStopCode, cond);
1507 svc(kStopCode + kMaxStopCode, cond);
1508 }
1509 emit(reinterpret_cast<Instr>(msg));
1510 } 1507 }
1508 emit(reinterpret_cast<Instr>(msg));
1511 #else // def __arm__ 1509 #else // def __arm__
1512 #ifdef CAN_USE_ARMV5_INSTRUCTIONS 1510 #ifdef CAN_USE_ARMV5_INSTRUCTIONS
1513 if (cond != al) { 1511 if (cond != al) {
1514 Label skip; 1512 Label skip;
1515 b(&skip, NegateCondition(cond)); 1513 b(&skip, NegateCondition(cond));
1516 bkpt(0); 1514 bkpt(0);
1517 bind(&skip); 1515 bind(&skip);
1518 } else { 1516 } else {
1519 bkpt(0); 1517 bkpt(0);
1520 } 1518 }
(...skipping 884 matching lines...) Expand 10 before | Expand all | Expand 10 after
2405 } 2403 }
2406 2404
2407 2405
2408 bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) { 2406 bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
2409 uint32_t dummy1; 2407 uint32_t dummy1;
2410 uint32_t dummy2; 2408 uint32_t dummy2;
2411 return fits_shifter(imm32, &dummy1, &dummy2, NULL); 2409 return fits_shifter(imm32, &dummy1, &dummy2, NULL);
2412 } 2410 }
2413 2411
2414 2412
2413 void Assembler::BlockConstPoolFor(int instructions) {
2414 BlockConstPoolBefore(pc_offset() + instructions * kInstrSize);
2415 }
2416
2417
2415 // Debugging. 2418 // Debugging.
2416 void Assembler::RecordJSReturn() { 2419 void Assembler::RecordJSReturn() {
2417 positions_recorder()->WriteRecordedPositions(); 2420 positions_recorder()->WriteRecordedPositions();
2418 CheckBuffer(); 2421 CheckBuffer();
2419 RecordRelocInfo(RelocInfo::JS_RETURN); 2422 RecordRelocInfo(RelocInfo::JS_RETURN);
2420 } 2423 }
2421 2424
2422 2425
2423 void Assembler::RecordDebugBreakSlot() { 2426 void Assembler::RecordDebugBreakSlot() {
2424 positions_recorder()->WriteRecordedPositions(); 2427 positions_recorder()->WriteRecordedPositions();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2468 buffer_size_ = desc.buffer_size; 2471 buffer_size_ = desc.buffer_size;
2469 pc_ += pc_delta; 2472 pc_ += pc_delta;
2470 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, 2473 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2471 reloc_info_writer.last_pc() + pc_delta); 2474 reloc_info_writer.last_pc() + pc_delta);
2472 2475
2473 // None of our relocation types are pc relative pointing outside the code 2476 // None of our relocation types are pc relative pointing outside the code
2474 // buffer nor pc absolute pointing inside the code buffer, so there is no need 2477 // buffer nor pc absolute pointing inside the code buffer, so there is no need
2475 // to relocate any emitted relocation entries. 2478 // to relocate any emitted relocation entries.
2476 2479
2477 // Relocate pending relocation entries. 2480 // Relocate pending relocation entries.
2478 for (int i = 0; i < num_pending_reloc_info_; i++) { 2481 for (int i = 0; i < num_prinfo_; i++) {
2479 RelocInfo& rinfo = pending_reloc_info_[i]; 2482 RelocInfo& rinfo = prinfo_[i];
2480 ASSERT(rinfo.rmode() != RelocInfo::COMMENT && 2483 ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
2481 rinfo.rmode() != RelocInfo::POSITION); 2484 rinfo.rmode() != RelocInfo::POSITION);
2482 if (rinfo.rmode() != RelocInfo::JS_RETURN) { 2485 if (rinfo.rmode() != RelocInfo::JS_RETURN) {
2483 rinfo.set_pc(rinfo.pc() + pc_delta); 2486 rinfo.set_pc(rinfo.pc() + pc_delta);
2484 } 2487 }
2485 } 2488 }
2486 } 2489 }
2487 2490
2488 2491
2489 void Assembler::db(uint8_t data) { 2492 void Assembler::db(uint8_t data) {
2490 // No relocation info should be pending while using db. db is used 2493 // No relocation info should be pending while using db. db is used
2491 // to write pure data with no pointers and the constant pool should 2494 // to write pure data with no pointers and the constant pool should
2492 // be emitted before using db. 2495 // be emitted before using db.
2493 ASSERT(num_pending_reloc_info_ == 0); 2496 ASSERT(num_prinfo_ == 0);
2494 CheckBuffer(); 2497 CheckBuffer();
2495 *reinterpret_cast<uint8_t*>(pc_) = data; 2498 *reinterpret_cast<uint8_t*>(pc_) = data;
2496 pc_ += sizeof(uint8_t); 2499 pc_ += sizeof(uint8_t);
2497 } 2500 }
2498 2501
2499 2502
2500 void Assembler::dd(uint32_t data) { 2503 void Assembler::dd(uint32_t data) {
2501 // No relocation info should be pending while using dd. dd is used 2504 // No relocation info should be pending while using dd. dd is used
2502 // to write pure data with no pointers and the constant pool should 2505 // to write pure data with no pointers and the constant pool should
2503 // be emitted before using dd. 2506 // be emitted before using dd.
2504 ASSERT(num_pending_reloc_info_ == 0); 2507 ASSERT(num_prinfo_ == 0);
2505 CheckBuffer(); 2508 CheckBuffer();
2506 *reinterpret_cast<uint32_t*>(pc_) = data; 2509 *reinterpret_cast<uint32_t*>(pc_) = data;
2507 pc_ += sizeof(uint32_t); 2510 pc_ += sizeof(uint32_t);
2508 } 2511 }
2509 2512
2510 2513
2511 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { 2514 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2512 // We do not try to reuse pool constants. 2515 // We do not try to reuse pool constants.
2513 RelocInfo rinfo(pc_, rmode, data, NULL); 2516 RelocInfo rinfo(pc_, rmode, data, NULL);
2514 if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::DEBUG_BREAK_SLOT) { 2517 if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::DEBUG_BREAK_SLOT) {
2515 // Adjust code for new modes. 2518 // Adjust code for new modes.
2516 ASSERT(RelocInfo::IsDebugBreakSlot(rmode) 2519 ASSERT(RelocInfo::IsDebugBreakSlot(rmode)
2517 || RelocInfo::IsJSReturn(rmode) 2520 || RelocInfo::IsJSReturn(rmode)
2518 || RelocInfo::IsComment(rmode) 2521 || RelocInfo::IsComment(rmode)
2519 || RelocInfo::IsPosition(rmode)); 2522 || RelocInfo::IsPosition(rmode));
2520 // These modes do not need an entry in the constant pool. 2523 // These modes do not need an entry in the constant pool.
2521 } else { 2524 } else {
2522 ASSERT(num_pending_reloc_info_ < kMaxNumPendingRelocInfo); 2525 ASSERT(num_prinfo_ < kMaxNumPRInfo);
2523 if (num_pending_reloc_info_ == 0) { 2526 prinfo_[num_prinfo_++] = rinfo;
2524 first_const_pool_use_ = pc_offset();
2525 }
2526 pending_reloc_info_[num_pending_reloc_info_++] = rinfo;
2527 // Make sure the constant pool is not emitted in place of the next 2527 // Make sure the constant pool is not emitted in place of the next
2528 // instruction for which we just recorded relocation info. 2528 // instruction for which we just recorded relocation info.
2529 BlockConstPoolFor(1); 2529 BlockConstPoolBefore(pc_offset() + kInstrSize);
2530 } 2530 }
2531 if (rinfo.rmode() != RelocInfo::NONE) { 2531 if (rinfo.rmode() != RelocInfo::NONE) {
2532 // Don't record external references unless the heap will be serialized. 2532 // Don't record external references unless the heap will be serialized.
2533 if (rmode == RelocInfo::EXTERNAL_REFERENCE) { 2533 if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
2534 #ifdef DEBUG 2534 #ifdef DEBUG
2535 if (!Serializer::enabled()) { 2535 if (!Serializer::enabled()) {
2536 Serializer::TooLateToEnableNow(); 2536 Serializer::TooLateToEnableNow();
2537 } 2537 }
2538 #endif 2538 #endif
2539 if (!Serializer::enabled() && !emit_debug_code()) { 2539 if (!Serializer::enabled() && !emit_debug_code()) {
2540 return; 2540 return;
2541 } 2541 }
2542 } 2542 }
2543 ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here 2543 ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here
2544 if (rmode == RelocInfo::CODE_TARGET_WITH_ID) { 2544 if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
2545 RelocInfo reloc_info_with_ast_id(pc_, rmode, RecordedAstId(), NULL); 2545 RelocInfo reloc_info_with_ast_id(pc_, rmode, RecordedAstId(), NULL);
2546 ClearRecordedAstId(); 2546 ClearRecordedAstId();
2547 reloc_info_writer.Write(&reloc_info_with_ast_id); 2547 reloc_info_writer.Write(&reloc_info_with_ast_id);
2548 } else { 2548 } else {
2549 reloc_info_writer.Write(&rinfo); 2549 reloc_info_writer.Write(&rinfo);
2550 } 2550 }
2551 } 2551 }
2552 } 2552 }
2553 2553
2554 2554
2555 void Assembler::BlockConstPoolFor(int instructions) {
2556 int pc_limit = pc_offset() + instructions * kInstrSize;
2557 if (no_const_pool_before_ < pc_limit) {
2558 // If there are some pending entries, the constant pool cannot be blocked
2559 // further than first_const_pool_use_ + kMaxDistToPool
2560 ASSERT((num_pending_reloc_info_ == 0) ||
2561 (pc_limit < (first_const_pool_use_ + kMaxDistToPool)));
2562 no_const_pool_before_ = pc_limit;
2563 }
2564
2565 if (next_buffer_check_ < no_const_pool_before_) {
2566 next_buffer_check_ = no_const_pool_before_;
2567 }
2568 }
2569
2570
2571 void Assembler::CheckConstPool(bool force_emit, bool require_jump) { 2555 void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
2572 // Some short sequence of instruction mustn't be broken up by constant pool 2556 // Calculate the offset of the next check. It will be overwritten
2573 // emission, such sequences are protected by calls to BlockConstPoolFor and 2557 // when a const pool is generated or when const pools are being
2574 // BlockConstPoolScope. 2558 // blocked for a specific range.
2575 if (is_const_pool_blocked()) { 2559 next_buffer_check_ = pc_offset() + kCheckConstInterval;
2560
2561 // There is nothing to do if there are no pending relocation info entries.
2562 if (num_prinfo_ == 0) return;
2563
2564 // We emit a constant pool at regular intervals of about kDistBetweenPools
2565 // or when requested by parameter force_emit (e.g. after each function).
2566 // We prefer not to emit a jump unless the max distance is reached or if we
2567 // are running low on slots, which can happen if a lot of constants are being
2568 // emitted (e.g. --debug-code and many static references).
2569 int dist = pc_offset() - last_const_pool_end_;
2570 if (!force_emit && dist < kMaxDistBetweenPools &&
2571 (require_jump || dist < kDistBetweenPools) &&
2572 // TODO(1236125): Cleanup the "magic" number below. We know that
2573 // the code generation will test every kCheckConstIntervalInst.
2574 // Thus we are safe as long as we generate less than 7 constant
2575 // entries per instruction.
2576 (num_prinfo_ < (kMaxNumPRInfo - (7 * kCheckConstIntervalInst)))) {
2577 return;
2578 }
2579
2580 // If we did not return by now, we need to emit the constant pool soon.
2581
2582 // However, some small sequences of instructions must not be broken up by the
2583 // insertion of a constant pool; such sequences are protected by setting
2584 // either const_pool_blocked_nesting_ or no_const_pool_before_, which are
2585 // both checked here. Also, recursive calls to CheckConstPool are blocked by
2586 // no_const_pool_before_.
2587 if (const_pool_blocked_nesting_ > 0 || pc_offset() < no_const_pool_before_) {
2588 // Emission is currently blocked; make sure we try again as soon as
2589 // possible.
2590 if (const_pool_blocked_nesting_ > 0) {
2591 next_buffer_check_ = pc_offset() + kInstrSize;
2592 } else {
2593 next_buffer_check_ = no_const_pool_before_;
2594 }
2595
2576 // Something is wrong if emission is forced and blocked at the same time. 2596 // Something is wrong if emission is forced and blocked at the same time.
2577 ASSERT(!force_emit); 2597 ASSERT(!force_emit);
2578 return; 2598 return;
2579 } 2599 }
2580 2600
2581 // There is nothing to do if there are no pending constant pool entries. 2601 int jump_instr = require_jump ? kInstrSize : 0;
2582 if (num_pending_reloc_info_ == 0) {
2583 // Calculate the offset of the next check.
2584 next_buffer_check_ = pc_offset() + kCheckPoolInterval;
2585 return;
2586 }
2587
2588 // We emit a constant pool when:
2589 // * requested to do so by parameter force_emit (e.g. after each function).
2590 // * the distance to the first instruction accessing the constant pool is
2591 // kAvgDistToPool or more.
2592 // * no jump is required and the distance to the first instruction accessing
2593 // the constant pool is at least kMaxDistToPool / 2.
2594 ASSERT(first_const_pool_use_ >= 0);
2595 int dist = pc_offset() - first_const_pool_use_;
2596 if (!force_emit && dist < kAvgDistToPool &&
2597 (require_jump || (dist < (kMaxDistToPool / 2)))) {
2598 return;
2599 }
2600 2602
2601 // Check that the code buffer is large enough before emitting the constant 2603 // Check that the code buffer is large enough before emitting the constant
2602 // pool (include the jump over the pool and the constant pool marker and 2604 // pool and relocation information (include the jump over the pool and the
2603 // the gap to the relocation information). 2605 // constant pool marker).
2604 int jump_instr = require_jump ? kInstrSize : 0; 2606 int max_needed_space =
2605 int needed_space = jump_instr + kInstrSize + 2607 jump_instr + kInstrSize + num_prinfo_*(kInstrSize + kMaxRelocSize);
2606 num_pending_reloc_info_ * kInstrSize + kGap; 2608 while (buffer_space() <= (max_needed_space + kGap)) GrowBuffer();
2607 while (buffer_space() <= needed_space) GrowBuffer();
2608 2609
2609 { 2610 // Block recursive calls to CheckConstPool.
2610 // Block recursive calls to CheckConstPool. 2611 BlockConstPoolBefore(pc_offset() + jump_instr + kInstrSize +
2611 BlockConstPoolScope block_const_pool(this); 2612 num_prinfo_*kInstrSize);
2613 // Don't bother to check for the emit calls below.
2614 next_buffer_check_ = no_const_pool_before_;
2612 2615
2613 // Emit jump over constant pool if necessary. 2616 // Emit jump over constant pool if necessary.
2614 Label after_pool; 2617 Label after_pool;
2615 if (require_jump) { 2618 if (require_jump) b(&after_pool);
2616 b(&after_pool); 2619
2620 RecordComment("[ Constant Pool");
2621
2622 // Put down constant pool marker "Undefined instruction" as specified by
2623 // A5.6 (ARMv7) Instruction set encoding.
2624 emit(kConstantPoolMarker | num_prinfo_);
2625
2626 // Emit constant pool entries.
2627 for (int i = 0; i < num_prinfo_; i++) {
2628 RelocInfo& rinfo = prinfo_[i];
2629 ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
2630 rinfo.rmode() != RelocInfo::POSITION &&
2631 rinfo.rmode() != RelocInfo::STATEMENT_POSITION);
2632 Instr instr = instr_at(rinfo.pc());
2633
2634 // Instruction to patch must be a ldr/str [pc, #offset].
2635 // P and U set, B and W clear, Rn == pc, offset12 still 0.
2636 ASSERT((instr & (7*B25 | P | U | B | W | 15*B16 | kOff12Mask)) ==
2637 (2*B25 | P | U | pc.code()*B16));
2638 int delta = pc_ - rinfo.pc() - 8;
2639 ASSERT(delta >= -4); // instr could be ldr pc, [pc, #-4] followed by targ32
2640 if (delta < 0) {
2641 instr &= ~U;
2642 delta = -delta;
2617 } 2643 }
2644 ASSERT(is_uint12(delta));
2645 instr_at_put(rinfo.pc(), instr + delta);
2646 emit(rinfo.data());
2647 }
2648 num_prinfo_ = 0;
2649 last_const_pool_end_ = pc_offset();
2618 2650
2619 RecordComment("[ Constant Pool"); 2651 RecordComment("]");
2620 2652
2621 // Put down constant pool marker "Undefined instruction" as specified by 2653 if (after_pool.is_linked()) {
2622 // A5.6 (ARMv7) Instruction set encoding. 2654 bind(&after_pool);
2623 emit(kConstantPoolMarker | num_pending_reloc_info_);
2624
2625 // Emit constant pool entries.
2626 for (int i = 0; i < num_pending_reloc_info_; i++) {
2627 RelocInfo& rinfo = pending_reloc_info_[i];
2628 ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
2629 rinfo.rmode() != RelocInfo::POSITION &&
2630 rinfo.rmode() != RelocInfo::STATEMENT_POSITION);
2631
2632 Instr instr = instr_at(rinfo.pc());
2633 // Instruction to patch must be 'ldr rd, [pc, #offset]' with offset == 0.
2634 ASSERT(IsLdrPcImmediateOffset(instr) &&
2635 GetLdrRegisterImmediateOffset(instr) == 0);
2636
2637 int delta = pc_ - rinfo.pc() - kPcLoadDelta;
2638 // 0 is the smallest delta:
2639 // ldr rd, [pc, #0]
2640 // constant pool marker
2641 // data
2642 ASSERT(is_uint12(delta));
2643
2644 instr_at_put(rinfo.pc(), SetLdrRegisterImmediateOffset(instr, delta));
2645 emit(rinfo.data());
2646 }
2647
2648 num_pending_reloc_info_ = 0;
2649 first_const_pool_use_ = -1;
2650
2651 RecordComment("]");
2652
2653 if (after_pool.is_linked()) {
2654 bind(&after_pool);
2655 }
2656 } 2655 }
2657 2656
2658 // Since a constant pool was just emitted, move the check offset forward by 2657 // Since a constant pool was just emitted, move the check offset forward by
2659 // the standard interval. 2658 // the standard interval.
2660 next_buffer_check_ = pc_offset() + kCheckPoolInterval; 2659 next_buffer_check_ = pc_offset() + kCheckConstInterval;
2661 } 2660 }
2662 2661
2663 2662
2664 } } // namespace v8::internal 2663 } } // namespace v8::internal
2665 2664
2666 #endif // V8_TARGET_ARCH_ARM 2665 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698