| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 613 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; | 613 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; |
| 614 ldm(ia_w, sp, kSafepointSavedRegisters); | 614 ldm(ia_w, sp, kSafepointSavedRegisters); |
| 615 add(sp, sp, Operand(num_unsaved * kPointerSize)); | 615 add(sp, sp, Operand(num_unsaved * kPointerSize)); |
| 616 } | 616 } |
| 617 | 617 |
| 618 | 618 |
| 619 void MacroAssembler::PushSafepointRegistersAndDoubles() { | 619 void MacroAssembler::PushSafepointRegistersAndDoubles() { |
| 620 // Number of d-regs not known at snapshot time. | 620 // Number of d-regs not known at snapshot time. |
| 621 ASSERT(!Serializer::enabled()); | 621 ASSERT(!Serializer::enabled()); |
| 622 PushSafepointRegisters(); | 622 PushSafepointRegisters(); |
| 623 sub(sp, sp, Operand(DwVfpRegister::NumAllocatableRegisters() * | 623 // Only save allocatable registers. |
| 624 kDoubleSize)); | 624 ASSERT(kScratchDoubleReg.is(d15) && kDoubleRegZero.is(d14)); |
| 625 for (int i = 0; i < DwVfpRegister::NumAllocatableRegisters(); i++) { | 625 ASSERT(DwVfpRegister::NumReservedRegisters() == 2); |
| 626 vstr(DwVfpRegister::FromAllocationIndex(i), sp, i * kDoubleSize); | 626 if (CpuFeatures::IsSupported(VFP32DREGS)) { |
| 627 vstm(db_w, sp, d16, d31); |
| 627 } | 628 } |
| 629 vstm(db_w, sp, d0, d13); |
| 628 } | 630 } |
| 629 | 631 |
| 630 | 632 |
| 631 void MacroAssembler::PopSafepointRegistersAndDoubles() { | 633 void MacroAssembler::PopSafepointRegistersAndDoubles() { |
| 632 // Number of d-regs not known at snapshot time. | 634 // Number of d-regs not known at snapshot time. |
| 633 ASSERT(!Serializer::enabled()); | 635 ASSERT(!Serializer::enabled()); |
| 634 for (int i = 0; i < DwVfpRegister::NumAllocatableRegisters(); i++) { | 636 // Only save allocatable registers. |
| 635 vldr(DwVfpRegister::FromAllocationIndex(i), sp, i * kDoubleSize); | 637 ASSERT(kScratchDoubleReg.is(d15) && kDoubleRegZero.is(d14)); |
| 638 ASSERT(DwVfpRegister::NumReservedRegisters() == 2); |
| 639 vldm(ia_w, sp, d0, d13); |
| 640 if (CpuFeatures::IsSupported(VFP32DREGS)) { |
| 641 vldm(ia_w, sp, d16, d31); |
| 636 } | 642 } |
| 637 add(sp, sp, Operand(DwVfpRegister::NumAllocatableRegisters() * | |
| 638 kDoubleSize)); | |
| 639 PopSafepointRegisters(); | 643 PopSafepointRegisters(); |
| 640 } | 644 } |
| 641 | 645 |
| 642 void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register src, | 646 void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register src, |
| 643 Register dst) { | 647 Register dst) { |
| 644 str(src, SafepointRegistersAndDoublesSlot(dst)); | 648 str(src, SafepointRegistersAndDoublesSlot(dst)); |
| 645 } | 649 } |
| 646 | 650 |
| 647 | 651 |
| 648 void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) { | 652 void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) { |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 851 void MacroAssembler::VmovLow(DwVfpRegister dst, Register src) { | 855 void MacroAssembler::VmovLow(DwVfpRegister dst, Register src) { |
| 852 if (dst.code() < 16) { | 856 if (dst.code() < 16) { |
| 853 const LowDwVfpRegister loc = LowDwVfpRegister::from_code(dst.code()); | 857 const LowDwVfpRegister loc = LowDwVfpRegister::from_code(dst.code()); |
| 854 vmov(loc.low(), src); | 858 vmov(loc.low(), src); |
| 855 } else { | 859 } else { |
| 856 vmov(dst, VmovIndexLo, src); | 860 vmov(dst, VmovIndexLo, src); |
| 857 } | 861 } |
| 858 } | 862 } |
| 859 | 863 |
| 860 | 864 |
| 861 void MacroAssembler::LoadNumber(Register object, | |
| 862 LowDwVfpRegister dst, | |
| 863 Register heap_number_map, | |
| 864 Register scratch, | |
| 865 Label* not_number) { | |
| 866 Label is_smi, done; | |
| 867 | |
| 868 UntagAndJumpIfSmi(scratch, object, &is_smi); | |
| 869 JumpIfNotHeapNumber(object, heap_number_map, scratch, not_number); | |
| 870 | |
| 871 vldr(dst, FieldMemOperand(object, HeapNumber::kValueOffset)); | |
| 872 b(&done); | |
| 873 | |
| 874 // Handle loading a double from a smi. | |
| 875 bind(&is_smi); | |
| 876 vmov(dst.high(), scratch); | |
| 877 vcvt_f64_s32(dst, dst.high()); | |
| 878 | |
| 879 bind(&done); | |
| 880 } | |
| 881 | |
| 882 | |
| 883 void MacroAssembler::LoadNumberAsInt32Double(Register object, | |
| 884 DwVfpRegister double_dst, | |
| 885 Register heap_number_map, | |
| 886 Register scratch, | |
| 887 LowDwVfpRegister double_scratch, | |
| 888 Label* not_int32) { | |
| 889 ASSERT(!scratch.is(object)); | |
| 890 ASSERT(!heap_number_map.is(object) && !heap_number_map.is(scratch)); | |
| 891 | |
| 892 Label done, obj_is_not_smi; | |
| 893 | |
| 894 UntagAndJumpIfNotSmi(scratch, object, &obj_is_not_smi); | |
| 895 vmov(double_scratch.low(), scratch); | |
| 896 vcvt_f64_s32(double_dst, double_scratch.low()); | |
| 897 b(&done); | |
| 898 | |
| 899 bind(&obj_is_not_smi); | |
| 900 JumpIfNotHeapNumber(object, heap_number_map, scratch, not_int32); | |
| 901 | |
| 902 // Load the number. | |
| 903 // Load the double value. | |
| 904 vldr(double_dst, FieldMemOperand(object, HeapNumber::kValueOffset)); | |
| 905 | |
| 906 TestDoubleIsInt32(double_dst, double_scratch); | |
| 907 // Jump to not_int32 if the operation did not succeed. | |
| 908 b(ne, not_int32); | |
| 909 | |
| 910 bind(&done); | |
| 911 } | |
| 912 | |
| 913 | |
| 914 void MacroAssembler::LoadNumberAsInt32(Register object, | |
| 915 Register dst, | |
| 916 Register heap_number_map, | |
| 917 Register scratch, | |
| 918 DwVfpRegister double_scratch0, | |
| 919 LowDwVfpRegister double_scratch1, | |
| 920 Label* not_int32) { | |
| 921 ASSERT(!dst.is(object)); | |
| 922 ASSERT(!scratch.is(object)); | |
| 923 | |
| 924 Label done, maybe_undefined; | |
| 925 | |
| 926 UntagAndJumpIfSmi(dst, object, &done); | |
| 927 | |
| 928 JumpIfNotHeapNumber(object, heap_number_map, scratch, &maybe_undefined); | |
| 929 | |
| 930 // Object is a heap number. | |
| 931 // Convert the floating point value to a 32-bit integer. | |
| 932 // Load the double value. | |
| 933 vldr(double_scratch0, FieldMemOperand(object, HeapNumber::kValueOffset)); | |
| 934 | |
| 935 TryDoubleToInt32Exact(dst, double_scratch0, double_scratch1); | |
| 936 // Jump to not_int32 if the operation did not succeed. | |
| 937 b(ne, not_int32); | |
| 938 b(&done); | |
| 939 | |
| 940 bind(&maybe_undefined); | |
| 941 CompareRoot(object, Heap::kUndefinedValueRootIndex); | |
| 942 b(ne, not_int32); | |
| 943 // |undefined| is truncated to 0. | |
| 944 mov(dst, Operand(Smi::FromInt(0))); | |
| 945 // Fall through. | |
| 946 | |
| 947 bind(&done); | |
| 948 } | |
| 949 | |
| 950 | |
| 951 void MacroAssembler::Prologue(PrologueFrameMode frame_mode) { | 865 void MacroAssembler::Prologue(PrologueFrameMode frame_mode) { |
| 952 if (frame_mode == BUILD_STUB_FRAME) { | 866 if (frame_mode == BUILD_STUB_FRAME) { |
| 953 stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); | 867 stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); |
| 954 Push(Smi::FromInt(StackFrame::STUB)); | 868 Push(Smi::FromInt(StackFrame::STUB)); |
| 955 // Adjust FP to point to saved FP. | 869 // Adjust FP to point to saved FP. |
| 956 add(fp, sp, Operand(2 * kPointerSize)); | 870 add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); |
| 957 } else { | 871 } else { |
| 958 PredictableCodeSizeScope predictible_code_size_scope( | 872 PredictableCodeSizeScope predictible_code_size_scope( |
| 959 this, kNoCodeAgeSequenceLength * Assembler::kInstrSize); | 873 this, kNoCodeAgeSequenceLength * Assembler::kInstrSize); |
| 960 // The following three instructions must remain together and unmodified | 874 // The following three instructions must remain together and unmodified |
| 961 // for code aging to work properly. | 875 // for code aging to work properly. |
| 962 if (isolate()->IsCodePreAgingActive()) { | 876 if (isolate()->IsCodePreAgingActive()) { |
| 963 // Pre-age the code. | 877 // Pre-age the code. |
| 964 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); | 878 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); |
| 965 add(r0, pc, Operand(-8)); | 879 add(r0, pc, Operand(-8)); |
| 966 ldr(pc, MemOperand(pc, -4)); | 880 ldr(pc, MemOperand(pc, -4)); |
| 967 emit_code_stub_address(stub); | 881 emit_code_stub_address(stub); |
| 968 } else { | 882 } else { |
| 969 stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); | 883 stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); |
| 970 nop(ip.code()); | 884 nop(ip.code()); |
| 971 // Adjust FP to point to saved FP. | 885 // Adjust FP to point to saved FP. |
| 972 add(fp, sp, Operand(2 * kPointerSize)); | 886 add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); |
| 973 } | 887 } |
| 974 } | 888 } |
| 975 } | 889 } |
| 976 | 890 |
| 977 | 891 |
| 978 void MacroAssembler::EnterFrame(StackFrame::Type type) { | 892 void MacroAssembler::EnterFrame(StackFrame::Type type) { |
| 979 // r0-r3: preserved | 893 // r0-r3: preserved |
| 980 stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); | 894 stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); |
| 981 mov(ip, Operand(Smi::FromInt(type))); | 895 mov(ip, Operand(Smi::FromInt(type))); |
| 982 push(ip); | 896 push(ip); |
| 983 mov(ip, Operand(CodeObject())); | 897 mov(ip, Operand(CodeObject())); |
| 984 push(ip); | 898 push(ip); |
| 985 add(fp, sp, Operand(3 * kPointerSize)); // Adjust FP to point to saved FP. | 899 // Adjust FP to point to saved FP. |
| 900 add(fp, sp, |
| 901 Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize)); |
| 986 } | 902 } |
| 987 | 903 |
| 988 | 904 |
| 989 void MacroAssembler::LeaveFrame(StackFrame::Type type) { | 905 void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
| 990 // r0: preserved | 906 // r0: preserved |
| 991 // r1: preserved | 907 // r1: preserved |
| 992 // r2: preserved | 908 // r2: preserved |
| 993 | 909 |
| 994 // Drop the execution stack down to the frame pointer and restore | 910 // Drop the execution stack down to the frame pointer and restore |
| 995 // the caller frame pointer and return address. | 911 // the caller frame pointer and return address. |
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1583 | 1499 |
| 1584 ldr(scratch, FieldMemOperand(scratch, token_offset)); | 1500 ldr(scratch, FieldMemOperand(scratch, token_offset)); |
| 1585 ldr(ip, FieldMemOperand(ip, token_offset)); | 1501 ldr(ip, FieldMemOperand(ip, token_offset)); |
| 1586 cmp(scratch, Operand(ip)); | 1502 cmp(scratch, Operand(ip)); |
| 1587 b(ne, miss); | 1503 b(ne, miss); |
| 1588 | 1504 |
| 1589 bind(&same_contexts); | 1505 bind(&same_contexts); |
| 1590 } | 1506 } |
| 1591 | 1507 |
| 1592 | 1508 |
| 1509 // Compute the hash code from the untagged key. This must be kept in sync with |
| 1510 // ComputeIntegerHash in utils.h and KeyedLoadGenericElementStub in |
| 1511 // code-stub-hydrogen.cc |
| 1593 void MacroAssembler::GetNumberHash(Register t0, Register scratch) { | 1512 void MacroAssembler::GetNumberHash(Register t0, Register scratch) { |
| 1594 // First of all we assign the hash seed to scratch. | 1513 // First of all we assign the hash seed to scratch. |
| 1595 LoadRoot(scratch, Heap::kHashSeedRootIndex); | 1514 LoadRoot(scratch, Heap::kHashSeedRootIndex); |
| 1596 SmiUntag(scratch); | 1515 SmiUntag(scratch); |
| 1597 | 1516 |
| 1598 // Xor original key with a seed. | 1517 // Xor original key with a seed. |
| 1599 eor(t0, t0, Operand(scratch)); | 1518 eor(t0, t0, Operand(scratch)); |
| 1600 | 1519 |
| 1601 // Compute the hash code from the untagged key. This must be kept in sync | 1520 // Compute the hash code from the untagged key. This must be kept in sync |
| 1602 // with ComputeIntegerHash in utils.h. | 1521 // with ComputeIntegerHash in utils.h. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1649 Label done; | 1568 Label done; |
| 1650 | 1569 |
| 1651 GetNumberHash(t0, t1); | 1570 GetNumberHash(t0, t1); |
| 1652 | 1571 |
| 1653 // Compute the capacity mask. | 1572 // Compute the capacity mask. |
| 1654 ldr(t1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset)); | 1573 ldr(t1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset)); |
| 1655 SmiUntag(t1); | 1574 SmiUntag(t1); |
| 1656 sub(t1, t1, Operand(1)); | 1575 sub(t1, t1, Operand(1)); |
| 1657 | 1576 |
| 1658 // Generate an unrolled loop that performs a few probes before giving up. | 1577 // Generate an unrolled loop that performs a few probes before giving up. |
| 1659 static const int kProbes = 4; | 1578 for (int i = 0; i < kNumberDictionaryProbes; i++) { |
| 1660 for (int i = 0; i < kProbes; i++) { | |
| 1661 // Use t2 for index calculations and keep the hash intact in t0. | 1579 // Use t2 for index calculations and keep the hash intact in t0. |
| 1662 mov(t2, t0); | 1580 mov(t2, t0); |
| 1663 // Compute the masked index: (hash + i + i * i) & mask. | 1581 // Compute the masked index: (hash + i + i * i) & mask. |
| 1664 if (i > 0) { | 1582 if (i > 0) { |
| 1665 add(t2, t2, Operand(SeededNumberDictionary::GetProbeOffset(i))); | 1583 add(t2, t2, Operand(SeededNumberDictionary::GetProbeOffset(i))); |
| 1666 } | 1584 } |
| 1667 and_(t2, t2, Operand(t1)); | 1585 and_(t2, t2, Operand(t1)); |
| 1668 | 1586 |
| 1669 // Scale the index by multiplying by the element size. | 1587 // Scale the index by multiplying by the element size. |
| 1670 ASSERT(SeededNumberDictionary::kEntrySize == 3); | 1588 ASSERT(SeededNumberDictionary::kEntrySize == 3); |
| 1671 add(t2, t2, Operand(t2, LSL, 1)); // t2 = t2 * 3 | 1589 add(t2, t2, Operand(t2, LSL, 1)); // t2 = t2 * 3 |
| 1672 | 1590 |
| 1673 // Check if the key is identical to the name. | 1591 // Check if the key is identical to the name. |
| 1674 add(t2, elements, Operand(t2, LSL, kPointerSizeLog2)); | 1592 add(t2, elements, Operand(t2, LSL, kPointerSizeLog2)); |
| 1675 ldr(ip, FieldMemOperand(t2, SeededNumberDictionary::kElementsStartOffset)); | 1593 ldr(ip, FieldMemOperand(t2, SeededNumberDictionary::kElementsStartOffset)); |
| 1676 cmp(key, Operand(ip)); | 1594 cmp(key, Operand(ip)); |
| 1677 if (i != kProbes - 1) { | 1595 if (i != kNumberDictionaryProbes - 1) { |
| 1678 b(eq, &done); | 1596 b(eq, &done); |
| 1679 } else { | 1597 } else { |
| 1680 b(ne, miss); | 1598 b(ne, miss); |
| 1681 } | 1599 } |
| 1682 } | 1600 } |
| 1683 | 1601 |
| 1684 bind(&done); | 1602 bind(&done); |
| 1685 // Check that the value is a normal property. | 1603 // Check that the value is a normal property. |
| 1686 // t2: elements + (index * kPointerSize) | 1604 // t2: elements + (index * kPointerSize) |
| 1687 const int kDetailsOffset = | 1605 const int kDetailsOffset = |
| (...skipping 1780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3468 num_reg_arguments += 2 * num_double_arguments; | 3386 num_reg_arguments += 2 * num_double_arguments; |
| 3469 } | 3387 } |
| 3470 // Up to four simple arguments are passed in registers r0..r3. | 3388 // Up to four simple arguments are passed in registers r0..r3. |
| 3471 if (num_reg_arguments > kRegisterPassedArguments) { | 3389 if (num_reg_arguments > kRegisterPassedArguments) { |
| 3472 stack_passed_words += num_reg_arguments - kRegisterPassedArguments; | 3390 stack_passed_words += num_reg_arguments - kRegisterPassedArguments; |
| 3473 } | 3391 } |
| 3474 return stack_passed_words; | 3392 return stack_passed_words; |
| 3475 } | 3393 } |
| 3476 | 3394 |
| 3477 | 3395 |
| 3396 void MacroAssembler::EmitSeqStringSetCharCheck(Register string, |
| 3397 Register index, |
| 3398 Register value, |
| 3399 uint32_t encoding_mask) { |
| 3400 Label is_object; |
| 3401 SmiTst(string); |
| 3402 ThrowIf(eq, kNonObject); |
| 3403 |
| 3404 ldr(ip, FieldMemOperand(string, HeapObject::kMapOffset)); |
| 3405 ldrb(ip, FieldMemOperand(ip, Map::kInstanceTypeOffset)); |
| 3406 |
| 3407 and_(ip, ip, Operand(kStringRepresentationMask | kStringEncodingMask)); |
| 3408 cmp(ip, Operand(encoding_mask)); |
| 3409 ThrowIf(ne, kUnexpectedStringType); |
| 3410 |
| 3411 // The index is assumed to be untagged coming in, tag it to compare with the |
| 3412 // string length without using a temp register, it is restored at the end of |
| 3413 // this function. |
| 3414 Label index_tag_ok, index_tag_bad; |
| 3415 TrySmiTag(index, index, &index_tag_bad); |
| 3416 b(&index_tag_ok); |
| 3417 bind(&index_tag_bad); |
| 3418 Throw(kIndexIsTooLarge); |
| 3419 bind(&index_tag_ok); |
| 3420 |
| 3421 ldr(ip, FieldMemOperand(string, String::kLengthOffset)); |
| 3422 cmp(index, ip); |
| 3423 ThrowIf(ge, kIndexIsTooLarge); |
| 3424 |
| 3425 cmp(index, Operand(Smi::FromInt(0))); |
| 3426 ThrowIf(lt, kIndexIsNegative); |
| 3427 |
| 3428 SmiUntag(index, index); |
| 3429 } |
| 3430 |
| 3431 |
| 3478 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, | 3432 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, |
| 3479 int num_double_arguments, | 3433 int num_double_arguments, |
| 3480 Register scratch) { | 3434 Register scratch) { |
| 3481 int frame_alignment = ActivationFrameAlignment(); | 3435 int frame_alignment = ActivationFrameAlignment(); |
| 3482 int stack_passed_arguments = CalculateStackPassedWords( | 3436 int stack_passed_arguments = CalculateStackPassedWords( |
| 3483 num_reg_arguments, num_double_arguments); | 3437 num_reg_arguments, num_double_arguments); |
| 3484 if (frame_alignment > kPointerSize) { | 3438 if (frame_alignment > kPointerSize) { |
| 3485 // Make stack end at alignment and make room for num_arguments - 4 words | 3439 // Make stack end at alignment and make room for num_arguments - 4 words |
| 3486 // and the original value of sp. | 3440 // and the original value of sp. |
| 3487 mov(scratch, sp); | 3441 mov(scratch, sp); |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3851 bic(result_reg, ip, Operand(kVFPRoundingModeMask)); | 3805 bic(result_reg, ip, Operand(kVFPRoundingModeMask)); |
| 3852 vmsr(result_reg); | 3806 vmsr(result_reg); |
| 3853 vcvt_s32_f64(double_scratch.low(), input_reg, kFPSCRRounding); | 3807 vcvt_s32_f64(double_scratch.low(), input_reg, kFPSCRRounding); |
| 3854 vmov(result_reg, double_scratch.low()); | 3808 vmov(result_reg, double_scratch.low()); |
| 3855 // Restore FPSCR. | 3809 // Restore FPSCR. |
| 3856 vmsr(ip); | 3810 vmsr(ip); |
| 3857 bind(&done); | 3811 bind(&done); |
| 3858 } | 3812 } |
| 3859 | 3813 |
| 3860 | 3814 |
| 3815 void MacroAssembler::Throw(BailoutReason reason) { |
| 3816 Label throw_start; |
| 3817 bind(&throw_start); |
| 3818 #ifdef DEBUG |
| 3819 const char* msg = GetBailoutReason(reason); |
| 3820 if (msg != NULL) { |
| 3821 RecordComment("Throw message: "); |
| 3822 RecordComment(msg); |
| 3823 } |
| 3824 #endif |
| 3825 |
| 3826 mov(r0, Operand(Smi::FromInt(reason))); |
| 3827 push(r0); |
| 3828 // Disable stub call restrictions to always allow calls to throw. |
| 3829 if (!has_frame_) { |
| 3830 // We don't actually want to generate a pile of code for this, so just |
| 3831 // claim there is a stack frame, without generating one. |
| 3832 FrameScope scope(this, StackFrame::NONE); |
| 3833 CallRuntime(Runtime::kThrowMessage, 1); |
| 3834 } else { |
| 3835 CallRuntime(Runtime::kThrowMessage, 1); |
| 3836 } |
| 3837 // will not return here |
| 3838 if (is_const_pool_blocked()) { |
| 3839 // If the calling code cares throw the exact number of |
| 3840 // instructions generated, we insert padding here to keep the size |
| 3841 // of the ThrowMessage macro constant. |
| 3842 static const int kExpectedThrowMessageInstructions = 10; |
| 3843 int throw_instructions = InstructionsGeneratedSince(&throw_start); |
| 3844 ASSERT(throw_instructions <= kExpectedThrowMessageInstructions); |
| 3845 while (throw_instructions++ < kExpectedThrowMessageInstructions) { |
| 3846 nop(); |
| 3847 } |
| 3848 } |
| 3849 } |
| 3850 |
| 3851 |
| 3852 void MacroAssembler::ThrowIf(Condition cc, BailoutReason reason) { |
| 3853 Label L; |
| 3854 b(NegateCondition(cc), &L); |
| 3855 Throw(reason); |
| 3856 // will not return here |
| 3857 bind(&L); |
| 3858 } |
| 3859 |
| 3860 |
| 3861 void MacroAssembler::LoadInstanceDescriptors(Register map, | 3861 void MacroAssembler::LoadInstanceDescriptors(Register map, |
| 3862 Register descriptors) { | 3862 Register descriptors) { |
| 3863 ldr(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset)); | 3863 ldr(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset)); |
| 3864 } | 3864 } |
| 3865 | 3865 |
| 3866 | 3866 |
| 3867 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) { | 3867 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) { |
| 3868 ldr(dst, FieldMemOperand(map, Map::kBitField3Offset)); | 3868 ldr(dst, FieldMemOperand(map, Map::kBitField3Offset)); |
| 3869 DecodeField<Map::NumberOfOwnDescriptorsBits>(dst); | 3869 DecodeField<Map::NumberOfOwnDescriptorsBits>(dst); |
| 3870 } | 3870 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3881 Register empty_fixed_array_value = r6; | 3881 Register empty_fixed_array_value = r6; |
| 3882 LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); | 3882 LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); |
| 3883 Label next, start; | 3883 Label next, start; |
| 3884 mov(r2, r0); | 3884 mov(r2, r0); |
| 3885 | 3885 |
| 3886 // Check if the enum length field is properly initialized, indicating that | 3886 // Check if the enum length field is properly initialized, indicating that |
| 3887 // there is an enum cache. | 3887 // there is an enum cache. |
| 3888 ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset)); | 3888 ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset)); |
| 3889 | 3889 |
| 3890 EnumLength(r3, r1); | 3890 EnumLength(r3, r1); |
| 3891 cmp(r3, Operand(Smi::FromInt(Map::kInvalidEnumCache))); | 3891 cmp(r3, Operand(Smi::FromInt(kInvalidEnumCacheSentinel))); |
| 3892 b(eq, call_runtime); | 3892 b(eq, call_runtime); |
| 3893 | 3893 |
| 3894 jmp(&start); | 3894 jmp(&start); |
| 3895 | 3895 |
| 3896 bind(&next); | 3896 bind(&next); |
| 3897 ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset)); | 3897 ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset)); |
| 3898 | 3898 |
| 3899 // For all objects but the receiver, check that the cache is empty. | 3899 // For all objects but the receiver, check that the cache is empty. |
| 3900 EnumLength(r3, r1); | 3900 EnumLength(r3, r1); |
| 3901 cmp(r3, Operand(Smi::FromInt(0))); | 3901 cmp(r3, Operand(Smi::FromInt(0))); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4050 void CodePatcher::EmitCondition(Condition cond) { | 4050 void CodePatcher::EmitCondition(Condition cond) { |
| 4051 Instr instr = Assembler::instr_at(masm_.pc_); | 4051 Instr instr = Assembler::instr_at(masm_.pc_); |
| 4052 instr = (instr & ~kCondMask) | cond; | 4052 instr = (instr & ~kCondMask) | cond; |
| 4053 masm_.emit(instr); | 4053 masm_.emit(instr); |
| 4054 } | 4054 } |
| 4055 | 4055 |
| 4056 | 4056 |
| 4057 } } // namespace v8::internal | 4057 } } // namespace v8::internal |
| 4058 | 4058 |
| 4059 #endif // V8_TARGET_ARCH_ARM | 4059 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |