| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 | 97 |
| 98 // Get the function from the stack. | 98 // Get the function from the stack. |
| 99 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); | 99 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); |
| 100 | 100 |
| 101 // Setup the object header. | 101 // Setup the object header. |
| 102 __ LoadRoot(kScratchRegister, Heap::kContextMapRootIndex); | 102 __ LoadRoot(kScratchRegister, Heap::kContextMapRootIndex); |
| 103 __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister); | 103 __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister); |
| 104 __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length)); | 104 __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length)); |
| 105 | 105 |
| 106 // Setup the fixed slots. | 106 // Setup the fixed slots. |
| 107 __ xor_(rbx, rbx); // Set to NULL. | 107 __ Set(rbx, 0); // Set to NULL. |
| 108 __ movq(Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)), rcx); | 108 __ movq(Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)), rcx); |
| 109 __ movq(Operand(rax, Context::SlotOffset(Context::FCONTEXT_INDEX)), rax); | 109 __ movq(Operand(rax, Context::SlotOffset(Context::FCONTEXT_INDEX)), rax); |
| 110 __ movq(Operand(rax, Context::SlotOffset(Context::PREVIOUS_INDEX)), rbx); | 110 __ movq(Operand(rax, Context::SlotOffset(Context::PREVIOUS_INDEX)), rbx); |
| 111 __ movq(Operand(rax, Context::SlotOffset(Context::EXTENSION_INDEX)), rbx); | 111 __ movq(Operand(rax, Context::SlotOffset(Context::EXTENSION_INDEX)), rbx); |
| 112 | 112 |
| 113 // Copy the global object from the surrounding context. | 113 // Copy the global object from the surrounding context. |
| 114 __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 114 __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 115 __ movq(Operand(rax, Context::SlotOffset(Context::GLOBAL_INDEX)), rbx); | 115 __ movq(Operand(rax, Context::SlotOffset(Context::GLOBAL_INDEX)), rbx); |
| 116 | 116 |
| 117 // Initialize the rest of the slots to undefined. | 117 // Initialize the rest of the slots to undefined. |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 __ xorpd(xmm0, xmm0); | 243 __ xorpd(xmm0, xmm0); |
| 244 __ ucomisd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); | 244 __ ucomisd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); |
| 245 __ j(zero, &false_result); | 245 __ j(zero, &false_result); |
| 246 // Fall through to |true_result|. | 246 // Fall through to |true_result|. |
| 247 | 247 |
| 248 // Return 1/0 for true/false in rax. | 248 // Return 1/0 for true/false in rax. |
| 249 __ bind(&true_result); | 249 __ bind(&true_result); |
| 250 __ movq(rax, Immediate(1)); | 250 __ movq(rax, Immediate(1)); |
| 251 __ ret(1 * kPointerSize); | 251 __ ret(1 * kPointerSize); |
| 252 __ bind(&false_result); | 252 __ bind(&false_result); |
| 253 __ xor_(rax, rax); | 253 __ Set(rax, 0); |
| 254 __ ret(1 * kPointerSize); | 254 __ ret(1 * kPointerSize); |
| 255 } | 255 } |
| 256 | 256 |
| 257 | 257 |
| 258 const char* GenericBinaryOpStub::GetName() { | 258 const char* GenericBinaryOpStub::GetName() { |
| 259 if (name_ != NULL) return name_; | 259 if (name_ != NULL) return name_; |
| 260 const int kMaxNameLength = 100; | 260 const int kMaxNameLength = 100; |
| 261 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( | 261 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( |
| 262 kMaxNameLength); | 262 kMaxNameLength); |
| 263 if (name_ == NULL) return "OOM"; | 263 if (name_ == NULL) return "OOM"; |
| (...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 982 | 982 |
| 983 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) { | 983 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) { |
| 984 GenericBinaryOpStub stub(key, type_info); | 984 GenericBinaryOpStub stub(key, type_info); |
| 985 return stub.GetCode(); | 985 return stub.GetCode(); |
| 986 } | 986 } |
| 987 | 987 |
| 988 | 988 |
| 989 Handle<Code> GetTypeRecordingBinaryOpStub(int key, | 989 Handle<Code> GetTypeRecordingBinaryOpStub(int key, |
| 990 TRBinaryOpIC::TypeInfo type_info, | 990 TRBinaryOpIC::TypeInfo type_info, |
| 991 TRBinaryOpIC::TypeInfo result_type_info) { | 991 TRBinaryOpIC::TypeInfo result_type_info) { |
| 992 TypeRecordingBinaryOpStub stub(key, type_info, result_type_info); |
| 993 return stub.GetCode(); |
| 994 } |
| 995 |
| 996 |
| 997 void TypeRecordingBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { |
| 998 __ pop(rcx); // Save return address. |
| 999 __ push(rdx); |
| 1000 __ push(rax); |
| 1001 // Left and right arguments are now on top. |
| 1002 // Push this stub's key. Although the operation and the type info are |
| 1003 // encoded into the key, the encoding is opaque, so push them too. |
| 1004 __ Push(Smi::FromInt(MinorKey())); |
| 1005 __ Push(Smi::FromInt(op_)); |
| 1006 __ Push(Smi::FromInt(operands_type_)); |
| 1007 |
| 1008 __ push(rcx); // Push return address. |
| 1009 |
| 1010 // Patch the caller to an appropriate specialized stub and return the |
| 1011 // operation result to the caller of the stub. |
| 1012 __ TailCallExternalReference( |
| 1013 ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch)), |
| 1014 5, |
| 1015 1); |
| 1016 } |
| 1017 |
| 1018 |
| 1019 // Prepare for a type transition runtime call when the args are already on |
| 1020 // the stack, under the return address. |
| 1021 void TypeRecordingBinaryOpStub::GenerateTypeTransitionWithSavedArgs( |
| 1022 MacroAssembler* masm) { |
| 1023 __ pop(rcx); // Save return address. |
| 1024 // Left and right arguments are already on top of the stack. |
| 1025 // Push this stub's key. Although the operation and the type info are |
| 1026 // encoded into the key, the encoding is opaque, so push them too. |
| 1027 __ Push(Smi::FromInt(MinorKey())); |
| 1028 __ Push(Smi::FromInt(op_)); |
| 1029 __ Push(Smi::FromInt(operands_type_)); |
| 1030 |
| 1031 __ push(rcx); // Push return address. |
| 1032 |
| 1033 // Patch the caller to an appropriate specialized stub and return the |
| 1034 // operation result to the caller of the stub. |
| 1035 __ TailCallExternalReference( |
| 1036 ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch)), |
| 1037 5, |
| 1038 1); |
| 1039 } |
| 1040 |
| 1041 |
| 1042 void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) { |
| 1043 switch (operands_type_) { |
| 1044 case TRBinaryOpIC::UNINITIALIZED: |
| 1045 GenerateTypeTransition(masm); |
| 1046 break; |
| 1047 case TRBinaryOpIC::SMI: |
| 1048 GenerateSmiStub(masm); |
| 1049 break; |
| 1050 case TRBinaryOpIC::INT32: |
| 1051 GenerateInt32Stub(masm); |
| 1052 break; |
| 1053 case TRBinaryOpIC::HEAP_NUMBER: |
| 1054 GenerateHeapNumberStub(masm); |
| 1055 break; |
| 1056 case TRBinaryOpIC::STRING: |
| 1057 GenerateStringStub(masm); |
| 1058 break; |
| 1059 case TRBinaryOpIC::GENERIC: |
| 1060 GenerateGeneric(masm); |
| 1061 break; |
| 1062 default: |
| 1063 UNREACHABLE(); |
| 1064 } |
| 1065 } |
| 1066 |
| 1067 |
| 1068 const char* TypeRecordingBinaryOpStub::GetName() { |
| 1069 if (name_ != NULL) return name_; |
| 1070 const int kMaxNameLength = 100; |
| 1071 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( |
| 1072 kMaxNameLength); |
| 1073 if (name_ == NULL) return "OOM"; |
| 1074 const char* op_name = Token::Name(op_); |
| 1075 const char* overwrite_name; |
| 1076 switch (mode_) { |
| 1077 case NO_OVERWRITE: overwrite_name = "Alloc"; break; |
| 1078 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; |
| 1079 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; |
| 1080 default: overwrite_name = "UnknownOverwrite"; break; |
| 1081 } |
| 1082 |
| 1083 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), |
| 1084 "TypeRecordingBinaryOpStub_%s_%s_%s", |
| 1085 op_name, |
| 1086 overwrite_name, |
| 1087 TRBinaryOpIC::GetName(operands_type_)); |
| 1088 return name_; |
| 1089 } |
| 1090 |
| 1091 |
| 1092 void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, |
| 1093 Label* slow, |
| 1094 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) { |
| 992 UNIMPLEMENTED(); | 1095 UNIMPLEMENTED(); |
| 993 return Handle<Code>::null(); | 1096 } |
| 1097 |
| 1098 |
| 1099 void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { |
| 1100 Label call_runtime; |
| 1101 |
| 1102 switch (op_) { |
| 1103 case Token::ADD: |
| 1104 case Token::SUB: |
| 1105 case Token::MUL: |
| 1106 case Token::DIV: |
| 1107 break; |
| 1108 case Token::MOD: |
| 1109 case Token::BIT_OR: |
| 1110 case Token::BIT_AND: |
| 1111 case Token::BIT_XOR: |
| 1112 case Token::SAR: |
| 1113 case Token::SHL: |
| 1114 case Token::SHR: |
| 1115 GenerateRegisterArgsPush(masm); |
| 1116 break; |
| 1117 default: |
| 1118 UNREACHABLE(); |
| 1119 } |
| 1120 |
| 1121 if (result_type_ == TRBinaryOpIC::UNINITIALIZED || |
| 1122 result_type_ == TRBinaryOpIC::SMI) { |
| 1123 GenerateSmiCode(masm, &call_runtime, NO_HEAPNUMBER_RESULTS); |
| 1124 } else { |
| 1125 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); |
| 1126 } |
| 1127 __ bind(&call_runtime); |
| 1128 switch (op_) { |
| 1129 case Token::ADD: |
| 1130 case Token::SUB: |
| 1131 case Token::MUL: |
| 1132 case Token::DIV: |
| 1133 GenerateTypeTransition(masm); |
| 1134 break; |
| 1135 case Token::MOD: |
| 1136 case Token::BIT_OR: |
| 1137 case Token::BIT_AND: |
| 1138 case Token::BIT_XOR: |
| 1139 case Token::SAR: |
| 1140 case Token::SHL: |
| 1141 case Token::SHR: |
| 1142 GenerateTypeTransitionWithSavedArgs(masm); |
| 1143 break; |
| 1144 default: |
| 1145 UNREACHABLE(); |
| 1146 } |
| 1147 } |
| 1148 |
| 1149 |
| 1150 void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) { |
| 1151 UNIMPLEMENTED(); |
| 1152 } |
| 1153 |
| 1154 |
| 1155 void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { |
| 1156 UNIMPLEMENTED(); |
| 1157 } |
| 1158 |
| 1159 |
| 1160 void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { |
| 1161 UNIMPLEMENTED(); |
| 1162 } |
| 1163 |
| 1164 |
| 1165 void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) { |
| 1166 UNIMPLEMENTED(); |
| 1167 } |
| 1168 |
| 1169 |
| 1170 void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation( |
| 1171 MacroAssembler* masm, |
| 1172 Label* alloc_failure) { |
| 1173 UNIMPLEMENTED(); |
| 1174 } |
| 1175 |
| 1176 |
| 1177 void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) { |
| 1178 __ pop(rcx); |
| 1179 __ push(rdx); |
| 1180 __ push(rax); |
| 1181 __ push(rcx); |
| 994 } | 1182 } |
| 995 | 1183 |
| 996 | 1184 |
| 997 void TranscendentalCacheStub::Generate(MacroAssembler* masm) { | 1185 void TranscendentalCacheStub::Generate(MacroAssembler* masm) { |
| 998 // Input on stack: | 1186 // Input on stack: |
| 999 // rsp[8]: argument (should be number). | 1187 // rsp[8]: argument (should be number). |
| 1000 // rsp[0]: return address. | 1188 // rsp[0]: return address. |
| 1001 Label runtime_call; | 1189 Label runtime_call; |
| 1002 Label runtime_call_clear_stack; | 1190 Label runtime_call_clear_stack; |
| 1003 Label input_not_smi; | 1191 Label input_not_smi; |
| (...skipping 1565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2569 __ movq(kScratchRegister, handler_address); | 2757 __ movq(kScratchRegister, handler_address); |
| 2570 __ movq(rsp, Operand(kScratchRegister, 0)); | 2758 __ movq(rsp, Operand(kScratchRegister, 0)); |
| 2571 // get next in chain | 2759 // get next in chain |
| 2572 __ pop(rcx); | 2760 __ pop(rcx); |
| 2573 __ movq(Operand(kScratchRegister, 0), rcx); | 2761 __ movq(Operand(kScratchRegister, 0), rcx); |
| 2574 __ pop(rbp); // pop frame pointer | 2762 __ pop(rbp); // pop frame pointer |
| 2575 __ pop(rdx); // remove state | 2763 __ pop(rdx); // remove state |
| 2576 | 2764 |
| 2577 // Before returning we restore the context from the frame pointer if not NULL. | 2765 // Before returning we restore the context from the frame pointer if not NULL. |
| 2578 // The frame pointer is NULL in the exception handler of a JS entry frame. | 2766 // The frame pointer is NULL in the exception handler of a JS entry frame. |
| 2579 __ xor_(rsi, rsi); // tentatively set context pointer to NULL | 2767 __ Set(rsi, 0); // Tentatively set context pointer to NULL |
| 2580 NearLabel skip; | 2768 NearLabel skip; |
| 2581 __ cmpq(rbp, Immediate(0)); | 2769 __ cmpq(rbp, Immediate(0)); |
| 2582 __ j(equal, &skip); | 2770 __ j(equal, &skip); |
| 2583 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2771 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2584 __ bind(&skip); | 2772 __ bind(&skip); |
| 2585 __ ret(0); | 2773 __ ret(0); |
| 2586 } | 2774 } |
| 2587 | 2775 |
| 2588 | 2776 |
| 2589 void CEntryStub::GenerateCore(MacroAssembler* masm, | 2777 void CEntryStub::GenerateCore(MacroAssembler* masm, |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2758 __ movq(rax, Immediate(false)); | 2946 __ movq(rax, Immediate(false)); |
| 2759 __ store_rax(external_caught); | 2947 __ store_rax(external_caught); |
| 2760 | 2948 |
| 2761 // Set pending exception and rax to out of memory exception. | 2949 // Set pending exception and rax to out of memory exception. |
| 2762 ExternalReference pending_exception(Isolate::k_pending_exception_address); | 2950 ExternalReference pending_exception(Isolate::k_pending_exception_address); |
| 2763 __ movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE); | 2951 __ movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE); |
| 2764 __ store_rax(pending_exception); | 2952 __ store_rax(pending_exception); |
| 2765 } | 2953 } |
| 2766 | 2954 |
| 2767 // Clear the context pointer. | 2955 // Clear the context pointer. |
| 2768 __ xor_(rsi, rsi); | 2956 __ Set(rsi, 0); |
| 2769 | 2957 |
| 2770 // Restore registers from handler. | 2958 // Restore registers from handler. |
| 2771 STATIC_ASSERT(StackHandlerConstants::kNextOffset + kPointerSize == | 2959 STATIC_ASSERT(StackHandlerConstants::kNextOffset + kPointerSize == |
| 2772 StackHandlerConstants::kFPOffset); | 2960 StackHandlerConstants::kFPOffset); |
| 2773 __ pop(rbp); // FP | 2961 __ pop(rbp); // FP |
| 2774 STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize == | 2962 STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize == |
| 2775 StackHandlerConstants::kStateOffset); | 2963 StackHandlerConstants::kStateOffset); |
| 2776 __ pop(rdx); // State | 2964 __ pop(rdx); // State |
| 2777 | 2965 |
| 2778 STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize == | 2966 STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize == |
| (...skipping 1332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4111 | 4299 |
| 4112 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { | 4300 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { |
| 4113 UNIMPLEMENTED(); | 4301 UNIMPLEMENTED(); |
| 4114 } | 4302 } |
| 4115 | 4303 |
| 4116 #undef __ | 4304 #undef __ |
| 4117 | 4305 |
| 4118 } } // namespace v8::internal | 4306 } } // namespace v8::internal |
| 4119 | 4307 |
| 4120 #endif // V8_TARGET_ARCH_X64 | 4308 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |