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 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/base/division-by-constant.h" | 8 #include "src/base/division-by-constant.h" |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 936 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
947 } | 947 } |
948 | 948 |
949 | 949 |
950 void MacroAssembler::AssertNotSmi(Register object) { | 950 void MacroAssembler::AssertNotSmi(Register object) { |
951 if (emit_debug_code()) { | 951 if (emit_debug_code()) { |
952 test(object, Immediate(kSmiTagMask)); | 952 test(object, Immediate(kSmiTagMask)); |
953 Check(not_equal, kOperandIsASmi); | 953 Check(not_equal, kOperandIsASmi); |
954 } | 954 } |
955 } | 955 } |
956 | 956 |
957 | 957 void MacroAssembler::StubPrologue(StackFrame::Type type) { |
958 void MacroAssembler::StubPrologue() { | |
959 push(ebp); // Caller's frame pointer. | 958 push(ebp); // Caller's frame pointer. |
960 mov(ebp, esp); | 959 mov(ebp, esp); |
961 push(esi); // Callee's context. | 960 push(Immediate(Smi::FromInt(type))); |
962 push(Immediate(Smi::FromInt(StackFrame::STUB))); | |
963 } | 961 } |
964 | 962 |
965 | 963 |
966 void MacroAssembler::Prologue(bool code_pre_aging) { | 964 void MacroAssembler::Prologue(bool code_pre_aging) { |
967 PredictableCodeSizeScope predictible_code_size_scope(this, | 965 PredictableCodeSizeScope predictible_code_size_scope(this, |
968 kNoCodeAgeSequenceLength); | 966 kNoCodeAgeSequenceLength); |
969 if (code_pre_aging) { | 967 if (code_pre_aging) { |
970 // Pre-age the code. | 968 // Pre-age the code. |
971 call(isolate()->builtins()->MarkCodeAsExecutedOnce(), | 969 call(isolate()->builtins()->MarkCodeAsExecutedOnce(), |
972 RelocInfo::CODE_AGE_SEQUENCE); | 970 RelocInfo::CODE_AGE_SEQUENCE); |
(...skipping 17 matching lines...) Expand all Loading... |
990 void MacroAssembler::EnterFrame(StackFrame::Type type, | 988 void MacroAssembler::EnterFrame(StackFrame::Type type, |
991 bool load_constant_pool_pointer_reg) { | 989 bool load_constant_pool_pointer_reg) { |
992 // Out-of-line constant pool not implemented on x87. | 990 // Out-of-line constant pool not implemented on x87. |
993 UNREACHABLE(); | 991 UNREACHABLE(); |
994 } | 992 } |
995 | 993 |
996 | 994 |
997 void MacroAssembler::EnterFrame(StackFrame::Type type) { | 995 void MacroAssembler::EnterFrame(StackFrame::Type type) { |
998 push(ebp); | 996 push(ebp); |
999 mov(ebp, esp); | 997 mov(ebp, esp); |
1000 push(esi); | |
1001 push(Immediate(Smi::FromInt(type))); | 998 push(Immediate(Smi::FromInt(type))); |
1002 push(Immediate(CodeObject())); | 999 if (type == StackFrame::INTERNAL) { |
| 1000 push(Immediate(CodeObject())); |
| 1001 } |
1003 if (emit_debug_code()) { | 1002 if (emit_debug_code()) { |
1004 cmp(Operand(esp, 0), Immediate(isolate()->factory()->undefined_value())); | 1003 cmp(Operand(esp, 0), Immediate(isolate()->factory()->undefined_value())); |
1005 Check(not_equal, kCodeObjectNotProperlyPatched); | 1004 Check(not_equal, kCodeObjectNotProperlyPatched); |
1006 } | 1005 } |
1007 } | 1006 } |
1008 | 1007 |
1009 | 1008 |
1010 void MacroAssembler::LeaveFrame(StackFrame::Type type) { | 1009 void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
1011 if (emit_debug_code()) { | 1010 if (emit_debug_code()) { |
1012 cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), | 1011 cmp(Operand(ebp, CommonFrameConstants::kContextOrFrameTypeOffset), |
1013 Immediate(Smi::FromInt(type))); | 1012 Immediate(Smi::FromInt(type))); |
1014 Check(equal, kStackFrameTypesMustMatch); | 1013 Check(equal, kStackFrameTypesMustMatch); |
1015 } | 1014 } |
1016 leave(); | 1015 leave(); |
1017 } | 1016 } |
1018 | 1017 |
1019 | 1018 |
1020 void MacroAssembler::EnterExitFramePrologue() { | 1019 void MacroAssembler::EnterExitFramePrologue() { |
1021 // Set up the frame structure on the stack. | 1020 // Set up the frame structure on the stack. |
1022 DCHECK(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); | 1021 DCHECK_EQ(+2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); |
1023 DCHECK(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); | 1022 DCHECK_EQ(+1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); |
1024 DCHECK(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); | 1023 DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); |
1025 push(ebp); | 1024 push(ebp); |
1026 mov(ebp, esp); | 1025 mov(ebp, esp); |
1027 | 1026 |
1028 // Reserve room for entry stack pointer and push the code object. | 1027 // Reserve room for entry stack pointer and push the code object. |
1029 DCHECK(ExitFrameConstants::kSPOffset == -1 * kPointerSize); | 1028 push(Immediate(Smi::FromInt(StackFrame::EXIT))); |
| 1029 DCHECK_EQ(-2 * kPointerSize, ExitFrameConstants::kSPOffset); |
1030 push(Immediate(0)); // Saved entry sp, patched before call. | 1030 push(Immediate(0)); // Saved entry sp, patched before call. |
| 1031 DCHECK_EQ(-3 * kPointerSize, ExitFrameConstants::kCodeOffset); |
1031 push(Immediate(CodeObject())); // Accessed from ExitFrame::code_slot. | 1032 push(Immediate(CodeObject())); // Accessed from ExitFrame::code_slot. |
1032 | 1033 |
1033 // Save the frame pointer and the context in top. | 1034 // Save the frame pointer and the context in top. |
1034 ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate()); | 1035 ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate()); |
1035 ExternalReference context_address(Isolate::kContextAddress, isolate()); | 1036 ExternalReference context_address(Isolate::kContextAddress, isolate()); |
1036 ExternalReference c_function_address(Isolate::kCFunctionAddress, isolate()); | 1037 ExternalReference c_function_address(Isolate::kCFunctionAddress, isolate()); |
1037 mov(Operand::StaticVariable(c_entry_fp_address), ebp); | 1038 mov(Operand::StaticVariable(c_entry_fp_address), ebp); |
1038 mov(Operand::StaticVariable(context_address), esi); | 1039 mov(Operand::StaticVariable(context_address), esi); |
1039 mov(Operand::StaticVariable(c_function_address), ebx); | 1040 mov(Operand::StaticVariable(c_function_address), ebx); |
1040 } | 1041 } |
1041 | 1042 |
1042 | 1043 |
1043 void MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) { | 1044 void MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) { |
1044 // Optionally save FPU state. | 1045 // Optionally save FPU state. |
1045 if (save_doubles) { | 1046 if (save_doubles) { |
1046 // Store FPU state to m108byte. | 1047 // Store FPU state to m108byte. |
1047 int space = 108 + argc * kPointerSize; | 1048 int space = 108 + argc * kPointerSize; |
1048 sub(esp, Immediate(space)); | 1049 sub(esp, Immediate(space)); |
1049 const int offset = -2 * kPointerSize; // entry fp + code object. | 1050 const int offset = -ExitFrameConstants::kFixedFrameSizeFromFp; |
1050 fnsave(MemOperand(ebp, offset - 108)); | 1051 fnsave(MemOperand(ebp, offset - 108)); |
1051 } else { | 1052 } else { |
1052 sub(esp, Immediate(argc * kPointerSize)); | 1053 sub(esp, Immediate(argc * kPointerSize)); |
1053 } | 1054 } |
1054 | 1055 |
1055 // Get the required frame alignment for the OS. | 1056 // Get the required frame alignment for the OS. |
1056 const int kFrameAlignment = base::OS::ActivationFrameAlignment(); | 1057 const int kFrameAlignment = base::OS::ActivationFrameAlignment(); |
1057 if (kFrameAlignment > 0) { | 1058 if (kFrameAlignment > 0) { |
1058 DCHECK(base::bits::IsPowerOfTwo32(kFrameAlignment)); | 1059 DCHECK(base::bits::IsPowerOfTwo32(kFrameAlignment)); |
1059 and_(esp, -kFrameAlignment); | 1060 and_(esp, -kFrameAlignment); |
(...skipping 19 matching lines...) Expand all Loading... |
1079 | 1080 |
1080 void MacroAssembler::EnterApiExitFrame(int argc) { | 1081 void MacroAssembler::EnterApiExitFrame(int argc) { |
1081 EnterExitFramePrologue(); | 1082 EnterExitFramePrologue(); |
1082 EnterExitFrameEpilogue(argc, false); | 1083 EnterExitFrameEpilogue(argc, false); |
1083 } | 1084 } |
1084 | 1085 |
1085 | 1086 |
1086 void MacroAssembler::LeaveExitFrame(bool save_doubles, bool pop_arguments) { | 1087 void MacroAssembler::LeaveExitFrame(bool save_doubles, bool pop_arguments) { |
1087 // Optionally restore FPU state. | 1088 // Optionally restore FPU state. |
1088 if (save_doubles) { | 1089 if (save_doubles) { |
1089 const int offset = -2 * kPointerSize; | 1090 const int offset = -ExitFrameConstants::kFixedFrameSizeFromFp; |
1090 frstor(MemOperand(ebp, offset - 108)); | 1091 frstor(MemOperand(ebp, offset - 108)); |
1091 } | 1092 } |
1092 | 1093 |
1093 if (pop_arguments) { | 1094 if (pop_arguments) { |
1094 // Get the return address from the stack and restore the frame pointer. | 1095 // Get the return address from the stack and restore the frame pointer. |
1095 mov(ecx, Operand(ebp, 1 * kPointerSize)); | 1096 mov(ecx, Operand(ebp, 1 * kPointerSize)); |
1096 mov(ebp, Operand(ebp, 0 * kPointerSize)); | 1097 mov(ebp, Operand(ebp, 0 * kPointerSize)); |
1097 | 1098 |
1098 // Pop the arguments and the receiver from the caller stack. | 1099 // Pop the arguments and the receiver from the caller stack. |
1099 lea(esp, Operand(esi, 1 * kPointerSize)); | 1100 lea(esp, Operand(esi, 1 * kPointerSize)); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1159 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 1160 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
1160 Register scratch1, | 1161 Register scratch1, |
1161 Register scratch2, | 1162 Register scratch2, |
1162 Label* miss) { | 1163 Label* miss) { |
1163 Label same_contexts; | 1164 Label same_contexts; |
1164 | 1165 |
1165 DCHECK(!holder_reg.is(scratch1)); | 1166 DCHECK(!holder_reg.is(scratch1)); |
1166 DCHECK(!holder_reg.is(scratch2)); | 1167 DCHECK(!holder_reg.is(scratch2)); |
1167 DCHECK(!scratch1.is(scratch2)); | 1168 DCHECK(!scratch1.is(scratch2)); |
1168 | 1169 |
1169 // Load current lexical context from the stack frame. | 1170 // Load current lexical context from the active StandardFrame, which |
1170 mov(scratch1, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1171 // may require crawling past STUB frames. |
| 1172 Label load_context; |
| 1173 Label has_context; |
| 1174 mov(scratch2, ebp); |
| 1175 bind(&load_context); |
| 1176 mov(scratch1, |
| 1177 MemOperand(scratch2, CommonFrameConstants::kContextOrFrameTypeOffset)); |
| 1178 JumpIfNotSmi(scratch1, &has_context); |
| 1179 mov(scratch2, MemOperand(scratch2, CommonFrameConstants::kCallerFPOffset)); |
| 1180 jmp(&load_context); |
| 1181 bind(&has_context); |
1171 | 1182 |
1172 // When generating debug code, make sure the lexical context is set. | 1183 // When generating debug code, make sure the lexical context is set. |
1173 if (emit_debug_code()) { | 1184 if (emit_debug_code()) { |
1174 cmp(scratch1, Immediate(0)); | 1185 cmp(scratch1, Immediate(0)); |
1175 Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext); | 1186 Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext); |
1176 } | 1187 } |
1177 // Load the native context of the current context. | 1188 // Load the native context of the current context. |
1178 mov(scratch1, ContextOperand(scratch1, Context::NATIVE_CONTEXT_INDEX)); | 1189 mov(scratch1, ContextOperand(scratch1, Context::NATIVE_CONTEXT_INDEX)); |
1179 | 1190 |
1180 // Check the context is a native context. | 1191 // Check the context is a native context. |
(...skipping 1996 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3177 mov(eax, dividend); | 3188 mov(eax, dividend); |
3178 shr(eax, 31); | 3189 shr(eax, 31); |
3179 add(edx, eax); | 3190 add(edx, eax); |
3180 } | 3191 } |
3181 | 3192 |
3182 | 3193 |
3183 } // namespace internal | 3194 } // namespace internal |
3184 } // namespace v8 | 3195 } // namespace v8 |
3185 | 3196 |
3186 #endif // V8_TARGET_ARCH_X87 | 3197 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |