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 |