| 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 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 Token::Value op_; | 255 Token::Value op_; |
| 256 Register dst_; | 256 Register dst_; |
| 257 Smi* value_; | 257 Smi* value_; |
| 258 Register src_; | 258 Register src_; |
| 259 OverwriteMode overwrite_mode_; | 259 OverwriteMode overwrite_mode_; |
| 260 }; | 260 }; |
| 261 | 261 |
| 262 | 262 |
| 263 class FloatingPointHelper : public AllStatic { | 263 class FloatingPointHelper : public AllStatic { |
| 264 public: | 264 public: |
| 265 // Code pattern for loading a floating point value. Input value must | 265 // Load the operands from rdx and rax into xmm0 and xmm1, as doubles. |
| 266 // be either a smi or a heap number object (fp value). Requirements: | 266 // If the operands are not both numbers, jump to not_numbers. |
| 267 // operand on TOS+1. Returns operand as floating point number on FPU | 267 // Leaves rdx and rax unchanged. SmiOperands assumes both are smis. |
| 268 // stack. | 268 // NumberOperands assumes both are smis or heap numbers. |
| 269 static void LoadFloatOperand(MacroAssembler* masm, Register scratch); | 269 static void LoadSSE2SmiOperands(MacroAssembler* masm); |
| 270 | 270 static void LoadSSE2NumberOperands(MacroAssembler* masm); |
| 271 // Code pattern for loading a floating point value. Input value must | 271 static void LoadSSE2UnknownOperands(MacroAssembler* masm, |
| 272 // be either a smi or a heap number object (fp value). Requirements: | 272 Label* not_numbers); |
| 273 // operand in src register. Returns operand as floating point number | |
| 274 // in XMM register. May destroy src register. | |
| 275 static void LoadFloatOperand(MacroAssembler* masm, | |
| 276 Register src, | |
| 277 XMMRegister dst); | |
| 278 | |
| 279 // Code pattern for loading a possible number into a XMM register. | |
| 280 // If the contents of src is not a number, control branches to | |
| 281 // the Label not_number. If contents of src is a smi or a heap number | |
| 282 // object (fp value), it is loaded into the XMM register as a double. | |
| 283 // The register src is not changed, and src may not be kScratchRegister. | |
| 284 static void LoadFloatOperand(MacroAssembler* masm, | |
| 285 Register src, | |
| 286 XMMRegister dst, | |
| 287 Label *not_number); | |
| 288 | |
| 289 // Code pattern for loading floating point values. Input values must | |
| 290 // be either smi or heap number objects (fp values). Requirements: | |
| 291 // operand_1 in rdx, operand_2 in rax; Returns operands as | |
| 292 // floating point numbers in XMM registers. | |
| 293 static void LoadFloatOperands(MacroAssembler* masm, | |
| 294 XMMRegister dst1, | |
| 295 XMMRegister dst2); | |
| 296 | |
| 297 // Similar to LoadFloatOperands, assumes that the operands are smis. | |
| 298 static void LoadFloatOperandsFromSmis(MacroAssembler* masm, | |
| 299 XMMRegister dst1, | |
| 300 XMMRegister dst2); | |
| 301 | |
| 302 // Code pattern for loading floating point values onto the fp stack. | |
| 303 // Input values must be either smi or heap number objects (fp values). | |
| 304 // Requirements: | |
| 305 // Register version: operands in registers lhs and rhs. | |
| 306 // Stack version: operands on TOS+1 and TOS+2. | |
| 307 // Returns operands as floating point numbers on fp stack. | |
| 308 static void LoadFloatOperands(MacroAssembler* masm, | |
| 309 Register lhs, | |
| 310 Register rhs); | |
| 311 | |
| 312 // Test if operands are smi or number objects (fp). Requirements: | |
| 313 // operand_1 in rax, operand_2 in rdx; falls through on float or smi | |
| 314 // operands, jumps to the non_float label otherwise. | |
| 315 static void CheckNumberOperands(MacroAssembler* masm, | |
| 316 Label* non_float); | |
| 317 // As CheckNumberOperands above, but expects the HeapNumber map in | |
| 318 // a register. | |
| 319 static void CheckNumberOperands(MacroAssembler* masm, | |
| 320 Label* non_float, | |
| 321 Register heap_number_map); | |
| 322 | 273 |
| 323 // Takes the operands in rdx and rax and loads them as integers in rax | 274 // Takes the operands in rdx and rax and loads them as integers in rax |
| 324 // and rcx. | 275 // and rcx. |
| 325 static void LoadAsIntegers(MacroAssembler* masm, | 276 static void LoadAsIntegers(MacroAssembler* masm, |
| 326 Label* operand_conversion_failure, | 277 Label* operand_conversion_failure); |
| 327 Register heap_number_map); | |
| 328 }; | 278 }; |
| 329 | 279 |
| 330 | 280 |
| 331 // ----------------------------------------------------------------------------- | 281 // ----------------------------------------------------------------------------- |
| 332 // CodeGenerator implementation. | 282 // CodeGenerator implementation. |
| 333 | 283 |
| 334 CodeGenerator::CodeGenerator(MacroAssembler* masm) | 284 CodeGenerator::CodeGenerator(MacroAssembler* masm) |
| 335 : deferred_(8), | 285 : deferred_(8), |
| 336 masm_(masm), | 286 masm_(masm), |
| 337 info_(NULL), | 287 info_(NULL), |
| (...skipping 8767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9105 // Push arguments below the return address to prepare jump to builtin. | 9055 // Push arguments below the return address to prepare jump to builtin. |
| 9106 __ pop(rcx); | 9056 __ pop(rcx); |
| 9107 __ push(rax); | 9057 __ push(rax); |
| 9108 __ push(rdx); | 9058 __ push(rdx); |
| 9109 __ push(rcx); | 9059 __ push(rcx); |
| 9110 | 9060 |
| 9111 // Generate the number comparison code. | 9061 // Generate the number comparison code. |
| 9112 if (include_number_compare_) { | 9062 if (include_number_compare_) { |
| 9113 Label non_number_comparison; | 9063 Label non_number_comparison; |
| 9114 Label unordered; | 9064 Label unordered; |
| 9115 FloatingPointHelper::LoadFloatOperand(masm, rdx, xmm0, | 9065 FloatingPointHelper::LoadSSE2UnknownOperands(masm, &non_number_comparison); |
| 9116 &non_number_comparison); | |
| 9117 FloatingPointHelper::LoadFloatOperand(masm, rax, xmm1, | |
| 9118 &non_number_comparison); | |
| 9119 | |
| 9120 __ ucomisd(xmm0, xmm1); | 9066 __ ucomisd(xmm0, xmm1); |
| 9121 | 9067 |
| 9122 // Don't base result on EFLAGS when a NaN is involved. | 9068 // Don't base result on EFLAGS when a NaN is involved. |
| 9123 __ j(parity_even, &unordered); | 9069 __ j(parity_even, &unordered); |
| 9124 // Return a result of -1, 0, or 1, based on EFLAGS. | 9070 // Return a result of -1, 0, or 1, based on EFLAGS. |
| 9125 __ movq(rax, Immediate(0)); // equal | 9071 __ movq(rax, Immediate(0)); // equal |
| 9126 __ movq(rcx, Immediate(1)); | 9072 __ movq(rcx, Immediate(1)); |
| 9127 __ cmovq(above, rax, rcx); | 9073 __ cmovq(above, rax, rcx); |
| 9128 __ movq(rcx, Immediate(-1)); | 9074 __ movq(rcx, Immediate(-1)); |
| 9129 __ cmovq(below, rax, rcx); | 9075 __ cmovq(below, rax, rcx); |
| (...skipping 836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9966 // temporarily store that in a register. | 9912 // temporarily store that in a register. |
| 9967 __ pop(rax); | 9913 __ pop(rax); |
| 9968 __ Push(Smi::FromInt(0)); | 9914 __ Push(Smi::FromInt(0)); |
| 9969 __ push(rax); | 9915 __ push(rax); |
| 9970 | 9916 |
| 9971 // Do tail-call to runtime routine. | 9917 // Do tail-call to runtime routine. |
| 9972 __ TailCallRuntime(Runtime::kStackGuard, 1, 1); | 9918 __ TailCallRuntime(Runtime::kStackGuard, 1, 1); |
| 9973 } | 9919 } |
| 9974 | 9920 |
| 9975 | 9921 |
| 9976 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, | 9922 void FloatingPointHelper::LoadSSE2SmiOperands(MacroAssembler* masm) { |
| 9977 Register number) { | 9923 __ SmiToInteger32(kScratchRegister, rdx); |
| 9978 Label load_smi, done; | 9924 __ cvtlsi2sd(xmm0, kScratchRegister); |
| 9925 __ SmiToInteger32(kScratchRegister, rax); |
| 9926 __ cvtlsi2sd(xmm1, kScratchRegister); |
| 9927 } |
| 9979 | 9928 |
| 9980 __ JumpIfSmi(number, &load_smi); | 9929 |
| 9981 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset)); | 9930 void FloatingPointHelper::LoadSSE2NumberOperands(MacroAssembler* masm) { |
| 9931 Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, done; |
| 9932 // Load operand in rdx into xmm0. |
| 9933 __ JumpIfSmi(rdx, &load_smi_rdx); |
| 9934 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); |
| 9935 // Load operand in rax into xmm1. |
| 9936 __ JumpIfSmi(rax, &load_smi_rax); |
| 9937 __ bind(&load_nonsmi_rax); |
| 9938 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); |
| 9982 __ jmp(&done); | 9939 __ jmp(&done); |
| 9983 | 9940 |
| 9984 __ bind(&load_smi); | 9941 __ bind(&load_smi_rdx); |
| 9985 __ SmiToInteger32(number, number); | 9942 __ SmiToInteger32(kScratchRegister, rdx); |
| 9986 __ push(number); | 9943 __ cvtlsi2sd(xmm0, kScratchRegister); |
| 9987 __ fild_s(Operand(rsp, 0)); | 9944 __ JumpIfNotSmi(rax, &load_nonsmi_rax); |
| 9988 __ pop(number); | 9945 |
| 9946 __ bind(&load_smi_rax); |
| 9947 __ SmiToInteger32(kScratchRegister, rax); |
| 9948 __ cvtlsi2sd(xmm1, kScratchRegister); |
| 9989 | 9949 |
| 9990 __ bind(&done); | 9950 __ bind(&done); |
| 9991 } | 9951 } |
| 9992 | 9952 |
| 9993 | 9953 |
| 9994 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, | 9954 void FloatingPointHelper::LoadSSE2UnknownOperands(MacroAssembler* masm, |
| 9995 Register src, | 9955 Label* not_numbers) { |
| 9996 XMMRegister dst) { | 9956 Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, load_float_rax, done; |
| 9997 ASSERT(!src.is(kScratchRegister)); | 9957 // Load operand in rdx into xmm0, or branch to not_numbers. |
| 9998 Label load_smi, done; | 9958 __ LoadRoot(rcx, Heap::kHeapNumberMapRootIndex); |
| 9959 __ JumpIfSmi(rdx, &load_smi_rdx); |
| 9960 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), rcx); |
| 9961 __ j(not_equal, not_numbers); // Argument in rdx is not a number. |
| 9962 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); |
| 9963 // Load operand in rax into xmm1, or branch to not_numbers. |
| 9964 __ JumpIfSmi(rax, &load_smi_rax); |
| 9999 | 9965 |
| 10000 __ JumpIfSmi(src, &load_smi); | 9966 __ bind(&load_nonsmi_rax); |
| 10001 __ movsd(dst, FieldOperand(src, HeapNumber::kValueOffset)); | 9967 __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), rcx); |
| 9968 __ j(not_equal, not_numbers); |
| 9969 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); |
| 10002 __ jmp(&done); | 9970 __ jmp(&done); |
| 10003 | 9971 |
| 10004 __ bind(&load_smi); | 9972 __ bind(&load_smi_rdx); |
| 10005 __ SmiToInteger32(kScratchRegister, src); | 9973 __ SmiToInteger32(kScratchRegister, rdx); |
| 10006 __ cvtlsi2sd(dst, kScratchRegister); | 9974 __ cvtlsi2sd(xmm0, kScratchRegister); |
| 9975 __ JumpIfNotSmi(rax, &load_nonsmi_rax); |
| 10007 | 9976 |
| 9977 __ bind(&load_smi_rax); |
| 9978 __ SmiToInteger32(kScratchRegister, rax); |
| 9979 __ cvtlsi2sd(xmm1, kScratchRegister); |
| 10008 __ bind(&done); | 9980 __ bind(&done); |
| 10009 } | 9981 } |
| 10010 | 9982 |
| 10011 | 9983 |
| 10012 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, | |
| 10013 Register src, | |
| 10014 XMMRegister dst, | |
| 10015 Label* not_number) { | |
| 10016 Label load_smi, done; | |
| 10017 ASSERT(!src.is(kScratchRegister)); | |
| 10018 __ JumpIfSmi(src, &load_smi); | |
| 10019 __ LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex); | |
| 10020 __ cmpq(FieldOperand(src, HeapObject::kMapOffset), kScratchRegister); | |
| 10021 __ j(not_equal, not_number); | |
| 10022 __ movsd(dst, FieldOperand(src, HeapNumber::kValueOffset)); | |
| 10023 __ jmp(&done); | |
| 10024 | |
| 10025 __ bind(&load_smi); | |
| 10026 __ SmiToInteger32(kScratchRegister, src); | |
| 10027 __ cvtlsi2sd(dst, kScratchRegister); | |
| 10028 | |
| 10029 __ bind(&done); | |
| 10030 } | |
| 10031 | |
| 10032 | |
| 10033 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, | |
| 10034 XMMRegister dst1, | |
| 10035 XMMRegister dst2) { | |
| 10036 LoadFloatOperand(masm, rdx, dst1); | |
| 10037 LoadFloatOperand(masm, rax, dst2); | |
| 10038 } | |
| 10039 | |
| 10040 | |
| 10041 void FloatingPointHelper::LoadFloatOperandsFromSmis(MacroAssembler* masm, | |
| 10042 XMMRegister dst1, | |
| 10043 XMMRegister dst2) { | |
| 10044 __ SmiToInteger32(kScratchRegister, rdx); | |
| 10045 __ cvtlsi2sd(dst1, kScratchRegister); | |
| 10046 __ SmiToInteger32(kScratchRegister, rax); | |
| 10047 __ cvtlsi2sd(dst2, kScratchRegister); | |
| 10048 } | |
| 10049 | |
| 10050 | |
| 10051 // Input: rdx, rax are the left and right objects of a bit op. | 9984 // Input: rdx, rax are the left and right objects of a bit op. |
| 10052 // Output: rax, rcx are left and right integers for a bit op. | 9985 // Output: rax, rcx are left and right integers for a bit op. |
| 10053 void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm, | 9986 void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm, |
| 10054 Label* conversion_failure, | 9987 Label* conversion_failure) { |
| 10055 Register heap_number_map) { | |
| 10056 // Check float operands. | 9988 // Check float operands. |
| 10057 Label arg1_is_object, check_undefined_arg1; | 9989 Label arg1_is_object, check_undefined_arg1; |
| 10058 Label arg2_is_object, check_undefined_arg2; | 9990 Label arg2_is_object, check_undefined_arg2; |
| 10059 Label load_arg2, done; | 9991 Label load_arg2, done; |
| 10060 | 9992 |
| 10061 __ JumpIfNotSmi(rdx, &arg1_is_object); | 9993 __ JumpIfNotSmi(rdx, &arg1_is_object); |
| 10062 __ SmiToInteger32(rdx, rdx); | 9994 __ SmiToInteger32(rdx, rdx); |
| 10063 __ jmp(&load_arg2); | 9995 __ jmp(&load_arg2); |
| 10064 | 9996 |
| 10065 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). | 9997 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
| 10066 __ bind(&check_undefined_arg1); | 9998 __ bind(&check_undefined_arg1); |
| 10067 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); | 9999 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); |
| 10068 __ j(not_equal, conversion_failure); | 10000 __ j(not_equal, conversion_failure); |
| 10069 __ movl(rdx, Immediate(0)); | 10001 __ movl(rdx, Immediate(0)); |
| 10070 __ jmp(&load_arg2); | 10002 __ jmp(&load_arg2); |
| 10071 | 10003 |
| 10072 __ bind(&arg1_is_object); | 10004 __ bind(&arg1_is_object); |
| 10073 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), heap_number_map); | 10005 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); |
| 10006 __ CompareRoot(rbx, Heap::kHeapNumberMapRootIndex); |
| 10074 __ j(not_equal, &check_undefined_arg1); | 10007 __ j(not_equal, &check_undefined_arg1); |
| 10075 // Get the untagged integer version of the edx heap number in rcx. | 10008 // Get the untagged integer version of the edx heap number in rcx. |
| 10076 IntegerConvert(masm, rdx, rdx); | 10009 IntegerConvert(masm, rdx, rdx); |
| 10077 | 10010 |
| 10078 // Here rdx has the untagged integer, rax has a Smi or a heap number. | 10011 // Here rdx has the untagged integer, rax has a Smi or a heap number. |
| 10079 __ bind(&load_arg2); | 10012 __ bind(&load_arg2); |
| 10080 // Test if arg2 is a Smi. | 10013 // Test if arg2 is a Smi. |
| 10081 __ JumpIfNotSmi(rax, &arg2_is_object); | 10014 __ JumpIfNotSmi(rax, &arg2_is_object); |
| 10082 __ SmiToInteger32(rax, rax); | 10015 __ SmiToInteger32(rax, rax); |
| 10083 __ movl(rcx, rax); | 10016 __ movl(rcx, rax); |
| 10084 __ jmp(&done); | 10017 __ jmp(&done); |
| 10085 | 10018 |
| 10086 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). | 10019 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
| 10087 __ bind(&check_undefined_arg2); | 10020 __ bind(&check_undefined_arg2); |
| 10088 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 10021 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
| 10089 __ j(not_equal, conversion_failure); | 10022 __ j(not_equal, conversion_failure); |
| 10090 __ movl(rcx, Immediate(0)); | 10023 __ movl(rcx, Immediate(0)); |
| 10091 __ jmp(&done); | 10024 __ jmp(&done); |
| 10092 | 10025 |
| 10093 __ bind(&arg2_is_object); | 10026 __ bind(&arg2_is_object); |
| 10094 __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), heap_number_map); | 10027 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
| 10028 __ CompareRoot(rbx, Heap::kHeapNumberMapRootIndex); |
| 10095 __ j(not_equal, &check_undefined_arg2); | 10029 __ j(not_equal, &check_undefined_arg2); |
| 10096 // Get the untagged integer version of the eax heap number in ecx. | 10030 // Get the untagged integer version of the eax heap number in ecx. |
| 10097 IntegerConvert(masm, rcx, rax); | 10031 IntegerConvert(masm, rcx, rax); |
| 10098 __ bind(&done); | 10032 __ bind(&done); |
| 10099 __ movl(rax, rdx); | 10033 __ movl(rax, rdx); |
| 10100 } | 10034 } |
| 10101 | 10035 |
| 10102 | 10036 |
| 10103 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, | |
| 10104 Register lhs, | |
| 10105 Register rhs) { | |
| 10106 Label load_smi_lhs, load_smi_rhs, done_load_lhs, done; | |
| 10107 __ JumpIfSmi(lhs, &load_smi_lhs); | |
| 10108 __ fld_d(FieldOperand(lhs, HeapNumber::kValueOffset)); | |
| 10109 __ bind(&done_load_lhs); | |
| 10110 | |
| 10111 __ JumpIfSmi(rhs, &load_smi_rhs); | |
| 10112 __ fld_d(FieldOperand(rhs, HeapNumber::kValueOffset)); | |
| 10113 __ jmp(&done); | |
| 10114 | |
| 10115 __ bind(&load_smi_lhs); | |
| 10116 __ SmiToInteger64(kScratchRegister, lhs); | |
| 10117 __ push(kScratchRegister); | |
| 10118 __ fild_d(Operand(rsp, 0)); | |
| 10119 __ pop(kScratchRegister); | |
| 10120 __ jmp(&done_load_lhs); | |
| 10121 | |
| 10122 __ bind(&load_smi_rhs); | |
| 10123 __ SmiToInteger64(kScratchRegister, rhs); | |
| 10124 __ push(kScratchRegister); | |
| 10125 __ fild_d(Operand(rsp, 0)); | |
| 10126 __ pop(kScratchRegister); | |
| 10127 | |
| 10128 __ bind(&done); | |
| 10129 } | |
| 10130 | |
| 10131 | |
| 10132 void FloatingPointHelper::CheckNumberOperands(MacroAssembler* masm, | |
| 10133 Label* non_float) { | |
| 10134 Label test_other, done; | |
| 10135 // Test if both operands are numbers (heap_numbers or smis). | |
| 10136 // If not, jump to label non_float. | |
| 10137 __ JumpIfSmi(rdx, &test_other); // argument in rdx is OK | |
| 10138 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), Factory::heap_number_map()); | |
| 10139 __ j(not_equal, non_float); // The argument in rdx is not a number. | |
| 10140 | |
| 10141 __ bind(&test_other); | |
| 10142 __ JumpIfSmi(rax, &done); // argument in rax is OK | |
| 10143 __ Cmp(FieldOperand(rax, HeapObject::kMapOffset), Factory::heap_number_map()); | |
| 10144 __ j(not_equal, non_float); // The argument in rax is not a number. | |
| 10145 | |
| 10146 // Fall-through: Both operands are numbers. | |
| 10147 __ bind(&done); | |
| 10148 } | |
| 10149 | |
| 10150 | |
| 10151 void FloatingPointHelper::CheckNumberOperands(MacroAssembler* masm, | |
| 10152 Label* non_float, | |
| 10153 Register heap_number_map) { | |
| 10154 Label test_other, done; | |
| 10155 // Test if both operands are numbers (heap_numbers or smis). | |
| 10156 // If not, jump to label non_float. | |
| 10157 __ JumpIfSmi(rdx, &test_other); // argument in rdx is OK | |
| 10158 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), heap_number_map); | |
| 10159 __ j(not_equal, non_float); // The argument in rdx is not a number. | |
| 10160 | |
| 10161 __ bind(&test_other); | |
| 10162 __ JumpIfSmi(rax, &done); // argument in rax is OK | |
| 10163 __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), heap_number_map); | |
| 10164 __ j(not_equal, non_float); // The argument in rax is not a number. | |
| 10165 | |
| 10166 // Fall-through: Both operands are numbers. | |
| 10167 __ bind(&done); | |
| 10168 } | |
| 10169 | |
| 10170 | |
| 10171 const char* GenericBinaryOpStub::GetName() { | 10037 const char* GenericBinaryOpStub::GetName() { |
| 10172 if (name_ != NULL) return name_; | 10038 if (name_ != NULL) return name_; |
| 10173 const int len = 100; | 10039 const int len = 100; |
| 10174 name_ = Bootstrapper::AllocateAutoDeletedArray(len); | 10040 name_ = Bootstrapper::AllocateAutoDeletedArray(len); |
| 10175 if (name_ == NULL) return "OOM"; | 10041 if (name_ == NULL) return "OOM"; |
| 10176 const char* op_name = Token::Name(op_); | 10042 const char* op_name = Token::Name(op_); |
| 10177 const char* overwrite_name; | 10043 const char* overwrite_name; |
| 10178 switch (mode_) { | 10044 switch (mode_) { |
| 10179 case NO_OVERWRITE: overwrite_name = "Alloc"; break; | 10045 case NO_OVERWRITE: overwrite_name = "Alloc"; break; |
| 10180 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; | 10046 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10467 case Token::MUL: | 10333 case Token::MUL: |
| 10468 case Token::DIV: { | 10334 case Token::DIV: { |
| 10469 ASSERT(use_fp_on_smis.is_linked()); | 10335 ASSERT(use_fp_on_smis.is_linked()); |
| 10470 __ bind(&use_fp_on_smis); | 10336 __ bind(&use_fp_on_smis); |
| 10471 if (op_ == Token::DIV) { | 10337 if (op_ == Token::DIV) { |
| 10472 __ movq(rdx, rax); | 10338 __ movq(rdx, rax); |
| 10473 __ movq(rax, rbx); | 10339 __ movq(rax, rbx); |
| 10474 } | 10340 } |
| 10475 // left is rdx, right is rax. | 10341 // left is rdx, right is rax. |
| 10476 __ AllocateHeapNumber(rbx, rcx, slow); | 10342 __ AllocateHeapNumber(rbx, rcx, slow); |
| 10477 FloatingPointHelper::LoadFloatOperandsFromSmis(masm, xmm4, xmm5); | 10343 FloatingPointHelper::LoadSSE2SmiOperands(masm); |
| 10478 switch (op_) { | 10344 switch (op_) { |
| 10479 case Token::ADD: __ addsd(xmm4, xmm5); break; | 10345 case Token::ADD: __ addsd(xmm0, xmm1); break; |
| 10480 case Token::SUB: __ subsd(xmm4, xmm5); break; | 10346 case Token::SUB: __ subsd(xmm0, xmm1); break; |
| 10481 case Token::MUL: __ mulsd(xmm4, xmm5); break; | 10347 case Token::MUL: __ mulsd(xmm0, xmm1); break; |
| 10482 case Token::DIV: __ divsd(xmm4, xmm5); break; | 10348 case Token::DIV: __ divsd(xmm0, xmm1); break; |
| 10483 default: UNREACHABLE(); | 10349 default: UNREACHABLE(); |
| 10484 } | 10350 } |
| 10485 __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm4); | 10351 __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm0); |
| 10486 __ movq(rax, rbx); | 10352 __ movq(rax, rbx); |
| 10487 GenerateReturn(masm); | 10353 GenerateReturn(masm); |
| 10488 } | 10354 } |
| 10489 default: | 10355 default: |
| 10490 break; | 10356 break; |
| 10491 } | 10357 } |
| 10492 | 10358 |
| 10493 // 6. Non-smi operands, fall out to the non-smi code with the operands in | 10359 // 6. Non-smi operands, fall out to the non-smi code with the operands in |
| 10494 // rdx and rax. | 10360 // rdx and rax. |
| 10495 Comment done_comment(masm, "-- Enter non-smi code"); | 10361 Comment done_comment(masm, "-- Enter non-smi code"); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 10520 | 10386 |
| 10521 if (ShouldGenerateSmiCode()) { | 10387 if (ShouldGenerateSmiCode()) { |
| 10522 GenerateSmiCode(masm, &call_runtime); | 10388 GenerateSmiCode(masm, &call_runtime); |
| 10523 } else if (op_ != Token::MOD) { | 10389 } else if (op_ != Token::MOD) { |
| 10524 if (!HasArgsInRegisters()) { | 10390 if (!HasArgsInRegisters()) { |
| 10525 GenerateLoadArguments(masm); | 10391 GenerateLoadArguments(masm); |
| 10526 } | 10392 } |
| 10527 } | 10393 } |
| 10528 // Floating point case. | 10394 // Floating point case. |
| 10529 if (ShouldGenerateFPCode()) { | 10395 if (ShouldGenerateFPCode()) { |
| 10530 // Load the HeapNumber map here and use it throughout the FP code. | |
| 10531 Register heap_number_map = r9; | |
| 10532 switch (op_) { | 10396 switch (op_) { |
| 10533 case Token::ADD: | 10397 case Token::ADD: |
| 10534 case Token::SUB: | 10398 case Token::SUB: |
| 10535 case Token::MUL: | 10399 case Token::MUL: |
| 10536 case Token::DIV: { | 10400 case Token::DIV: { |
| 10537 if (runtime_operands_type_ == BinaryOpIC::DEFAULT && | 10401 if (runtime_operands_type_ == BinaryOpIC::DEFAULT && |
| 10538 HasSmiCodeInStub()) { | 10402 HasSmiCodeInStub()) { |
| 10539 // Execution reaches this point when the first non-smi argument occurs | 10403 // Execution reaches this point when the first non-smi argument occurs |
| 10540 // (and only if smi code is generated). This is the right moment to | 10404 // (and only if smi code is generated). This is the right moment to |
| 10541 // patch to HEAP_NUMBERS state. The transition is attempted only for | 10405 // patch to HEAP_NUMBERS state. The transition is attempted only for |
| 10542 // the four basic operations. The stub stays in the DEFAULT state | 10406 // the four basic operations. The stub stays in the DEFAULT state |
| 10543 // forever for all other operations (also if smi code is skipped). | 10407 // forever for all other operations (also if smi code is skipped). |
| 10544 GenerateTypeTransition(masm); | 10408 GenerateTypeTransition(masm); |
| 10545 } | 10409 } |
| 10546 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); | |
| 10547 | 10410 |
| 10548 Label not_floats; | 10411 Label not_floats; |
| 10549 // rax: y | 10412 // rax: y |
| 10550 // rdx: x | 10413 // rdx: x |
| 10551 if (static_operands_type_.IsNumber() && FLAG_debug_code) { | 10414 ASSERT(!static_operands_type_.IsSmi()); |
| 10552 // Assert at runtime that inputs are only numbers. | 10415 if (static_operands_type_.IsNumber()) { |
| 10553 __ AbortIfNotNumber(rdx); | 10416 if (FLAG_debug_code) { |
| 10554 __ AbortIfNotNumber(rax); | 10417 // Assert at runtime that inputs are only numbers. |
| 10418 __ AbortIfNotNumber(rdx); |
| 10419 __ AbortIfNotNumber(rax); |
| 10420 } |
| 10421 FloatingPointHelper::LoadSSE2NumberOperands(masm); |
| 10555 } else { | 10422 } else { |
| 10556 if (FLAG_debug_code) { | 10423 FloatingPointHelper::LoadSSE2UnknownOperands(masm, &call_runtime); |
| 10557 __ AbortIfNotRootValue(heap_number_map, | |
| 10558 Heap::kHeapNumberMapRootIndex, | |
| 10559 "HeapNumberMap register clobbered."); | |
| 10560 } | |
| 10561 FloatingPointHelper::CheckNumberOperands(masm, | |
| 10562 &call_runtime, | |
| 10563 heap_number_map); | |
| 10564 } | 10424 } |
| 10565 // Fast-case: Both operands are numbers. | |
| 10566 // xmm4 and xmm5 are volatile XMM registers. | |
| 10567 FloatingPointHelper::LoadFloatOperands(masm, xmm4, xmm5); | |
| 10568 | 10425 |
| 10569 switch (op_) { | 10426 switch (op_) { |
| 10570 case Token::ADD: __ addsd(xmm4, xmm5); break; | 10427 case Token::ADD: __ addsd(xmm0, xmm1); break; |
| 10571 case Token::SUB: __ subsd(xmm4, xmm5); break; | 10428 case Token::SUB: __ subsd(xmm0, xmm1); break; |
| 10572 case Token::MUL: __ mulsd(xmm4, xmm5); break; | 10429 case Token::MUL: __ mulsd(xmm0, xmm1); break; |
| 10573 case Token::DIV: __ divsd(xmm4, xmm5); break; | 10430 case Token::DIV: __ divsd(xmm0, xmm1); break; |
| 10574 default: UNREACHABLE(); | 10431 default: UNREACHABLE(); |
| 10575 } | 10432 } |
| 10576 // Allocate a heap number, if needed. | 10433 // Allocate a heap number, if needed. |
| 10577 Label skip_allocation; | 10434 Label skip_allocation; |
| 10578 OverwriteMode mode = mode_; | 10435 OverwriteMode mode = mode_; |
| 10579 if (HasArgsReversed()) { | 10436 if (HasArgsReversed()) { |
| 10580 if (mode == OVERWRITE_RIGHT) { | 10437 if (mode == OVERWRITE_RIGHT) { |
| 10581 mode = OVERWRITE_LEFT; | 10438 mode = OVERWRITE_LEFT; |
| 10582 } else if (mode == OVERWRITE_LEFT) { | 10439 } else if (mode == OVERWRITE_LEFT) { |
| 10583 mode = OVERWRITE_RIGHT; | 10440 mode = OVERWRITE_RIGHT; |
| 10584 } | 10441 } |
| 10585 } | 10442 } |
| 10586 switch (mode) { | 10443 switch (mode) { |
| 10587 // TODO(lrn): Allocate this when we first see that the | |
| 10588 // left register is a smi (and load it into xmm4). | |
| 10589 case OVERWRITE_LEFT: | 10444 case OVERWRITE_LEFT: |
| 10590 __ JumpIfNotSmi(rdx, &skip_allocation); | 10445 __ JumpIfNotSmi(rdx, &skip_allocation); |
| 10591 // Allocate heap number in new space. | 10446 __ AllocateHeapNumber(rbx, rcx, &call_runtime); |
| 10592 __ AllocateInNewSpace(HeapNumber::kSize, | |
| 10593 rbx, | |
| 10594 rcx, | |
| 10595 no_reg, | |
| 10596 &call_runtime, | |
| 10597 TAG_OBJECT); | |
| 10598 if (FLAG_debug_code) { | |
| 10599 __ AbortIfNotRootValue(heap_number_map, | |
| 10600 Heap::kHeapNumberMapRootIndex, | |
| 10601 "HeapNumberMap register clobbered."); | |
| 10602 } | |
| 10603 __ movq(FieldOperand(rbx, HeapObject::kMapOffset), | |
| 10604 heap_number_map); | |
| 10605 __ movq(rdx, rbx); | 10447 __ movq(rdx, rbx); |
| 10606 __ bind(&skip_allocation); | 10448 __ bind(&skip_allocation); |
| 10607 __ movq(rax, rdx); | 10449 __ movq(rax, rdx); |
| 10608 break; | 10450 break; |
| 10609 case OVERWRITE_RIGHT: | 10451 case OVERWRITE_RIGHT: |
| 10610 // If the argument in rax is already an object, we skip the | 10452 // If the argument in rax is already an object, we skip the |
| 10611 // allocation of a heap number. | 10453 // allocation of a heap number. |
| 10612 // TODO(lrn): Allocate the heap number when we first see that the | |
| 10613 // right register is a smi (and load it into xmm5). | |
| 10614 __ JumpIfNotSmi(rax, &skip_allocation); | 10454 __ JumpIfNotSmi(rax, &skip_allocation); |
| 10615 // Fall through! | 10455 // Fall through! |
| 10616 case NO_OVERWRITE: | 10456 case NO_OVERWRITE: |
| 10617 // Allocate a heap number for the result. Keep rax and rdx intact | 10457 // Allocate a heap number for the result. Keep rax and rdx intact |
| 10618 // for the possible runtime call. | 10458 // for the possible runtime call. |
| 10619 __ AllocateInNewSpace(HeapNumber::kSize, | 10459 __ AllocateHeapNumber(rbx, rcx, &call_runtime); |
| 10620 rbx, | |
| 10621 rcx, | |
| 10622 no_reg, | |
| 10623 &call_runtime, | |
| 10624 TAG_OBJECT); | |
| 10625 if (FLAG_debug_code) { | |
| 10626 __ AbortIfNotRootValue(heap_number_map, | |
| 10627 Heap::kHeapNumberMapRootIndex, | |
| 10628 "HeapNumberMap register clobbered."); | |
| 10629 } | |
| 10630 __ movq(FieldOperand(rbx, HeapObject::kMapOffset), | |
| 10631 heap_number_map); | |
| 10632 __ movq(rax, rbx); | 10460 __ movq(rax, rbx); |
| 10633 __ bind(&skip_allocation); | 10461 __ bind(&skip_allocation); |
| 10634 break; | 10462 break; |
| 10635 default: UNREACHABLE(); | 10463 default: UNREACHABLE(); |
| 10636 } | 10464 } |
| 10637 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm4); | 10465 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0); |
| 10638 GenerateReturn(masm); | 10466 GenerateReturn(masm); |
| 10639 __ bind(¬_floats); | 10467 __ bind(¬_floats); |
| 10640 if (runtime_operands_type_ == BinaryOpIC::DEFAULT && | 10468 if (runtime_operands_type_ == BinaryOpIC::DEFAULT && |
| 10641 !HasSmiCodeInStub()) { | 10469 !HasSmiCodeInStub()) { |
| 10642 // Execution reaches this point when the first non-number argument | 10470 // Execution reaches this point when the first non-number argument |
| 10643 // occurs (and only if smi code is skipped from the stub, otherwise | 10471 // occurs (and only if smi code is skipped from the stub, otherwise |
| 10644 // the patching has already been done earlier in this case branch). | 10472 // the patching has already been done earlier in this case branch). |
| 10645 // A perfect moment to try patching to STRINGS for ADD operation. | 10473 // A perfect moment to try patching to STRINGS for ADD operation. |
| 10646 if (op_ == Token::ADD) { | 10474 if (op_ == Token::ADD) { |
| 10647 GenerateTypeTransition(masm); | 10475 GenerateTypeTransition(masm); |
| 10648 } | 10476 } |
| 10649 } | 10477 } |
| 10650 break; | 10478 break; |
| 10651 } | 10479 } |
| 10652 case Token::MOD: { | 10480 case Token::MOD: { |
| 10653 // For MOD we go directly to runtime in the non-smi case. | 10481 // For MOD we go directly to runtime in the non-smi case. |
| 10654 break; | 10482 break; |
| 10655 } | 10483 } |
| 10656 case Token::BIT_OR: | 10484 case Token::BIT_OR: |
| 10657 case Token::BIT_AND: | 10485 case Token::BIT_AND: |
| 10658 case Token::BIT_XOR: | 10486 case Token::BIT_XOR: |
| 10659 case Token::SAR: | 10487 case Token::SAR: |
| 10660 case Token::SHL: | 10488 case Token::SHL: |
| 10661 case Token::SHR: { | 10489 case Token::SHR: { |
| 10662 Label skip_allocation, non_smi_shr_result; | 10490 Label skip_allocation, non_smi_result; |
| 10663 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); | 10491 FloatingPointHelper::LoadAsIntegers(masm, &call_runtime); |
| 10664 FloatingPointHelper::LoadAsIntegers(masm, | |
| 10665 &call_runtime, | |
| 10666 heap_number_map); | |
| 10667 switch (op_) { | 10492 switch (op_) { |
| 10668 case Token::BIT_OR: __ orl(rax, rcx); break; | 10493 case Token::BIT_OR: __ orl(rax, rcx); break; |
| 10669 case Token::BIT_AND: __ andl(rax, rcx); break; | 10494 case Token::BIT_AND: __ andl(rax, rcx); break; |
| 10670 case Token::BIT_XOR: __ xorl(rax, rcx); break; | 10495 case Token::BIT_XOR: __ xorl(rax, rcx); break; |
| 10671 case Token::SAR: __ sarl_cl(rax); break; | 10496 case Token::SAR: __ sarl_cl(rax); break; |
| 10672 case Token::SHL: __ shll_cl(rax); break; | 10497 case Token::SHL: __ shll_cl(rax); break; |
| 10673 case Token::SHR: __ shrl_cl(rax); break; | 10498 case Token::SHR: __ shrl_cl(rax); break; |
| 10674 default: UNREACHABLE(); | 10499 default: UNREACHABLE(); |
| 10675 } | 10500 } |
| 10676 if (op_ == Token::SHR) { | 10501 if (op_ == Token::SHR) { |
| 10677 // Check if result is negative. This can only happen for a shift | 10502 // Check if result is negative. This can only happen for a shift |
| 10678 // by zero. | 10503 // by zero, which also doesn't update the sign flag. |
| 10679 __ testl(rax, rax); | 10504 __ testl(rax, rax); |
| 10680 __ j(negative, &non_smi_shr_result); | 10505 __ j(negative, &non_smi_result); |
| 10681 } | 10506 } |
| 10682 STATIC_ASSERT(kSmiValueSize == 32); | 10507 __ JumpIfNotValidSmiValue(rax, &non_smi_result); |
| 10683 // Tag smi result and return. | 10508 // Tag smi result, if possible, and return. |
| 10684 __ Integer32ToSmi(rax, rax); | 10509 __ Integer32ToSmi(rax, rax); |
| 10685 GenerateReturn(masm); | 10510 GenerateReturn(masm); |
| 10686 | 10511 |
| 10687 // All bit-ops except SHR return a signed int32 that can be | 10512 // All ops except SHR return a signed int32 that we load in |
| 10688 // returned immediately as a smi. | 10513 // a HeapNumber. |
| 10689 if (op_ == Token::SHR) { | 10514 if (op_ != Token::SHR && non_smi_result.is_linked()) { |
| 10690 ASSERT(non_smi_shr_result.is_linked()); | 10515 __ bind(&non_smi_result); |
| 10691 __ bind(&non_smi_shr_result); | |
| 10692 // Allocate a heap number if needed. | 10516 // Allocate a heap number if needed. |
| 10693 __ movl(rbx, rax); // rbx holds result value (uint32 value as int64). | 10517 __ movsxlq(rbx, rax); // rbx: sign extended 32-bit result |
| 10694 switch (mode_) { | 10518 switch (mode_) { |
| 10695 case OVERWRITE_LEFT: | 10519 case OVERWRITE_LEFT: |
| 10696 case OVERWRITE_RIGHT: | 10520 case OVERWRITE_RIGHT: |
| 10697 // If the operand was an object, we skip the | 10521 // If the operand was an object, we skip the |
| 10698 // allocation of a heap number. | 10522 // allocation of a heap number. |
| 10699 __ movq(rax, Operand(rsp, mode_ == OVERWRITE_RIGHT ? | 10523 __ movq(rax, Operand(rsp, mode_ == OVERWRITE_RIGHT ? |
| 10700 1 * kPointerSize : 2 * kPointerSize)); | 10524 1 * kPointerSize : 2 * kPointerSize)); |
| 10701 __ JumpIfNotSmi(rax, &skip_allocation); | 10525 __ JumpIfNotSmi(rax, &skip_allocation); |
| 10702 // Fall through! | 10526 // Fall through! |
| 10703 case NO_OVERWRITE: | 10527 case NO_OVERWRITE: |
| 10704 // Allocate heap number in new space. | 10528 __ AllocateHeapNumber(rax, rcx, &call_runtime); |
| 10705 __ AllocateInNewSpace(HeapNumber::kSize, | |
| 10706 rax, | |
| 10707 rcx, | |
| 10708 no_reg, | |
| 10709 &call_runtime, | |
| 10710 TAG_OBJECT); | |
| 10711 // Set the map. | |
| 10712 if (FLAG_debug_code) { | |
| 10713 __ AbortIfNotRootValue(heap_number_map, | |
| 10714 Heap::kHeapNumberMapRootIndex, | |
| 10715 "HeapNumberMap register clobbered."); | |
| 10716 } | |
| 10717 __ movq(FieldOperand(rax, HeapObject::kMapOffset), | |
| 10718 heap_number_map); | |
| 10719 __ bind(&skip_allocation); | 10529 __ bind(&skip_allocation); |
| 10720 break; | 10530 break; |
| 10721 default: UNREACHABLE(); | 10531 default: UNREACHABLE(); |
| 10722 } | 10532 } |
| 10723 // Store the result in the HeapNumber and return. | 10533 // Store the result in the HeapNumber and return. |
| 10724 __ cvtqsi2sd(xmm0, rbx); | 10534 __ movq(Operand(rsp, 1 * kPointerSize), rbx); |
| 10725 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0); | 10535 __ fild_s(Operand(rsp, 1 * kPointerSize)); |
| 10536 __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset)); |
| 10726 GenerateReturn(masm); | 10537 GenerateReturn(masm); |
| 10727 } | 10538 } |
| 10728 | 10539 |
| 10540 // SHR should return uint32 - go to runtime for non-smi/negative result. |
| 10541 if (op_ == Token::SHR) { |
| 10542 __ bind(&non_smi_result); |
| 10543 } |
| 10729 break; | 10544 break; |
| 10730 } | 10545 } |
| 10731 default: UNREACHABLE(); break; | 10546 default: UNREACHABLE(); break; |
| 10732 } | 10547 } |
| 10733 } | 10548 } |
| 10734 | 10549 |
| 10735 // If all else fails, use the runtime system to get the correct | 10550 // If all else fails, use the runtime system to get the correct |
| 10736 // result. If arguments was passed in registers now place them on the | 10551 // result. If arguments was passed in registers now place them on the |
| 10737 // stack in the correct order below the return address. | 10552 // stack in the correct order below the return address. |
| 10738 __ bind(&call_runtime); | 10553 __ bind(&call_runtime); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 10751 rhs = rdx; | 10566 rhs = rdx; |
| 10752 } else { | 10567 } else { |
| 10753 lhs = rdx; | 10568 lhs = rdx; |
| 10754 rhs = rax; | 10569 rhs = rax; |
| 10755 } | 10570 } |
| 10756 | 10571 |
| 10757 // Test for string arguments before calling runtime. | 10572 // Test for string arguments before calling runtime. |
| 10758 Label not_strings, both_strings, not_string1, string1, string1_smi2; | 10573 Label not_strings, both_strings, not_string1, string1, string1_smi2; |
| 10759 | 10574 |
| 10760 // If this stub has already generated FP-specific code then the arguments | 10575 // If this stub has already generated FP-specific code then the arguments |
| 10761 // are already in rdx, rax. | 10576 // are already in rdx, rax |
| 10762 if (!ShouldGenerateFPCode() && !HasArgsInRegisters()) { | 10577 if (!ShouldGenerateFPCode() && !HasArgsInRegisters()) { |
| 10763 GenerateLoadArguments(masm); | 10578 GenerateLoadArguments(masm); |
| 10764 } | 10579 } |
| 10765 | 10580 |
| 10766 Condition is_smi; | 10581 Condition is_smi; |
| 10767 is_smi = masm->CheckSmi(lhs); | 10582 is_smi = masm->CheckSmi(lhs); |
| 10768 __ j(is_smi, ¬_string1); | 10583 __ j(is_smi, ¬_string1); |
| 10769 __ CmpObjectType(lhs, FIRST_NONSTRING_TYPE, r8); | 10584 __ CmpObjectType(lhs, FIRST_NONSTRING_TYPE, r8); |
| 10770 __ j(above_equal, ¬_string1); | 10585 __ j(above_equal, ¬_string1); |
| 10771 | 10586 |
| (...skipping 1260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12032 } | 11847 } |
| 12033 | 11848 |
| 12034 #endif | 11849 #endif |
| 12035 | 11850 |
| 12036 | 11851 |
| 12037 #undef __ | 11852 #undef __ |
| 12038 | 11853 |
| 12039 } } // namespace v8::internal | 11854 } } // namespace v8::internal |
| 12040 | 11855 |
| 12041 #endif // V8_TARGET_ARCH_X64 | 11856 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |