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

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

Issue 6606006: [Isolates] Merge 6500:6700 from bleeding_edge to isolates. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: '' Created 9 years, 9 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/macro-assembler-arm.h ('k') | src/arm/simulator-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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 478
479 void MacroAssembler::PopSafepointRegistersAndDoubles() { 479 void MacroAssembler::PopSafepointRegistersAndDoubles() {
480 for (int i = 0; i < DwVfpRegister::kNumAllocatableRegisters; i++) { 480 for (int i = 0; i < DwVfpRegister::kNumAllocatableRegisters; i++) {
481 vldr(DwVfpRegister::FromAllocationIndex(i), sp, i * kDoubleSize); 481 vldr(DwVfpRegister::FromAllocationIndex(i), sp, i * kDoubleSize);
482 } 482 }
483 add(sp, sp, Operand(DwVfpRegister::kNumAllocatableRegisters * 483 add(sp, sp, Operand(DwVfpRegister::kNumAllocatableRegisters *
484 kDoubleSize)); 484 kDoubleSize));
485 PopSafepointRegisters(); 485 PopSafepointRegisters();
486 } 486 }
487 487
488 void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register reg) {
489 str(reg, SafepointRegistersAndDoublesSlot(reg));
490 }
491
492
488 void MacroAssembler::StoreToSafepointRegisterSlot(Register reg) { 493 void MacroAssembler::StoreToSafepointRegisterSlot(Register reg) {
489 str(reg, SafepointRegisterSlot(reg)); 494 str(reg, SafepointRegisterSlot(reg));
490 } 495 }
491 496
492 497
498 void MacroAssembler::LoadFromSafepointRegisterSlot(Register reg) {
499 ldr(reg, SafepointRegisterSlot(reg));
500 }
501
502
493 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) { 503 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
494 // The registers are pushed starting with the highest encoding, 504 // The registers are pushed starting with the highest encoding,
495 // which means that lowest encodings are closest to the stack pointer. 505 // which means that lowest encodings are closest to the stack pointer.
496 ASSERT(reg_code >= 0 && reg_code < kNumSafepointRegisters); 506 ASSERT(reg_code >= 0 && reg_code < kNumSafepointRegisters);
497 return reg_code; 507 return reg_code;
498 } 508 }
499 509
500 510
501 MemOperand MacroAssembler::SafepointRegisterSlot(Register reg) { 511 MemOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
502 return MemOperand(sp, SafepointRegisterStackIndex(reg.code()) * kPointerSize); 512 return MemOperand(sp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
503 } 513 }
504 514
505 515
516 MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
517 // General purpose registers are pushed last on the stack.
518 int doubles_size = DwVfpRegister::kNumAllocatableRegisters * kDoubleSize;
519 int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
520 return MemOperand(sp, doubles_size + register_offset);
521 }
522
523
506 void MacroAssembler::Ldrd(Register dst1, Register dst2, 524 void MacroAssembler::Ldrd(Register dst1, Register dst2,
507 const MemOperand& src, Condition cond) { 525 const MemOperand& src, Condition cond) {
508 ASSERT(src.rm().is(no_reg)); 526 ASSERT(src.rm().is(no_reg));
509 ASSERT(!dst1.is(lr)); // r14. 527 ASSERT(!dst1.is(lr)); // r14.
510 ASSERT_EQ(0, dst1.code() % 2); 528 ASSERT_EQ(0, dst1.code() % 2);
511 ASSERT_EQ(dst1.code() + 1, dst2.code()); 529 ASSERT_EQ(dst1.code() + 1, dst2.code());
512 530
513 // Generate two ldr instructions if ldrd is not available. 531 // Generate two ldr instructions if ldrd is not available.
514 if (Isolate::Current()->cpu_features()->IsSupported(ARMv7)) { 532 if (Isolate::Current()->cpu_features()->IsSupported(ARMv7)) {
515 CpuFeatures::Scope scope(ARMv7); 533 CpuFeatures::Scope scope(ARMv7);
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 // r1: preserved 625 // r1: preserved
608 // r2: preserved 626 // r2: preserved
609 627
610 // Drop the execution stack down to the frame pointer and restore 628 // Drop the execution stack down to the frame pointer and restore
611 // the caller frame pointer and return address. 629 // the caller frame pointer and return address.
612 mov(sp, fp); 630 mov(sp, fp);
613 ldm(ia_w, sp, fp.bit() | lr.bit()); 631 ldm(ia_w, sp, fp.bit() | lr.bit());
614 } 632 }
615 633
616 634
617 void MacroAssembler::EnterExitFrame(bool save_doubles) { 635 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) {
618 // Compute the argv pointer in a callee-saved register.
619 add(r6, sp, Operand(r0, LSL, kPointerSizeLog2));
620 sub(r6, r6, Operand(kPointerSize));
621
622 // Setup the frame structure on the stack. 636 // Setup the frame structure on the stack.
623 ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); 637 ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement);
624 ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); 638 ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset);
625 ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); 639 ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset);
626 Push(lr, fp); 640 Push(lr, fp);
627 mov(fp, Operand(sp)); // Setup new frame pointer. 641 mov(fp, Operand(sp)); // Setup new frame pointer.
628 // Reserve room for saved entry sp and code object. 642 // Reserve room for saved entry sp and code object.
629 sub(sp, sp, Operand(2 * kPointerSize)); 643 sub(sp, sp, Operand(2 * kPointerSize));
630 if (FLAG_debug_code) { 644 if (FLAG_debug_code) {
631 mov(ip, Operand(0)); 645 mov(ip, Operand(0));
632 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); 646 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset));
633 } 647 }
634 mov(ip, Operand(CodeObject())); 648 mov(ip, Operand(CodeObject()));
635 str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset)); 649 str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset));
636 650
637 // Save the frame pointer and the context in top. 651 // Save the frame pointer and the context in top.
638 mov(ip, Operand(ExternalReference(Isolate::k_c_entry_fp_address))); 652 mov(ip, Operand(ExternalReference(Isolate::k_c_entry_fp_address)));
639 str(fp, MemOperand(ip)); 653 str(fp, MemOperand(ip));
640 mov(ip, Operand(ExternalReference(Isolate::k_context_address))); 654 mov(ip, Operand(ExternalReference(Isolate::k_context_address)));
641 str(cp, MemOperand(ip)); 655 str(cp, MemOperand(ip));
642 656
643 // Setup argc and the builtin function in callee-saved registers.
644 mov(r4, Operand(r0));
645 mov(r5, Operand(r1));
646
647 // Optionally save all double registers. 657 // Optionally save all double registers.
648 if (save_doubles) { 658 if (save_doubles) {
649 sub(sp, sp, Operand(DwVfpRegister::kNumRegisters * kDoubleSize)); 659 sub(sp, sp, Operand(DwVfpRegister::kNumRegisters * kDoubleSize));
650 const int offset = -2 * kPointerSize; 660 const int offset = -2 * kPointerSize;
651 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { 661 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) {
652 DwVfpRegister reg = DwVfpRegister::from_code(i); 662 DwVfpRegister reg = DwVfpRegister::from_code(i);
653 vstr(reg, fp, offset - ((i + 1) * kDoubleSize)); 663 vstr(reg, fp, offset - ((i + 1) * kDoubleSize));
654 } 664 }
655 // Note that d0 will be accessible at 665 // Note that d0 will be accessible at
656 // fp - 2 * kPointerSize - DwVfpRegister::kNumRegisters * kDoubleSize, 666 // fp - 2 * kPointerSize - DwVfpRegister::kNumRegisters * kDoubleSize,
657 // since the sp slot and code slot were pushed after the fp. 667 // since the sp slot and code slot were pushed after the fp.
658 } 668 }
659 669
660 // Reserve place for the return address and align the frame preparing for 670 // Reserve place for the return address and stack space and align the frame
661 // calling the runtime function. 671 // preparing for calling the runtime function.
662 const int frame_alignment = MacroAssembler::ActivationFrameAlignment(); 672 const int frame_alignment = MacroAssembler::ActivationFrameAlignment();
663 sub(sp, sp, Operand(kPointerSize)); 673 sub(sp, sp, Operand((stack_space + 1) * kPointerSize));
664 if (frame_alignment > 0) { 674 if (frame_alignment > 0) {
665 ASSERT(IsPowerOf2(frame_alignment)); 675 ASSERT(IsPowerOf2(frame_alignment));
666 and_(sp, sp, Operand(-frame_alignment)); 676 and_(sp, sp, Operand(-frame_alignment));
667 } 677 }
668 678
669 // Set the exit frame sp value to point just before the return address 679 // Set the exit frame sp value to point just before the return address
670 // location. 680 // location.
671 add(ip, sp, Operand(kPointerSize)); 681 add(ip, sp, Operand(kPointerSize));
672 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); 682 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset));
673 } 683 }
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after
1134 ldr(ip, MemOperand(topaddr)); 1144 ldr(ip, MemOperand(topaddr));
1135 cmp(result, ip); 1145 cmp(result, ip);
1136 Check(eq, "Unexpected allocation top"); 1146 Check(eq, "Unexpected allocation top");
1137 } 1147 }
1138 // Load allocation limit into ip. Result already contains allocation top. 1148 // Load allocation limit into ip. Result already contains allocation top.
1139 ldr(ip, MemOperand(topaddr, limit - top)); 1149 ldr(ip, MemOperand(topaddr, limit - top));
1140 } 1150 }
1141 1151
1142 // Calculate new top and bail out if new space is exhausted. Use result 1152 // Calculate new top and bail out if new space is exhausted. Use result
1143 // to calculate the new top. 1153 // to calculate the new top.
1144 add(scratch2, result, Operand(obj_size_reg)); 1154 add(scratch2, result, Operand(obj_size_reg), SetCC);
1155 b(cs, gc_required);
1145 cmp(scratch2, Operand(ip)); 1156 cmp(scratch2, Operand(ip));
1146 b(hi, gc_required); 1157 b(hi, gc_required);
1147 str(scratch2, MemOperand(topaddr)); 1158 str(scratch2, MemOperand(topaddr));
1148 1159
1149 // Tag object if requested. 1160 // Tag object if requested.
1150 if ((flags & TAG_OBJECT) != 0) { 1161 if ((flags & TAG_OBJECT) != 0) {
1151 add(result, result, Operand(kHeapObjectTag)); 1162 add(result, result, Operand(kHeapObjectTag));
1152 } 1163 }
1153 } 1164 }
1154 1165
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1213 Check(eq, "Unexpected allocation top"); 1224 Check(eq, "Unexpected allocation top");
1214 } 1225 }
1215 // Load allocation limit into ip. Result already contains allocation top. 1226 // Load allocation limit into ip. Result already contains allocation top.
1216 ldr(ip, MemOperand(topaddr, limit - top)); 1227 ldr(ip, MemOperand(topaddr, limit - top));
1217 } 1228 }
1218 1229
1219 // Calculate new top and bail out if new space is exhausted. Use result 1230 // Calculate new top and bail out if new space is exhausted. Use result
1220 // to calculate the new top. Object size may be in words so a shift is 1231 // to calculate the new top. Object size may be in words so a shift is
1221 // required to get the number of bytes. 1232 // required to get the number of bytes.
1222 if ((flags & SIZE_IN_WORDS) != 0) { 1233 if ((flags & SIZE_IN_WORDS) != 0) {
1223 add(scratch2, result, Operand(object_size, LSL, kPointerSizeLog2)); 1234 add(scratch2, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC);
1224 } else { 1235 } else {
1225 add(scratch2, result, Operand(object_size)); 1236 add(scratch2, result, Operand(object_size), SetCC);
1226 } 1237 }
1238 b(cs, gc_required);
1227 cmp(scratch2, Operand(ip)); 1239 cmp(scratch2, Operand(ip));
1228 b(hi, gc_required); 1240 b(hi, gc_required);
1229 1241
1230 // Update allocation top. result temporarily holds the new top. 1242 // Update allocation top. result temporarily holds the new top.
1231 if (FLAG_debug_code) { 1243 if (FLAG_debug_code) {
1232 tst(scratch2, Operand(kObjectAlignmentMask)); 1244 tst(scratch2, Operand(kObjectAlignmentMask));
1233 Check(eq, "Unaligned allocation in new space"); 1245 Check(eq, "Unaligned allocation in new space");
1234 } 1246 }
1235 str(scratch2, MemOperand(topaddr)); 1247 str(scratch2, MemOperand(topaddr));
1236 1248
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
1451 // in initial map. 1463 // in initial map.
1452 bind(&non_instance); 1464 bind(&non_instance);
1453 ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); 1465 ldr(result, FieldMemOperand(result, Map::kConstructorOffset));
1454 1466
1455 // All done. 1467 // All done.
1456 bind(&done); 1468 bind(&done);
1457 } 1469 }
1458 1470
1459 1471
1460 void MacroAssembler::CallStub(CodeStub* stub, Condition cond) { 1472 void MacroAssembler::CallStub(CodeStub* stub, Condition cond) {
1461 ASSERT(allow_stub_calls()); // stub calls are not allowed in some stubs 1473 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs.
1462 Call(stub->GetCode(), RelocInfo::CODE_TARGET, cond); 1474 Call(stub->GetCode(), RelocInfo::CODE_TARGET, cond);
1463 } 1475 }
1464 1476
1465 1477
1466 void MacroAssembler::TailCallStub(CodeStub* stub, Condition cond) { 1478 void MacroAssembler::TailCallStub(CodeStub* stub, Condition cond) {
1467 ASSERT(allow_stub_calls()); // stub calls are not allowed in some stubs 1479 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs.
1468 Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond); 1480 Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond);
1469 } 1481 }
1470 1482
1471 1483
1484 MaybeObject* MacroAssembler::TryTailCallStub(CodeStub* stub, Condition cond) {
1485 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs.
1486 Object* result;
1487 { MaybeObject* maybe_result = stub->TryGetCode();
1488 if (!maybe_result->ToObject(&result)) return maybe_result;
1489 }
1490 Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond);
1491 return result;
1492 }
1493
1494
1495 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
1496 return ref0.address() - ref1.address();
1497 }
1498
1499
1500 MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(
1501 ApiFunction* function, int stack_space) {
1502 ExternalReference next_address =
1503 ExternalReference::handle_scope_next_address();
1504 const int kNextOffset = 0;
1505 const int kLimitOffset = AddressOffset(
1506 ExternalReference::handle_scope_limit_address(),
1507 next_address);
1508 const int kLevelOffset = AddressOffset(
1509 ExternalReference::handle_scope_level_address(),
1510 next_address);
1511
1512 // Allocate HandleScope in callee-save registers.
1513 mov(r7, Operand(next_address));
1514 ldr(r4, MemOperand(r7, kNextOffset));
1515 ldr(r5, MemOperand(r7, kLimitOffset));
1516 ldr(r6, MemOperand(r7, kLevelOffset));
1517 add(r6, r6, Operand(1));
1518 str(r6, MemOperand(r7, kLevelOffset));
1519
1520 // Native call returns to the DirectCEntry stub which redirects to the
1521 // return address pushed on stack (could have moved after GC).
1522 // DirectCEntry stub itself is generated early and never moves.
1523 DirectCEntryStub stub;
1524 stub.GenerateCall(this, function);
1525
1526 Label promote_scheduled_exception;
1527 Label delete_allocated_handles;
1528 Label leave_exit_frame;
1529
1530 // If result is non-zero, dereference to get the result value
1531 // otherwise set it to undefined.
1532 cmp(r0, Operand(0));
1533 LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
1534 ldr(r0, MemOperand(r0), ne);
1535
1536 // No more valid handles (the result handle was the last one). Restore
1537 // previous handle scope.
1538 str(r4, MemOperand(r7, kNextOffset));
1539 if (FLAG_debug_code) {
1540 ldr(r1, MemOperand(r7, kLevelOffset));
1541 cmp(r1, r6);
1542 Check(eq, "Unexpected level after return from api call");
1543 }
1544 sub(r6, r6, Operand(1));
1545 str(r6, MemOperand(r7, kLevelOffset));
1546 ldr(ip, MemOperand(r7, kLimitOffset));
1547 cmp(r5, ip);
1548 b(ne, &delete_allocated_handles);
1549
1550 // Check if the function scheduled an exception.
1551 bind(&leave_exit_frame);
1552 LoadRoot(r4, Heap::kTheHoleValueRootIndex);
1553 mov(ip, Operand(ExternalReference::scheduled_exception_address()));
1554 ldr(r5, MemOperand(ip));
1555 cmp(r4, r5);
1556 b(ne, &promote_scheduled_exception);
1557
1558 // LeaveExitFrame expects unwind space to be in r4.
1559 mov(r4, Operand(stack_space));
1560 LeaveExitFrame(false);
1561
1562 bind(&promote_scheduled_exception);
1563 MaybeObject* result = TryTailCallExternalReference(
1564 ExternalReference(Runtime::kPromoteScheduledException), 0, 1);
1565 if (result->IsFailure()) {
1566 return result;
1567 }
1568
1569 // HandleScope limit has changed. Delete allocated extensions.
1570 bind(&delete_allocated_handles);
1571 str(r5, MemOperand(r7, kLimitOffset));
1572 mov(r4, r0);
1573 PrepareCallCFunction(0, r5);
1574 CallCFunction(ExternalReference::delete_handle_scope_extensions(), 0);
1575 mov(r0, r4);
1576 jmp(&leave_exit_frame);
1577
1578 return result;
1579 }
1580
1581
1472 void MacroAssembler::IllegalOperation(int num_arguments) { 1582 void MacroAssembler::IllegalOperation(int num_arguments) {
1473 if (num_arguments > 0) { 1583 if (num_arguments > 0) {
1474 add(sp, sp, Operand(num_arguments * kPointerSize)); 1584 add(sp, sp, Operand(num_arguments * kPointerSize));
1475 } 1585 }
1476 LoadRoot(r0, Heap::kUndefinedValueRootIndex); 1586 LoadRoot(r0, Heap::kUndefinedValueRootIndex);
1477 } 1587 }
1478 1588
1479 1589
1480 void MacroAssembler::IndexFromHash(Register hash, Register index) { 1590 void MacroAssembler::IndexFromHash(Register hash, Register index) {
1481 // If the hash field contains an array index pick it out. The assert checks 1591 // If the hash field contains an array index pick it out. The assert checks
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1553 } 1663 }
1554 1664
1555 1665
1556 // Tries to get a signed int32 out of a double precision floating point heap 1666 // Tries to get a signed int32 out of a double precision floating point heap
1557 // number. Rounds towards 0. Branch to 'not_int32' if the double is out of the 1667 // number. Rounds towards 0. Branch to 'not_int32' if the double is out of the
1558 // 32bits signed integer range. 1668 // 32bits signed integer range.
1559 void MacroAssembler::ConvertToInt32(Register source, 1669 void MacroAssembler::ConvertToInt32(Register source,
1560 Register dest, 1670 Register dest,
1561 Register scratch, 1671 Register scratch,
1562 Register scratch2, 1672 Register scratch2,
1673 DwVfpRegister double_scratch,
1563 Label *not_int32) { 1674 Label *not_int32) {
1564 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { 1675 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
1565 CpuFeatures::Scope scope(VFP3); 1676 CpuFeatures::Scope scope(VFP3);
1566 sub(scratch, source, Operand(kHeapObjectTag)); 1677 sub(scratch, source, Operand(kHeapObjectTag));
1567 vldr(d0, scratch, HeapNumber::kValueOffset); 1678 vldr(double_scratch, scratch, HeapNumber::kValueOffset);
1568 vcvt_s32_f64(s0, d0); 1679 vcvt_s32_f64(double_scratch.low(), double_scratch);
1569 vmov(dest, s0); 1680 vmov(dest, double_scratch.low());
1570 // Signed vcvt instruction will saturate to the minimum (0x80000000) or 1681 // Signed vcvt instruction will saturate to the minimum (0x80000000) or
1571 // maximun (0x7fffffff) signed 32bits integer when the double is out of 1682 // maximun (0x7fffffff) signed 32bits integer when the double is out of
1572 // range. When substracting one, the minimum signed integer becomes the 1683 // range. When substracting one, the minimum signed integer becomes the
1573 // maximun signed integer. 1684 // maximun signed integer.
1574 sub(scratch, dest, Operand(1)); 1685 sub(scratch, dest, Operand(1));
1575 cmp(scratch, Operand(LONG_MAX - 1)); 1686 cmp(scratch, Operand(LONG_MAX - 1));
1576 // If equal then dest was LONG_MAX, if greater dest was LONG_MIN. 1687 // If equal then dest was LONG_MAX, if greater dest was LONG_MIN.
1577 b(ge, not_int32); 1688 b(ge, not_int32);
1578 } else { 1689 } else {
1579 // This code is faster for doubles that are in the ranges -0x7fffffff to 1690 // This code is faster for doubles that are in the ranges -0x7fffffff to
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
1716 int result_size) { 1827 int result_size) {
1717 // TODO(1236192): Most runtime routines don't need the number of 1828 // TODO(1236192): Most runtime routines don't need the number of
1718 // arguments passed in because it is constant. At some point we 1829 // arguments passed in because it is constant. At some point we
1719 // should remove this need and make the runtime routine entry code 1830 // should remove this need and make the runtime routine entry code
1720 // smarter. 1831 // smarter.
1721 mov(r0, Operand(num_arguments)); 1832 mov(r0, Operand(num_arguments));
1722 JumpToExternalReference(ext); 1833 JumpToExternalReference(ext);
1723 } 1834 }
1724 1835
1725 1836
1837 MaybeObject* MacroAssembler::TryTailCallExternalReference(
1838 const ExternalReference& ext, int num_arguments, int result_size) {
1839 // TODO(1236192): Most runtime routines don't need the number of
1840 // arguments passed in because it is constant. At some point we
1841 // should remove this need and make the runtime routine entry code
1842 // smarter.
1843 mov(r0, Operand(num_arguments));
1844 return TryJumpToExternalReference(ext);
1845 }
1846
1847
1726 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, 1848 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
1727 int num_arguments, 1849 int num_arguments,
1728 int result_size) { 1850 int result_size) {
1729 TailCallExternalReference(ExternalReference(fid), num_arguments, result_size); 1851 TailCallExternalReference(ExternalReference(fid), num_arguments, result_size);
1730 } 1852 }
1731 1853
1732 1854
1733 void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin) { 1855 void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin) {
1734 #if defined(__thumb__) 1856 #if defined(__thumb__)
1735 // Thumb mode builtin. 1857 // Thumb mode builtin.
1736 ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1); 1858 ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1);
1737 #endif 1859 #endif
1738 mov(r1, Operand(builtin)); 1860 mov(r1, Operand(builtin));
1739 CEntryStub stub(1); 1861 CEntryStub stub(1);
1740 Jump(stub.GetCode(), RelocInfo::CODE_TARGET); 1862 Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
1741 } 1863 }
1742 1864
1743 1865
1866 MaybeObject* MacroAssembler::TryJumpToExternalReference(
1867 const ExternalReference& builtin) {
1868 #if defined(__thumb__)
1869 // Thumb mode builtin.
1870 ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1);
1871 #endif
1872 mov(r1, Operand(builtin));
1873 CEntryStub stub(1);
1874 return TryTailCallStub(&stub);
1875 }
1876
1877
1744 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, 1878 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
1745 InvokeJSFlags flags, 1879 InvokeJSFlags flags,
1746 PostCallGenerator* post_call_generator) { 1880 PostCallGenerator* post_call_generator) {
1747 GetBuiltinEntry(r2, id); 1881 GetBuiltinEntry(r2, id);
1748 if (flags == CALL_JS) { 1882 if (flags == CALL_JS) {
1749 Call(r2); 1883 Call(r2);
1750 if (post_call_generator != NULL) post_call_generator->Generate(); 1884 if (post_call_generator != NULL) post_call_generator->Generate();
1751 } else { 1885 } else {
1752 ASSERT(flags == JUMP_JS); 1886 ASSERT(flags == JUMP_JS);
1753 Jump(r2); 1887 Jump(r2);
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
1931 Label ok, fail; 2065 Label ok, fail;
1932 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, false); 2066 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, false);
1933 b(&ok); 2067 b(&ok);
1934 bind(&fail); 2068 bind(&fail);
1935 Abort("Global functions must have initial map"); 2069 Abort("Global functions must have initial map");
1936 bind(&ok); 2070 bind(&ok);
1937 } 2071 }
1938 } 2072 }
1939 2073
1940 2074
2075 void MacroAssembler::JumpIfNotPowerOfTwoOrZero(
2076 Register reg,
2077 Register scratch,
2078 Label* not_power_of_two_or_zero) {
2079 sub(scratch, reg, Operand(1), SetCC);
2080 b(mi, not_power_of_two_or_zero);
2081 tst(scratch, reg);
2082 b(ne, not_power_of_two_or_zero);
2083 }
2084
2085
1941 void MacroAssembler::JumpIfNotBothSmi(Register reg1, 2086 void MacroAssembler::JumpIfNotBothSmi(Register reg1,
1942 Register reg2, 2087 Register reg2,
1943 Label* on_not_both_smi) { 2088 Label* on_not_both_smi) {
1944 STATIC_ASSERT(kSmiTag == 0); 2089 STATIC_ASSERT(kSmiTag == 0);
1945 tst(reg1, Operand(kSmiTagMask)); 2090 tst(reg1, Operand(kSmiTagMask));
1946 tst(reg2, Operand(kSmiTagMask), eq); 2091 tst(reg2, Operand(kSmiTagMask), eq);
1947 b(ne, on_not_both_smi); 2092 b(ne, on_not_both_smi);
1948 } 2093 }
1949 2094
1950 2095
(...skipping 14 matching lines...) Expand all
1965 } 2110 }
1966 2111
1967 2112
1968 void MacroAssembler::AbortIfNotSmi(Register object) { 2113 void MacroAssembler::AbortIfNotSmi(Register object) {
1969 STATIC_ASSERT(kSmiTag == 0); 2114 STATIC_ASSERT(kSmiTag == 0);
1970 tst(object, Operand(kSmiTagMask)); 2115 tst(object, Operand(kSmiTagMask));
1971 Assert(eq, "Operand is not smi"); 2116 Assert(eq, "Operand is not smi");
1972 } 2117 }
1973 2118
1974 2119
2120 void MacroAssembler::AbortIfNotRootValue(Register src,
2121 Heap::RootListIndex root_value_index,
2122 const char* message) {
2123 ASSERT(!src.is(ip));
2124 LoadRoot(ip, root_value_index);
2125 cmp(src, ip);
2126 Assert(eq, message);
2127 }
2128
2129
1975 void MacroAssembler::JumpIfNotHeapNumber(Register object, 2130 void MacroAssembler::JumpIfNotHeapNumber(Register object,
1976 Register heap_number_map, 2131 Register heap_number_map,
1977 Register scratch, 2132 Register scratch,
1978 Label* on_not_heap_number) { 2133 Label* on_not_heap_number) {
1979 ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); 2134 ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
1980 AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 2135 AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
1981 cmp(scratch, heap_number_map); 2136 cmp(scratch, heap_number_map);
1982 b(ne, on_not_heap_number); 2137 b(ne, on_not_heap_number);
1983 } 2138 }
1984 2139
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
2079 for (int i = 0; i < field_count; i++) { 2234 for (int i = 0; i < field_count; i++) {
2080 ldr(tmp, FieldMemOperand(src, i * kPointerSize)); 2235 ldr(tmp, FieldMemOperand(src, i * kPointerSize));
2081 str(tmp, FieldMemOperand(dst, i * kPointerSize)); 2236 str(tmp, FieldMemOperand(dst, i * kPointerSize));
2082 } 2237 }
2083 } 2238 }
2084 2239
2085 2240
2086 void MacroAssembler::CountLeadingZeros(Register zeros, // Answer. 2241 void MacroAssembler::CountLeadingZeros(Register zeros, // Answer.
2087 Register source, // Input. 2242 Register source, // Input.
2088 Register scratch) { 2243 Register scratch) {
2089 ASSERT(!zeros.is(source) || !source.is(zeros)); 2244 ASSERT(!zeros.is(source) || !source.is(scratch));
2090 ASSERT(!zeros.is(scratch)); 2245 ASSERT(!zeros.is(scratch));
2091 ASSERT(!scratch.is(ip)); 2246 ASSERT(!scratch.is(ip));
2092 ASSERT(!source.is(ip)); 2247 ASSERT(!source.is(ip));
2093 ASSERT(!zeros.is(ip)); 2248 ASSERT(!zeros.is(ip));
2094 #ifdef CAN_USE_ARMV5_INSTRUCTIONS 2249 #ifdef CAN_USE_ARMV5_INSTRUCTIONS
2095 clz(zeros, source); // This instruction is only supported after ARM5. 2250 clz(zeros, source); // This instruction is only supported after ARM5.
2096 #else 2251 #else
2097 mov(zeros, Operand(0, RelocInfo::NONE)); 2252 mov(zeros, Operand(0, RelocInfo::NONE));
2098 Move(scratch, source); 2253 Move(scratch, source);
2099 // Top 16. 2254 // Top 16.
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
2293 2448
2294 void CodePatcher::Emit(Address addr) { 2449 void CodePatcher::Emit(Address addr) {
2295 masm()->emit(reinterpret_cast<Instr>(addr)); 2450 masm()->emit(reinterpret_cast<Instr>(addr));
2296 } 2451 }
2297 #endif // ENABLE_DEBUGGER_SUPPORT 2452 #endif // ENABLE_DEBUGGER_SUPPORT
2298 2453
2299 2454
2300 } } // namespace v8::internal 2455 } } // namespace v8::internal
2301 2456
2302 #endif // V8_TARGET_ARCH_ARM 2457 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/macro-assembler-arm.h ('k') | src/arm/simulator-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698