Chromium Code Reviews| 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 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 310 static const Instr kStrRegFpNegOffsetPattern = | 310 static const Instr kStrRegFpNegOffsetPattern = |
| 311 al | B26 | NegOffset | fp.code() * B16; | 311 al | B26 | NegOffset | fp.code() * B16; |
| 312 static const Instr kLdrStrInstrTypeMask = 0xffff0000; | 312 static const Instr kLdrStrInstrTypeMask = 0xffff0000; |
| 313 static const Instr kLdrStrInstrArgumentMask = 0x0000ffff; | 313 static const Instr kLdrStrInstrArgumentMask = 0x0000ffff; |
| 314 static const Instr kLdrStrOffsetMask = 0x00000fff; | 314 static const Instr kLdrStrOffsetMask = 0x00000fff; |
| 315 | 315 |
| 316 // Spare buffer. | 316 // Spare buffer. |
| 317 static const int kMinimalBufferSize = 4*KB; | 317 static const int kMinimalBufferSize = 4*KB; |
| 318 static byte* spare_buffer_ = NULL; | 318 static byte* spare_buffer_ = NULL; |
| 319 | 319 |
| 320 Assembler::Assembler(void* buffer, int buffer_size) { | 320 Assembler::Assembler(void* buffer, int buffer_size) |
| 321 : positions_recorder_(this) { | |
| 321 if (buffer == NULL) { | 322 if (buffer == NULL) { |
| 322 // Do our own buffer management. | 323 // Do our own buffer management. |
| 323 if (buffer_size <= kMinimalBufferSize) { | 324 if (buffer_size <= kMinimalBufferSize) { |
| 324 buffer_size = kMinimalBufferSize; | 325 buffer_size = kMinimalBufferSize; |
| 325 | 326 |
| 326 if (spare_buffer_ != NULL) { | 327 if (spare_buffer_ != NULL) { |
| 327 buffer = spare_buffer_; | 328 buffer = spare_buffer_; |
| 328 spare_buffer_ = NULL; | 329 spare_buffer_ = NULL; |
| 329 } | 330 } |
| 330 } | 331 } |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 347 // Setup buffer pointers. | 348 // Setup buffer pointers. |
| 348 ASSERT(buffer_ != NULL); | 349 ASSERT(buffer_ != NULL); |
| 349 pc_ = buffer_; | 350 pc_ = buffer_; |
| 350 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); | 351 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); |
| 351 num_prinfo_ = 0; | 352 num_prinfo_ = 0; |
| 352 next_buffer_check_ = 0; | 353 next_buffer_check_ = 0; |
| 353 const_pool_blocked_nesting_ = 0; | 354 const_pool_blocked_nesting_ = 0; |
| 354 no_const_pool_before_ = 0; | 355 no_const_pool_before_ = 0; |
| 355 last_const_pool_end_ = 0; | 356 last_const_pool_end_ = 0; |
| 356 last_bound_pos_ = 0; | 357 last_bound_pos_ = 0; |
| 357 current_statement_position_ = RelocInfo::kNoPosition; | |
| 358 current_position_ = RelocInfo::kNoPosition; | |
| 359 written_statement_position_ = current_statement_position_; | |
| 360 written_position_ = current_position_; | |
| 361 } | 358 } |
| 362 | 359 |
| 363 | 360 |
| 364 Assembler::~Assembler() { | 361 Assembler::~Assembler() { |
| 365 ASSERT(const_pool_blocked_nesting_ == 0); | 362 ASSERT(const_pool_blocked_nesting_ == 0); |
| 366 if (own_buffer_) { | 363 if (own_buffer_) { |
| 367 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { | 364 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { |
| 368 spare_buffer_ = buffer_; | 365 spare_buffer_ = buffer_; |
| 369 } else { | 366 } else { |
| 370 DeleteArray(buffer_); | 367 DeleteArray(buffer_); |
| (...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 992 | 989 |
| 993 void Assembler::bl(int branch_offset, Condition cond) { | 990 void Assembler::bl(int branch_offset, Condition cond) { |
| 994 ASSERT((branch_offset & 3) == 0); | 991 ASSERT((branch_offset & 3) == 0); |
| 995 int imm24 = branch_offset >> 2; | 992 int imm24 = branch_offset >> 2; |
| 996 ASSERT(is_int24(imm24)); | 993 ASSERT(is_int24(imm24)); |
| 997 emit(cond | B27 | B25 | B24 | (imm24 & Imm24Mask)); | 994 emit(cond | B27 | B25 | B24 | (imm24 & Imm24Mask)); |
| 998 } | 995 } |
| 999 | 996 |
| 1000 | 997 |
| 1001 void Assembler::blx(int branch_offset) { // v5 and above | 998 void Assembler::blx(int branch_offset) { // v5 and above |
| 1002 WriteRecordedPositions(); | 999 positions_recorder()->WriteRecordedPositions(); |
|
Søren Thygesen Gjesse
2010/11/04 15:08:24
Why not just positions_recorder_. instead of posit
| |
| 1003 ASSERT((branch_offset & 1) == 0); | 1000 ASSERT((branch_offset & 1) == 0); |
| 1004 int h = ((branch_offset & 2) >> 1)*B24; | 1001 int h = ((branch_offset & 2) >> 1)*B24; |
| 1005 int imm24 = branch_offset >> 2; | 1002 int imm24 = branch_offset >> 2; |
| 1006 ASSERT(is_int24(imm24)); | 1003 ASSERT(is_int24(imm24)); |
| 1007 emit(nv | B27 | B25 | h | (imm24 & Imm24Mask)); | 1004 emit(nv | B27 | B25 | h | (imm24 & Imm24Mask)); |
| 1008 } | 1005 } |
| 1009 | 1006 |
| 1010 | 1007 |
| 1011 void Assembler::blx(Register target, Condition cond) { // v5 and above | 1008 void Assembler::blx(Register target, Condition cond) { // v5 and above |
| 1012 WriteRecordedPositions(); | 1009 positions_recorder()->WriteRecordedPositions(); |
| 1013 ASSERT(!target.is(pc)); | 1010 ASSERT(!target.is(pc)); |
| 1014 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | 3*B4 | target.code()); | 1011 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | 3*B4 | target.code()); |
| 1015 } | 1012 } |
| 1016 | 1013 |
| 1017 | 1014 |
| 1018 void Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t | 1015 void Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t |
| 1019 WriteRecordedPositions(); | 1016 positions_recorder()->WriteRecordedPositions(); |
| 1020 ASSERT(!target.is(pc)); // use of pc is actually allowed, but discouraged | 1017 ASSERT(!target.is(pc)); // use of pc is actually allowed, but discouraged |
| 1021 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | B4 | target.code()); | 1018 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | B4 | target.code()); |
| 1022 } | 1019 } |
| 1023 | 1020 |
| 1024 | 1021 |
| 1025 // Data-processing instructions. | 1022 // Data-processing instructions. |
| 1026 | 1023 |
| 1027 void Assembler::and_(Register dst, Register src1, const Operand& src2, | 1024 void Assembler::and_(Register dst, Register src1, const Operand& src2, |
| 1028 SBit s, Condition cond) { | 1025 SBit s, Condition cond) { |
| 1029 addrmod1(cond | 0*B21 | s, src1, dst, src2); | 1026 addrmod1(cond | 0*B21 | s, src1, dst, src2); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1107 | 1104 |
| 1108 | 1105 |
| 1109 void Assembler::orr(Register dst, Register src1, const Operand& src2, | 1106 void Assembler::orr(Register dst, Register src1, const Operand& src2, |
| 1110 SBit s, Condition cond) { | 1107 SBit s, Condition cond) { |
| 1111 addrmod1(cond | 12*B21 | s, src1, dst, src2); | 1108 addrmod1(cond | 12*B21 | s, src1, dst, src2); |
| 1112 } | 1109 } |
| 1113 | 1110 |
| 1114 | 1111 |
| 1115 void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) { | 1112 void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) { |
| 1116 if (dst.is(pc)) { | 1113 if (dst.is(pc)) { |
| 1117 WriteRecordedPositions(); | 1114 positions_recorder()->WriteRecordedPositions(); |
| 1118 } | 1115 } |
| 1119 // Don't allow nop instructions in the form mov rn, rn to be generated using | 1116 // Don't allow nop instructions in the form mov rn, rn to be generated using |
| 1120 // the mov instruction. They must be generated using nop(int) | 1117 // the mov instruction. They must be generated using nop(int) |
| 1121 // pseudo instructions. | 1118 // pseudo instructions. |
| 1122 ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al)); | 1119 ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al)); |
| 1123 addrmod1(cond | 13*B21 | s, r0, dst, src); | 1120 addrmod1(cond | 13*B21 | s, r0, dst, src); |
| 1124 } | 1121 } |
| 1125 | 1122 |
| 1126 | 1123 |
| 1127 void Assembler::movw(Register reg, uint32_t immediate, Condition cond) { | 1124 void Assembler::movw(Register reg, uint32_t immediate, Condition cond) { |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1352 ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0); // only rm allowed | 1349 ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0); // only rm allowed |
| 1353 instr = src.rm_.code(); | 1350 instr = src.rm_.code(); |
| 1354 } | 1351 } |
| 1355 emit(cond | instr | B24 | B21 | fields | 15*B12); | 1352 emit(cond | instr | B24 | B21 | fields | 15*B12); |
| 1356 } | 1353 } |
| 1357 | 1354 |
| 1358 | 1355 |
| 1359 // Load/Store instructions. | 1356 // Load/Store instructions. |
| 1360 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { | 1357 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { |
| 1361 if (dst.is(pc)) { | 1358 if (dst.is(pc)) { |
| 1362 WriteRecordedPositions(); | 1359 positions_recorder()->WriteRecordedPositions(); |
| 1363 } | 1360 } |
| 1364 addrmod2(cond | B26 | L, dst, src); | 1361 addrmod2(cond | B26 | L, dst, src); |
| 1365 | 1362 |
| 1366 // Eliminate pattern: push(ry), pop(rx) | 1363 // Eliminate pattern: push(ry), pop(rx) |
| 1367 // str(ry, MemOperand(sp, 4, NegPreIndex), al) | 1364 // str(ry, MemOperand(sp, 4, NegPreIndex), al) |
| 1368 // ldr(rx, MemOperand(sp, 4, PostIndex), al) | 1365 // ldr(rx, MemOperand(sp, 4, PostIndex), al) |
| 1369 // Both instructions can be eliminated if ry = rx. | 1366 // Both instructions can be eliminated if ry = rx. |
| 1370 // If ry != rx, a register copy from ry to rx is inserted | 1367 // If ry != rx, a register copy from ry to rx is inserted |
| 1371 // after eliminating the push and the pop instructions. | 1368 // after eliminating the push and the pop instructions. |
| 1372 if (can_peephole_optimize(2)) { | 1369 if (can_peephole_optimize(2)) { |
| (...skipping 997 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2370 } | 2367 } |
| 2371 | 2368 |
| 2372 | 2369 |
| 2373 void Assembler::BlockConstPoolFor(int instructions) { | 2370 void Assembler::BlockConstPoolFor(int instructions) { |
| 2374 BlockConstPoolBefore(pc_offset() + instructions * kInstrSize); | 2371 BlockConstPoolBefore(pc_offset() + instructions * kInstrSize); |
| 2375 } | 2372 } |
| 2376 | 2373 |
| 2377 | 2374 |
| 2378 // Debugging. | 2375 // Debugging. |
| 2379 void Assembler::RecordJSReturn() { | 2376 void Assembler::RecordJSReturn() { |
| 2380 WriteRecordedPositions(); | 2377 positions_recorder()->WriteRecordedPositions(); |
| 2381 CheckBuffer(); | 2378 CheckBuffer(); |
| 2382 RecordRelocInfo(RelocInfo::JS_RETURN); | 2379 RecordRelocInfo(RelocInfo::JS_RETURN); |
| 2383 } | 2380 } |
| 2384 | 2381 |
| 2385 | 2382 |
| 2386 void Assembler::RecordDebugBreakSlot() { | 2383 void Assembler::RecordDebugBreakSlot() { |
| 2387 WriteRecordedPositions(); | 2384 positions_recorder()->WriteRecordedPositions(); |
| 2388 CheckBuffer(); | 2385 CheckBuffer(); |
| 2389 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT); | 2386 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT); |
| 2390 } | 2387 } |
| 2391 | 2388 |
| 2392 | 2389 |
| 2393 void Assembler::RecordComment(const char* msg) { | 2390 void Assembler::RecordComment(const char* msg) { |
| 2394 if (FLAG_debug_code) { | 2391 if (FLAG_debug_code) { |
| 2395 CheckBuffer(); | 2392 CheckBuffer(); |
| 2396 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg)); | 2393 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg)); |
| 2397 } | 2394 } |
| 2398 } | 2395 } |
| 2399 | 2396 |
| 2400 | 2397 |
| 2401 void Assembler::RecordPosition(int pos) { | |
| 2402 if (pos == RelocInfo::kNoPosition) return; | |
| 2403 ASSERT(pos >= 0); | |
| 2404 current_position_ = pos; | |
| 2405 } | |
| 2406 | |
| 2407 | |
| 2408 void Assembler::RecordStatementPosition(int pos) { | |
| 2409 if (pos == RelocInfo::kNoPosition) return; | |
| 2410 ASSERT(pos >= 0); | |
| 2411 current_statement_position_ = pos; | |
| 2412 } | |
| 2413 | |
| 2414 | |
| 2415 bool Assembler::WriteRecordedPositions() { | |
| 2416 bool written = false; | |
| 2417 | |
| 2418 // Write the statement position if it is different from what was written last | |
| 2419 // time. | |
| 2420 if (current_statement_position_ != written_statement_position_) { | |
| 2421 CheckBuffer(); | |
| 2422 RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_); | |
| 2423 written_statement_position_ = current_statement_position_; | |
| 2424 written = true; | |
| 2425 } | |
| 2426 | |
| 2427 // Write the position if it is different from what was written last time and | |
| 2428 // also different from the written statement position. | |
| 2429 if (current_position_ != written_position_ && | |
| 2430 current_position_ != written_statement_position_) { | |
| 2431 CheckBuffer(); | |
| 2432 RecordRelocInfo(RelocInfo::POSITION, current_position_); | |
| 2433 written_position_ = current_position_; | |
| 2434 written = true; | |
| 2435 } | |
| 2436 | |
| 2437 // Return whether something was written. | |
| 2438 return written; | |
| 2439 } | |
| 2440 | |
| 2441 | |
| 2442 void Assembler::GrowBuffer() { | 2398 void Assembler::GrowBuffer() { |
| 2443 if (!own_buffer_) FATAL("external code buffer is too small"); | 2399 if (!own_buffer_) FATAL("external code buffer is too small"); |
| 2444 | 2400 |
| 2445 // Compute new buffer size. | 2401 // Compute new buffer size. |
| 2446 CodeDesc desc; // the new buffer | 2402 CodeDesc desc; // the new buffer |
| 2447 if (buffer_size_ < 4*KB) { | 2403 if (buffer_size_ < 4*KB) { |
| 2448 desc.buffer_size = 4*KB; | 2404 desc.buffer_size = 4*KB; |
| 2449 } else if (buffer_size_ < 1*MB) { | 2405 } else if (buffer_size_ < 1*MB) { |
| 2450 desc.buffer_size = 2*buffer_size_; | 2406 desc.buffer_size = 2*buffer_size_; |
| 2451 } else { | 2407 } else { |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2628 | 2584 |
| 2629 // Since a constant pool was just emitted, move the check offset forward by | 2585 // Since a constant pool was just emitted, move the check offset forward by |
| 2630 // the standard interval. | 2586 // the standard interval. |
| 2631 next_buffer_check_ = pc_offset() + kCheckConstInterval; | 2587 next_buffer_check_ = pc_offset() + kCheckConstInterval; |
| 2632 } | 2588 } |
| 2633 | 2589 |
| 2634 | 2590 |
| 2635 } } // namespace v8::internal | 2591 } } // namespace v8::internal |
| 2636 | 2592 |
| 2637 #endif // V8_TARGET_ARCH_ARM | 2593 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |