OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <limits.h> // For LONG_MIN, LONG_MAX. | 5 #include <limits.h> // For LONG_MIN, LONG_MAX. |
6 | 6 |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 | 8 |
9 #if V8_TARGET_ARCH_ARM | 9 #if V8_TARGET_ARCH_ARM |
10 | 10 |
(...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 pop(lr); | 684 pop(lr); |
685 bind(&done); | 685 bind(&done); |
686 if (and_then == kReturnAtEnd) { | 686 if (and_then == kReturnAtEnd) { |
687 Ret(); | 687 Ret(); |
688 } | 688 } |
689 } | 689 } |
690 | 690 |
691 | 691 |
692 void MacroAssembler::PushFixedFrame(Register marker_reg) { | 692 void MacroAssembler::PushFixedFrame(Register marker_reg) { |
693 DCHECK(!marker_reg.is_valid() || marker_reg.code() < cp.code()); | 693 DCHECK(!marker_reg.is_valid() || marker_reg.code() < cp.code()); |
694 stm(db_w, sp, (marker_reg.is_valid() ? marker_reg.bit() : 0) | cp.bit() | | 694 stm(db_w, sp, (marker_reg.is_valid() ? marker_reg.bit() : 0) | |
695 (FLAG_enable_embedded_constant_pool ? pp.bit() : 0) | | 695 cp.bit() | |
696 fp.bit() | lr.bit()); | 696 (FLAG_enable_ool_constant_pool ? pp.bit() : 0) | |
| 697 fp.bit() | |
| 698 lr.bit()); |
697 } | 699 } |
698 | 700 |
699 | 701 |
700 void MacroAssembler::PopFixedFrame(Register marker_reg) { | 702 void MacroAssembler::PopFixedFrame(Register marker_reg) { |
701 DCHECK(!marker_reg.is_valid() || marker_reg.code() < cp.code()); | 703 DCHECK(!marker_reg.is_valid() || marker_reg.code() < cp.code()); |
702 ldm(ia_w, sp, (marker_reg.is_valid() ? marker_reg.bit() : 0) | cp.bit() | | 704 ldm(ia_w, sp, (marker_reg.is_valid() ? marker_reg.bit() : 0) | |
703 (FLAG_enable_embedded_constant_pool ? pp.bit() : 0) | | 705 cp.bit() | |
704 fp.bit() | lr.bit()); | 706 (FLAG_enable_ool_constant_pool ? pp.bit() : 0) | |
| 707 fp.bit() | |
| 708 lr.bit()); |
705 } | 709 } |
706 | 710 |
707 | 711 |
708 // Push and pop all registers that can hold pointers. | 712 // Push and pop all registers that can hold pointers. |
709 void MacroAssembler::PushSafepointRegisters() { | 713 void MacroAssembler::PushSafepointRegisters() { |
710 // Safepoints expect a block of contiguous register values starting with r0: | 714 // Safepoints expect a block of contiguous register values starting with r0: |
711 DCHECK(((1 << kNumSafepointSavedRegisters) - 1) == kSafepointSavedRegisters); | 715 DCHECK(((1 << kNumSafepointSavedRegisters) - 1) == kSafepointSavedRegisters); |
712 // Safepoints expect a block of kNumSafepointRegisters values on the | 716 // Safepoints expect a block of kNumSafepointRegisters values on the |
713 // stack, so adjust the stack for unsaved registers. | 717 // stack, so adjust the stack for unsaved registers. |
714 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; | 718 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
974 void MacroAssembler::VmovLow(DwVfpRegister dst, Register src) { | 978 void MacroAssembler::VmovLow(DwVfpRegister dst, Register src) { |
975 if (dst.code() < 16) { | 979 if (dst.code() < 16) { |
976 const LowDwVfpRegister loc = LowDwVfpRegister::from_code(dst.code()); | 980 const LowDwVfpRegister loc = LowDwVfpRegister::from_code(dst.code()); |
977 vmov(loc.low(), src); | 981 vmov(loc.low(), src); |
978 } else { | 982 } else { |
979 vmov(dst, VmovIndexLo, src); | 983 vmov(dst, VmovIndexLo, src); |
980 } | 984 } |
981 } | 985 } |
982 | 986 |
983 | 987 |
984 void MacroAssembler::LoadConstantPoolPointerRegisterFromCodeTargetAddress( | |
985 Register code_target_address) { | |
986 DCHECK(FLAG_enable_embedded_constant_pool); | |
987 ldr(pp, MemOperand(code_target_address, | |
988 Code::kConstantPoolOffset - Code::kHeaderSize)); | |
989 add(pp, pp, code_target_address); | |
990 } | |
991 | |
992 | |
993 void MacroAssembler::LoadConstantPoolPointerRegister() { | 988 void MacroAssembler::LoadConstantPoolPointerRegister() { |
994 DCHECK(FLAG_enable_embedded_constant_pool); | 989 if (FLAG_enable_ool_constant_pool) { |
995 int entry_offset = pc_offset() + Instruction::kPCReadOffset; | 990 int constant_pool_offset = Code::kConstantPoolOffset - Code::kHeaderSize - |
996 sub(ip, pc, Operand(entry_offset)); | 991 pc_offset() - Instruction::kPCReadOffset; |
997 LoadConstantPoolPointerRegisterFromCodeTargetAddress(ip); | 992 DCHECK(ImmediateFitsAddrMode2Instruction(constant_pool_offset)); |
| 993 ldr(pp, MemOperand(pc, constant_pool_offset)); |
| 994 } |
998 } | 995 } |
999 | 996 |
1000 | 997 |
1001 void MacroAssembler::StubPrologue() { | 998 void MacroAssembler::StubPrologue() { |
1002 PushFixedFrame(); | 999 PushFixedFrame(); |
1003 Push(Smi::FromInt(StackFrame::STUB)); | 1000 Push(Smi::FromInt(StackFrame::STUB)); |
1004 // Adjust FP to point to saved FP. | 1001 // Adjust FP to point to saved FP. |
1005 add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); | 1002 add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); |
1006 if (FLAG_enable_embedded_constant_pool) { | 1003 if (FLAG_enable_ool_constant_pool) { |
1007 LoadConstantPoolPointerRegister(); | 1004 LoadConstantPoolPointerRegister(); |
1008 set_constant_pool_available(true); | 1005 set_ool_constant_pool_available(true); |
1009 } | 1006 } |
1010 } | 1007 } |
1011 | 1008 |
1012 | 1009 |
1013 void MacroAssembler::Prologue(bool code_pre_aging) { | 1010 void MacroAssembler::Prologue(bool code_pre_aging) { |
1014 { PredictableCodeSizeScope predictible_code_size_scope( | 1011 { PredictableCodeSizeScope predictible_code_size_scope( |
1015 this, kNoCodeAgeSequenceLength); | 1012 this, kNoCodeAgeSequenceLength); |
1016 // The following three instructions must remain together and unmodified | 1013 // The following three instructions must remain together and unmodified |
1017 // for code aging to work properly. | 1014 // for code aging to work properly. |
1018 if (code_pre_aging) { | 1015 if (code_pre_aging) { |
1019 // Pre-age the code. | 1016 // Pre-age the code. |
1020 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); | 1017 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); |
1021 add(r0, pc, Operand(-8)); | 1018 add(r0, pc, Operand(-8)); |
1022 ldr(pc, MemOperand(pc, -4)); | 1019 ldr(pc, MemOperand(pc, -4)); |
1023 emit_code_stub_address(stub); | 1020 emit_code_stub_address(stub); |
1024 } else { | 1021 } else { |
1025 PushFixedFrame(r1); | 1022 PushFixedFrame(r1); |
1026 nop(ip.code()); | 1023 nop(ip.code()); |
1027 // Adjust FP to point to saved FP. | 1024 // Adjust FP to point to saved FP. |
1028 add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); | 1025 add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); |
1029 } | 1026 } |
1030 } | 1027 } |
1031 if (FLAG_enable_embedded_constant_pool) { | 1028 if (FLAG_enable_ool_constant_pool) { |
1032 LoadConstantPoolPointerRegister(); | 1029 LoadConstantPoolPointerRegister(); |
1033 set_constant_pool_available(true); | 1030 set_ool_constant_pool_available(true); |
1034 } | 1031 } |
1035 } | 1032 } |
1036 | 1033 |
1037 | 1034 |
1038 void MacroAssembler::EnterFrame(StackFrame::Type type, | 1035 void MacroAssembler::EnterFrame(StackFrame::Type type, |
1039 bool load_constant_pool_pointer_reg) { | 1036 bool load_constant_pool_pointer_reg) { |
1040 // r0-r3: preserved | 1037 // r0-r3: preserved |
1041 PushFixedFrame(); | 1038 PushFixedFrame(); |
1042 if (FLAG_enable_embedded_constant_pool && load_constant_pool_pointer_reg) { | 1039 if (FLAG_enable_ool_constant_pool && load_constant_pool_pointer_reg) { |
1043 LoadConstantPoolPointerRegister(); | 1040 LoadConstantPoolPointerRegister(); |
1044 } | 1041 } |
1045 mov(ip, Operand(Smi::FromInt(type))); | 1042 mov(ip, Operand(Smi::FromInt(type))); |
1046 push(ip); | 1043 push(ip); |
1047 mov(ip, Operand(CodeObject())); | 1044 mov(ip, Operand(CodeObject())); |
1048 push(ip); | 1045 push(ip); |
1049 // Adjust FP to point to saved FP. | 1046 // Adjust FP to point to saved FP. |
1050 add(fp, sp, | 1047 add(fp, sp, |
1051 Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize)); | 1048 Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize)); |
1052 } | 1049 } |
1053 | 1050 |
1054 | 1051 |
1055 int MacroAssembler::LeaveFrame(StackFrame::Type type) { | 1052 int MacroAssembler::LeaveFrame(StackFrame::Type type) { |
1056 // r0: preserved | 1053 // r0: preserved |
1057 // r1: preserved | 1054 // r1: preserved |
1058 // r2: preserved | 1055 // r2: preserved |
1059 | 1056 |
1060 // Drop the execution stack down to the frame pointer and restore | 1057 // Drop the execution stack down to the frame pointer and restore |
1061 // the caller frame pointer, return address and constant pool pointer | 1058 // the caller frame pointer, return address and constant pool pointer |
1062 // (if FLAG_enable_embedded_constant_pool). | 1059 // (if FLAG_enable_ool_constant_pool). |
1063 int frame_ends; | 1060 int frame_ends; |
1064 if (FLAG_enable_embedded_constant_pool) { | 1061 if (FLAG_enable_ool_constant_pool) { |
1065 add(sp, fp, Operand(StandardFrameConstants::kConstantPoolOffset)); | 1062 add(sp, fp, Operand(StandardFrameConstants::kConstantPoolOffset)); |
1066 frame_ends = pc_offset(); | 1063 frame_ends = pc_offset(); |
1067 ldm(ia_w, sp, pp.bit() | fp.bit() | lr.bit()); | 1064 ldm(ia_w, sp, pp.bit() | fp.bit() | lr.bit()); |
1068 } else { | 1065 } else { |
1069 mov(sp, fp); | 1066 mov(sp, fp); |
1070 frame_ends = pc_offset(); | 1067 frame_ends = pc_offset(); |
1071 ldm(ia_w, sp, fp.bit() | lr.bit()); | 1068 ldm(ia_w, sp, fp.bit() | lr.bit()); |
1072 } | 1069 } |
1073 return frame_ends; | 1070 return frame_ends; |
1074 } | 1071 } |
1075 | 1072 |
1076 | 1073 |
1077 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { | 1074 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { |
1078 // Set up the frame structure on the stack. | 1075 // Set up the frame structure on the stack. |
1079 DCHECK_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); | 1076 DCHECK_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); |
1080 DCHECK_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); | 1077 DCHECK_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); |
1081 DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); | 1078 DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); |
1082 Push(lr, fp); | 1079 Push(lr, fp); |
1083 mov(fp, Operand(sp)); // Set up new frame pointer. | 1080 mov(fp, Operand(sp)); // Set up new frame pointer. |
1084 // Reserve room for saved entry sp and code object. | 1081 // Reserve room for saved entry sp and code object. |
1085 sub(sp, sp, Operand(ExitFrameConstants::kFrameSize)); | 1082 sub(sp, sp, Operand(ExitFrameConstants::kFrameSize)); |
1086 if (emit_debug_code()) { | 1083 if (emit_debug_code()) { |
1087 mov(ip, Operand::Zero()); | 1084 mov(ip, Operand::Zero()); |
1088 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); | 1085 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
1089 } | 1086 } |
1090 if (FLAG_enable_embedded_constant_pool) { | 1087 if (FLAG_enable_ool_constant_pool) { |
1091 str(pp, MemOperand(fp, ExitFrameConstants::kConstantPoolOffset)); | 1088 str(pp, MemOperand(fp, ExitFrameConstants::kConstantPoolOffset)); |
1092 } | 1089 } |
1093 mov(ip, Operand(CodeObject())); | 1090 mov(ip, Operand(CodeObject())); |
1094 str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset)); | 1091 str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset)); |
1095 | 1092 |
1096 // Save the frame pointer and the context in top. | 1093 // Save the frame pointer and the context in top. |
1097 mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); | 1094 mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); |
1098 str(fp, MemOperand(ip)); | 1095 str(fp, MemOperand(ip)); |
1099 mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); | 1096 mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); |
1100 str(cp, MemOperand(ip)); | 1097 str(cp, MemOperand(ip)); |
1101 | 1098 |
1102 // Optionally save all double registers. | 1099 // Optionally save all double registers. |
1103 if (save_doubles) { | 1100 if (save_doubles) { |
1104 SaveFPRegs(sp, ip); | 1101 SaveFPRegs(sp, ip); |
1105 // Note that d0 will be accessible at | 1102 // Note that d0 will be accessible at |
1106 // fp - ExitFrameConstants::kFrameSize - | 1103 // fp - ExitFrameConstants::kFrameSize - |
1107 // DwVfpRegister::kMaxNumRegisters * kDoubleSize, | 1104 // DwVfpRegister::kMaxNumRegisters * kDoubleSize, |
1108 // since the sp slot, code slot and constant pool slot (if | 1105 // since the sp slot, code slot and constant pool slot (if |
1109 // FLAG_enable_embedded_constant_pool) were pushed after the fp. | 1106 // FLAG_enable_ool_constant_pool) were pushed after the fp. |
1110 } | 1107 } |
1111 | 1108 |
1112 // Reserve place for the return address and stack space and align the frame | 1109 // Reserve place for the return address and stack space and align the frame |
1113 // preparing for calling the runtime function. | 1110 // preparing for calling the runtime function. |
1114 const int frame_alignment = MacroAssembler::ActivationFrameAlignment(); | 1111 const int frame_alignment = MacroAssembler::ActivationFrameAlignment(); |
1115 sub(sp, sp, Operand((stack_space + 1) * kPointerSize)); | 1112 sub(sp, sp, Operand((stack_space + 1) * kPointerSize)); |
1116 if (frame_alignment > 0) { | 1113 if (frame_alignment > 0) { |
1117 DCHECK(base::bits::IsPowerOfTwo32(frame_alignment)); | 1114 DCHECK(base::bits::IsPowerOfTwo32(frame_alignment)); |
1118 and_(sp, sp, Operand(-frame_alignment)); | 1115 and_(sp, sp, Operand(-frame_alignment)); |
1119 } | 1116 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1179 if (restore_context) { | 1176 if (restore_context) { |
1180 mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); | 1177 mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); |
1181 ldr(cp, MemOperand(ip)); | 1178 ldr(cp, MemOperand(ip)); |
1182 } | 1179 } |
1183 #ifdef DEBUG | 1180 #ifdef DEBUG |
1184 mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); | 1181 mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); |
1185 str(r3, MemOperand(ip)); | 1182 str(r3, MemOperand(ip)); |
1186 #endif | 1183 #endif |
1187 | 1184 |
1188 // Tear down the exit frame, pop the arguments, and return. | 1185 // Tear down the exit frame, pop the arguments, and return. |
1189 if (FLAG_enable_embedded_constant_pool) { | 1186 if (FLAG_enable_ool_constant_pool) { |
1190 ldr(pp, MemOperand(fp, ExitFrameConstants::kConstantPoolOffset)); | 1187 ldr(pp, MemOperand(fp, ExitFrameConstants::kConstantPoolOffset)); |
1191 } | 1188 } |
1192 mov(sp, Operand(fp)); | 1189 mov(sp, Operand(fp)); |
1193 ldm(ia_w, sp, fp.bit() | lr.bit()); | 1190 ldm(ia_w, sp, fp.bit() | lr.bit()); |
1194 if (argument_count.is_valid()) { | 1191 if (argument_count.is_valid()) { |
1195 if (argument_count_is_length) { | 1192 if (argument_count_is_length) { |
1196 add(sp, sp, argument_count); | 1193 add(sp, sp, argument_count); |
1197 } else { | 1194 } else { |
1198 add(sp, sp, Operand(argument_count, LSL, kPointerSizeLog2)); | 1195 add(sp, sp, Operand(argument_count, LSL, kPointerSizeLog2)); |
1199 } | 1196 } |
(...skipping 2198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3398 } | 3395 } |
3399 } | 3396 } |
3400 | 3397 |
3401 | 3398 |
3402 void MacroAssembler::GetRelocatedValueLocation(Register ldr_location, | 3399 void MacroAssembler::GetRelocatedValueLocation(Register ldr_location, |
3403 Register result, | 3400 Register result, |
3404 Register scratch) { | 3401 Register scratch) { |
3405 Label small_constant_pool_load, load_result; | 3402 Label small_constant_pool_load, load_result; |
3406 ldr(result, MemOperand(ldr_location)); | 3403 ldr(result, MemOperand(ldr_location)); |
3407 | 3404 |
3408 if (FLAG_enable_embedded_constant_pool) { | 3405 if (FLAG_enable_ool_constant_pool) { |
3409 // Check if this is an extended constant pool load. | 3406 // Check if this is an extended constant pool load. |
3410 and_(scratch, result, Operand(GetConsantPoolLoadMask())); | 3407 and_(scratch, result, Operand(GetConsantPoolLoadMask())); |
3411 teq(scratch, Operand(GetConsantPoolLoadPattern())); | 3408 teq(scratch, Operand(GetConsantPoolLoadPattern())); |
3412 b(eq, &small_constant_pool_load); | 3409 b(eq, &small_constant_pool_load); |
3413 if (emit_debug_code()) { | 3410 if (emit_debug_code()) { |
3414 // Check that the instruction sequence is: | 3411 // Check that the instruction sequence is: |
3415 // movw reg, #offset_low | 3412 // movw reg, #offset_low |
3416 // movt reg, #offset_high | 3413 // movt reg, #offset_high |
3417 // ldr reg, [pp, reg] | 3414 // ldr reg, [pp, reg] |
3418 Instr patterns[] = {GetMovWPattern(), GetMovTPattern(), | 3415 Instr patterns[] = {GetMovWPattern(), GetMovTPattern(), |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3452 // Result was clobbered. Restore it. | 3449 // Result was clobbered. Restore it. |
3453 ldr(result, MemOperand(ldr_location)); | 3450 ldr(result, MemOperand(ldr_location)); |
3454 } | 3451 } |
3455 | 3452 |
3456 // Get the offset into the constant pool. | 3453 // Get the offset into the constant pool. |
3457 const uint32_t kLdrOffsetMask = (1 << 12) - 1; | 3454 const uint32_t kLdrOffsetMask = (1 << 12) - 1; |
3458 and_(result, result, Operand(kLdrOffsetMask)); | 3455 and_(result, result, Operand(kLdrOffsetMask)); |
3459 | 3456 |
3460 bind(&load_result); | 3457 bind(&load_result); |
3461 // Get the address of the constant. | 3458 // Get the address of the constant. |
3462 if (FLAG_enable_embedded_constant_pool) { | 3459 if (FLAG_enable_ool_constant_pool) { |
3463 add(result, pp, Operand(result)); | 3460 add(result, pp, Operand(result)); |
3464 } else { | 3461 } else { |
3465 add(result, ldr_location, Operand(result)); | 3462 add(result, ldr_location, Operand(result)); |
3466 add(result, result, Operand(Instruction::kPCReadOffset)); | 3463 add(result, result, Operand(Instruction::kPCReadOffset)); |
3467 } | 3464 } |
3468 } | 3465 } |
3469 | 3466 |
3470 | 3467 |
3471 void MacroAssembler::CheckPageFlag( | 3468 void MacroAssembler::CheckPageFlag( |
3472 Register object, | 3469 Register object, |
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3912 } | 3909 } |
3913 } | 3910 } |
3914 if (mag.shift > 0) mov(result, Operand(result, ASR, mag.shift)); | 3911 if (mag.shift > 0) mov(result, Operand(result, ASR, mag.shift)); |
3915 add(result, result, Operand(dividend, LSR, 31)); | 3912 add(result, result, Operand(dividend, LSR, 31)); |
3916 } | 3913 } |
3917 | 3914 |
3918 } // namespace internal | 3915 } // namespace internal |
3919 } // namespace v8 | 3916 } // namespace v8 |
3920 | 3917 |
3921 #endif // V8_TARGET_ARCH_ARM | 3918 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |