| 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 4024 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4035 frame_->Push(&result); | 4035 frame_->Push(&result); |
| 4036 } | 4036 } |
| 4037 | 4037 |
| 4038 | 4038 |
| 4039 void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) { | 4039 void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) { |
| 4040 ASSERT_EQ(args->length(), 1); | 4040 ASSERT_EQ(args->length(), 1); |
| 4041 | 4041 |
| 4042 // Load the argument on the stack and jump to the runtime. | 4042 // Load the argument on the stack and jump to the runtime. |
| 4043 Load(args->at(0)); | 4043 Load(args->at(0)); |
| 4044 | 4044 |
| 4045 Result answer = frame_->CallRuntime(Runtime::kNumberToString, 1); | 4045 NumberToStringStub stub; |
| 4046 frame_->Push(&answer); | 4046 Result result = frame_->CallStub(&stub, 1); |
| 4047 frame_->Push(&result); |
| 4047 } | 4048 } |
| 4048 | 4049 |
| 4049 | 4050 |
| 4050 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { | 4051 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { |
| 4051 ASSERT_EQ(args->length(), 1); | 4052 ASSERT_EQ(args->length(), 1); |
| 4052 // Load the argument on the stack and jump to the runtime. | 4053 // Load the argument on the stack and jump to the runtime. |
| 4053 Load(args->at(0)); | 4054 Load(args->at(0)); |
| 4054 Result answer = frame_->CallRuntime(Runtime::kMath_sin, 1); | 4055 Result answer = frame_->CallRuntime(Runtime::kMath_sin, 1); |
| 4055 frame_->Push(&answer); | 4056 frame_->Push(&answer); |
| 4056 } | 4057 } |
| (...skipping 3132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7189 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); | 7190 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); |
| 7190 __ ret(4 * kPointerSize); | 7191 __ ret(4 * kPointerSize); |
| 7191 | 7192 |
| 7192 // Do the runtime call to execute the regexp. | 7193 // Do the runtime call to execute the regexp. |
| 7193 __ bind(&runtime); | 7194 __ bind(&runtime); |
| 7194 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 7195 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
| 7195 #endif // V8_NATIVE_REGEXP | 7196 #endif // V8_NATIVE_REGEXP |
| 7196 } | 7197 } |
| 7197 | 7198 |
| 7198 | 7199 |
| 7200 void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm, |
| 7201 Register object, |
| 7202 Register result, |
| 7203 Register scratch1, |
| 7204 Register scratch2, |
| 7205 bool object_is_smi, |
| 7206 Label* not_found) { |
| 7207 // Currently only lookup for smis. Check for smi if object is not known to be |
| 7208 // a smi. |
| 7209 if (!object_is_smi) { |
| 7210 __ JumpIfNotSmi(object, not_found); |
| 7211 } |
| 7212 |
| 7213 // Use of registers. Register result is used as a temporary. |
| 7214 Register number_string_cache = result; |
| 7215 Register mask = scratch1; |
| 7216 Register scratch = scratch2; |
| 7217 |
| 7218 // Load the number string cache. |
| 7219 __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); |
| 7220 |
| 7221 // Make the hash mask from the length of the number string cache. It |
| 7222 // contains two elements (number and string) for each cache entry. |
| 7223 __ movl(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); |
| 7224 __ shrl(mask, Immediate(1)); // Divide length by two (length is not a smi). |
| 7225 __ subl(mask, Immediate(1)); // Make mask. |
| 7226 |
| 7227 // Calculate the entry in the number string cache. The hash value in the |
| 7228 // number string cache for smis is just the smi value. |
| 7229 __ movq(scratch, object); |
| 7230 __ SmiToInteger32(scratch, scratch); |
| 7231 __ andl(scratch, mask); |
| 7232 |
| 7233 // Each entry in string cache consists of two pointer sized fields, |
| 7234 // but times_twice_pointer_size (multiplication by 16) scale factor |
| 7235 // is not supported by addrmode on x64 platform. |
| 7236 // So we have to premultiply entry index before lookup |
| 7237 __ shl(scratch, Immediate(kPointerSizeLog2 + 1)); |
| 7238 // Check if the entry is the smi we are looking for. |
| 7239 __ cmpq(object, |
| 7240 FieldOperand(number_string_cache, |
| 7241 scratch, |
| 7242 times_1, |
| 7243 FixedArray::kHeaderSize)); |
| 7244 __ j(not_equal, not_found); |
| 7245 |
| 7246 // Get the result from the cache. |
| 7247 __ movq(result, |
| 7248 FieldOperand(number_string_cache, |
| 7249 scratch, |
| 7250 times_1, |
| 7251 FixedArray::kHeaderSize + kPointerSize)); |
| 7252 __ IncrementCounter(&Counters::number_to_string_native, 1); |
| 7253 } |
| 7254 |
| 7255 |
| 7256 void NumberToStringStub::Generate(MacroAssembler* masm) { |
| 7257 Label runtime; |
| 7258 |
| 7259 __ movq(rbx, Operand(rsp, kPointerSize)); |
| 7260 |
| 7261 // Generate code to lookup number in the number string cache. |
| 7262 GenerateLookupNumberStringCache(masm, rbx, rax, r8, r9, false, &runtime); |
| 7263 __ ret(1 * kPointerSize); |
| 7264 |
| 7265 __ bind(&runtime); |
| 7266 // Handle number to string in the runtime system if not found in the cache. |
| 7267 __ TailCallRuntime(Runtime::kNumberToString, 1, 1); |
| 7268 } |
| 7269 |
| 7270 |
| 7199 void CompareStub::Generate(MacroAssembler* masm) { | 7271 void CompareStub::Generate(MacroAssembler* masm) { |
| 7200 Label call_builtin, done; | 7272 Label call_builtin, done; |
| 7201 | 7273 |
| 7202 // NOTICE! This code is only reached after a smi-fast-case check, so | 7274 // NOTICE! This code is only reached after a smi-fast-case check, so |
| 7203 // it is certain that at least one operand isn't a smi. | 7275 // it is certain that at least one operand isn't a smi. |
| 7204 | 7276 |
| 7205 if (cc_ == equal) { // Both strict and non-strict. | 7277 if (cc_ == equal) { // Both strict and non-strict. |
| 7206 Label slow; // Fallthrough label. | 7278 Label slow; // Fallthrough label. |
| 7207 // Equality is almost reflexive (everything but NaN), so start by testing | 7279 // Equality is almost reflexive (everything but NaN), so start by testing |
| 7208 // for "identity and not NaN". | 7280 // for "identity and not NaN". |
| (...skipping 1567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8776 } | 8848 } |
| 8777 break; | 8849 break; |
| 8778 } | 8850 } |
| 8779 default: UNREACHABLE(); break; | 8851 default: UNREACHABLE(); break; |
| 8780 } | 8852 } |
| 8781 | 8853 |
| 8782 // If all else fails, use the runtime system to get the correct | 8854 // If all else fails, use the runtime system to get the correct |
| 8783 // result. If arguments was passed in registers now place them on the | 8855 // result. If arguments was passed in registers now place them on the |
| 8784 // stack in the correct order below the return address. | 8856 // stack in the correct order below the return address. |
| 8785 __ bind(&call_runtime); | 8857 __ bind(&call_runtime); |
| 8858 |
| 8786 if (HasArgsInRegisters()) { | 8859 if (HasArgsInRegisters()) { |
| 8787 __ pop(rcx); | 8860 __ pop(rcx); |
| 8788 if (HasArgsReversed()) { | 8861 if (HasArgsReversed()) { |
| 8789 __ push(rax); | 8862 __ push(rax); |
| 8790 __ push(rdx); | 8863 __ push(rdx); |
| 8791 } else { | 8864 } else { |
| 8792 __ push(rdx); | 8865 __ push(rdx); |
| 8793 __ push(rax); | 8866 __ push(rax); |
| 8794 } | 8867 } |
| 8795 __ push(rcx); | 8868 __ push(rcx); |
| 8796 } | 8869 } |
| 8870 |
| 8797 switch (op_) { | 8871 switch (op_) { |
| 8798 case Token::ADD: { | 8872 case Token::ADD: { |
| 8873 // Registers containing left and right operands respectively. |
| 8874 Register lhs, rhs; |
| 8875 |
| 8876 if (HasArgsReversed()) { |
| 8877 lhs = rax; |
| 8878 rhs = rdx; |
| 8879 } else { |
| 8880 lhs = rdx; |
| 8881 rhs = rax; |
| 8882 } |
| 8883 |
| 8799 // Test for string arguments before calling runtime. | 8884 // Test for string arguments before calling runtime. |
| 8800 Label not_strings, both_strings, not_string1, string1; | 8885 Label not_strings, both_strings, not_string1, string1, string1_smi2; |
| 8801 Condition is_smi; | 8886 Condition is_smi; |
| 8802 Result answer; | 8887 Result answer; |
| 8803 is_smi = masm->CheckSmi(rdx); | 8888 is_smi = masm->CheckSmi(lhs); |
| 8804 __ j(is_smi, ¬_string1); | 8889 __ j(is_smi, ¬_string1); |
| 8805 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rdx); | 8890 __ CmpObjectType(lhs, FIRST_NONSTRING_TYPE, r8); |
| 8806 __ j(above_equal, ¬_string1); | 8891 __ j(above_equal, ¬_string1); |
| 8807 | 8892 |
| 8808 // First argument is a a string, test second. | 8893 // First argument is a a string, test second. |
| 8809 is_smi = masm->CheckSmi(rax); | 8894 is_smi = masm->CheckSmi(rhs); |
| 8810 __ j(is_smi, &string1); | 8895 __ j(is_smi, &string1_smi2); |
| 8811 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rax); | 8896 __ CmpObjectType(rhs, FIRST_NONSTRING_TYPE, r9); |
| 8812 __ j(above_equal, &string1); | 8897 __ j(above_equal, &string1); |
| 8813 | 8898 |
| 8814 // First and second argument are strings. | 8899 // First and second argument are strings. |
| 8815 StringAddStub stub(NO_STRING_CHECK_IN_STUB); | 8900 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); |
| 8816 __ TailCallStub(&stub); | 8901 __ TailCallStub(&string_add_stub); |
| 8902 |
| 8903 __ bind(&string1_smi2); |
| 8904 // First argument is a string, second is a smi. Try to lookup the number |
| 8905 // string for the smi in the number string cache. |
| 8906 NumberToStringStub::GenerateLookupNumberStringCache( |
| 8907 masm, rhs, rbx, rcx, r8, true, &string1); |
| 8908 |
| 8909 // Replace second argument on stack and tailcall string add stub to make |
| 8910 // the result. |
| 8911 __ movq(Operand(rsp, 1 * kPointerSize), rbx); |
| 8912 __ TailCallStub(&string_add_stub); |
| 8817 | 8913 |
| 8818 // Only first argument is a string. | 8914 // Only first argument is a string. |
| 8819 __ bind(&string1); | 8915 __ bind(&string1); |
| 8820 __ InvokeBuiltin( | 8916 __ InvokeBuiltin(Builtins::STRING_ADD_LEFT, JUMP_FUNCTION); |
| 8821 HasArgsReversed() ? | |
| 8822 Builtins::STRING_ADD_RIGHT : | |
| 8823 Builtins::STRING_ADD_LEFT, | |
| 8824 JUMP_FUNCTION); | |
| 8825 | 8917 |
| 8826 // First argument was not a string, test second. | 8918 // First argument was not a string, test second. |
| 8827 __ bind(¬_string1); | 8919 __ bind(¬_string1); |
| 8828 is_smi = masm->CheckSmi(rax); | 8920 is_smi = masm->CheckSmi(rhs); |
| 8829 __ j(is_smi, ¬_strings); | 8921 __ j(is_smi, ¬_strings); |
| 8830 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rax); | 8922 __ CmpObjectType(rhs, FIRST_NONSTRING_TYPE, rhs); |
| 8831 __ j(above_equal, ¬_strings); | 8923 __ j(above_equal, ¬_strings); |
| 8832 | 8924 |
| 8833 // Only second argument is a string. | 8925 // Only second argument is a string. |
| 8834 __ InvokeBuiltin( | 8926 __ InvokeBuiltin(Builtins::STRING_ADD_RIGHT, JUMP_FUNCTION); |
| 8835 HasArgsReversed() ? | |
| 8836 Builtins::STRING_ADD_LEFT : | |
| 8837 Builtins::STRING_ADD_RIGHT, | |
| 8838 JUMP_FUNCTION); | |
| 8839 | 8927 |
| 8840 __ bind(¬_strings); | 8928 __ bind(¬_strings); |
| 8841 // Neither argument is a string. | 8929 // Neither argument is a string. |
| 8842 __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION); | 8930 __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION); |
| 8843 break; | 8931 break; |
| 8844 } | 8932 } |
| 8845 case Token::SUB: | 8933 case Token::SUB: |
| 8846 __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION); | 8934 __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION); |
| 8847 break; | 8935 break; |
| 8848 case Token::MUL: | 8936 case Token::MUL: |
| (...skipping 709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9558 // Call the function from C++. | 9646 // Call the function from C++. |
| 9559 return FUNCTION_CAST<ModuloFunction>(buffer); | 9647 return FUNCTION_CAST<ModuloFunction>(buffer); |
| 9560 } | 9648 } |
| 9561 | 9649 |
| 9562 #endif | 9650 #endif |
| 9563 | 9651 |
| 9564 | 9652 |
| 9565 #undef __ | 9653 #undef __ |
| 9566 | 9654 |
| 9567 } } // namespace v8::internal | 9655 } } // namespace v8::internal |
| OLD | NEW |