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

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

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

Powered by Google App Engine
This is Rietveld 408576698