OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 1754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1765 case Token::SHR: | 1765 case Token::SHR: |
1766 GenerateTypeTransitionWithSavedArgs(masm); | 1766 GenerateTypeTransitionWithSavedArgs(masm); |
1767 break; | 1767 break; |
1768 default: | 1768 default: |
1769 UNREACHABLE(); | 1769 UNREACHABLE(); |
1770 } | 1770 } |
1771 } | 1771 } |
1772 | 1772 |
1773 | 1773 |
1774 void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) { | 1774 void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) { |
1775 Label call_runtime; | |
1776 ASSERT(operands_type_ == TRBinaryOpIC::STRING); | 1775 ASSERT(operands_type_ == TRBinaryOpIC::STRING); |
1777 ASSERT(op_ == Token::ADD); | 1776 ASSERT(op_ == Token::ADD); |
1778 // If one of the arguments is a string, call the string add stub. | 1777 // Try to add arguments as strings, otherwise, transition to the generic |
1779 // Otherwise, transition to the generic TRBinaryOpIC type. | 1778 // TRBinaryOpIC type. |
1780 | 1779 GenerateAddStrings(masm); |
1781 // Registers containing left and right operands respectively. | |
1782 Register left = edx; | |
1783 Register right = eax; | |
1784 | |
1785 // Test if left operand is a string. | |
1786 NearLabel left_not_string; | |
1787 __ test(left, Immediate(kSmiTagMask)); | |
1788 __ j(zero, &left_not_string); | |
1789 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); | |
1790 __ j(above_equal, &left_not_string); | |
1791 | |
1792 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); | |
1793 GenerateRegisterArgsPush(masm); | |
1794 __ TailCallStub(&string_add_left_stub); | |
1795 | |
1796 // Left operand is not a string, test right. | |
1797 __ bind(&left_not_string); | |
1798 __ test(right, Immediate(kSmiTagMask)); | |
1799 __ j(zero, &call_runtime); | |
1800 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); | |
1801 __ j(above_equal, &call_runtime); | |
1802 | |
1803 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); | |
1804 GenerateRegisterArgsPush(masm); | |
1805 __ TailCallStub(&string_add_right_stub); | |
1806 | |
1807 // Neither argument is a string. | |
1808 __ bind(&call_runtime); | |
1809 GenerateTypeTransition(masm); | 1780 GenerateTypeTransition(masm); |
1810 } | 1781 } |
1811 | 1782 |
1812 | 1783 |
1813 void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { | 1784 void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { |
1814 Label call_runtime; | 1785 Label call_runtime; |
1815 ASSERT(operands_type_ == TRBinaryOpIC::INT32); | 1786 ASSERT(operands_type_ == TRBinaryOpIC::INT32); |
1816 | 1787 |
1817 // Floating point case. | 1788 // Floating point case. |
1818 switch (op_) { | 1789 switch (op_) { |
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2339 break; | 2310 break; |
2340 } | 2311 } |
2341 default: UNREACHABLE(); break; | 2312 default: UNREACHABLE(); break; |
2342 } | 2313 } |
2343 | 2314 |
2344 // If all else fails, use the runtime system to get the correct | 2315 // If all else fails, use the runtime system to get the correct |
2345 // result. | 2316 // result. |
2346 __ bind(&call_runtime); | 2317 __ bind(&call_runtime); |
2347 switch (op_) { | 2318 switch (op_) { |
2348 case Token::ADD: { | 2319 case Token::ADD: { |
| 2320 GenerateAddStrings(masm); |
2349 GenerateRegisterArgsPush(masm); | 2321 GenerateRegisterArgsPush(masm); |
2350 // Test for string arguments before calling runtime. | |
2351 // Registers containing left and right operands respectively. | |
2352 Register lhs, rhs; | |
2353 lhs = edx; | |
2354 rhs = eax; | |
2355 | |
2356 // Test if left operand is a string. | |
2357 NearLabel lhs_not_string; | |
2358 __ test(lhs, Immediate(kSmiTagMask)); | |
2359 __ j(zero, &lhs_not_string); | |
2360 __ CmpObjectType(lhs, FIRST_NONSTRING_TYPE, ecx); | |
2361 __ j(above_equal, &lhs_not_string); | |
2362 | |
2363 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); | |
2364 __ TailCallStub(&string_add_left_stub); | |
2365 | |
2366 NearLabel call_add_runtime; | |
2367 // Left operand is not a string, test right. | |
2368 __ bind(&lhs_not_string); | |
2369 __ test(rhs, Immediate(kSmiTagMask)); | |
2370 __ j(zero, &call_add_runtime); | |
2371 __ CmpObjectType(rhs, FIRST_NONSTRING_TYPE, ecx); | |
2372 __ j(above_equal, &call_add_runtime); | |
2373 | |
2374 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); | |
2375 __ TailCallStub(&string_add_right_stub); | |
2376 | |
2377 // Neither argument is a string. | |
2378 __ bind(&call_add_runtime); | |
2379 __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION); | 2322 __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION); |
2380 break; | 2323 break; |
2381 } | 2324 } |
2382 case Token::SUB: | 2325 case Token::SUB: |
2383 GenerateRegisterArgsPush(masm); | 2326 GenerateRegisterArgsPush(masm); |
2384 __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION); | 2327 __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION); |
2385 break; | 2328 break; |
2386 case Token::MUL: | 2329 case Token::MUL: |
2387 GenerateRegisterArgsPush(masm); | 2330 GenerateRegisterArgsPush(masm); |
2388 __ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION); | 2331 __ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION); |
(...skipping 22 matching lines...) Expand all Loading... |
2411 break; | 2354 break; |
2412 case Token::SHR: | 2355 case Token::SHR: |
2413 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); | 2356 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); |
2414 break; | 2357 break; |
2415 default: | 2358 default: |
2416 UNREACHABLE(); | 2359 UNREACHABLE(); |
2417 } | 2360 } |
2418 } | 2361 } |
2419 | 2362 |
2420 | 2363 |
| 2364 void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { |
| 2365 NearLabel call_runtime; |
| 2366 |
| 2367 // Registers containing left and right operands respectively. |
| 2368 Register left = edx; |
| 2369 Register right = eax; |
| 2370 |
| 2371 // Test if left operand is a string. |
| 2372 NearLabel left_not_string; |
| 2373 __ test(left, Immediate(kSmiTagMask)); |
| 2374 __ j(zero, &left_not_string); |
| 2375 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); |
| 2376 __ j(above_equal, &left_not_string); |
| 2377 |
| 2378 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); |
| 2379 GenerateRegisterArgsPush(masm); |
| 2380 __ TailCallStub(&string_add_left_stub); |
| 2381 |
| 2382 // Left operand is not a string, test right. |
| 2383 __ bind(&left_not_string); |
| 2384 __ test(right, Immediate(kSmiTagMask)); |
| 2385 __ j(zero, &call_runtime); |
| 2386 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); |
| 2387 __ j(above_equal, &call_runtime); |
| 2388 |
| 2389 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); |
| 2390 GenerateRegisterArgsPush(masm); |
| 2391 __ TailCallStub(&string_add_right_stub); |
| 2392 |
| 2393 // Neither argument is a string. |
| 2394 __ bind(&call_runtime); |
| 2395 } |
| 2396 |
| 2397 |
2421 void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation( | 2398 void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation( |
2422 MacroAssembler* masm, | 2399 MacroAssembler* masm, |
2423 Label* alloc_failure) { | 2400 Label* alloc_failure) { |
2424 Label skip_allocation; | 2401 Label skip_allocation; |
2425 OverwriteMode mode = mode_; | 2402 OverwriteMode mode = mode_; |
2426 switch (mode) { | 2403 switch (mode) { |
2427 case OVERWRITE_LEFT: { | 2404 case OVERWRITE_LEFT: { |
2428 // If the argument in edx is already an object, we skip the | 2405 // If the argument in edx is already an object, we skip the |
2429 // allocation of a heap number. | 2406 // allocation of a heap number. |
2430 __ test(edx, Immediate(kSmiTagMask)); | 2407 __ test(edx, Immediate(kSmiTagMask)); |
(...skipping 4074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6505 // Do a tail call to the rewritten stub. | 6482 // Do a tail call to the rewritten stub. |
6506 __ jmp(Operand(edi)); | 6483 __ jmp(Operand(edi)); |
6507 } | 6484 } |
6508 | 6485 |
6509 | 6486 |
6510 #undef __ | 6487 #undef __ |
6511 | 6488 |
6512 } } // namespace v8::internal | 6489 } } // namespace v8::internal |
6513 | 6490 |
6514 #endif // V8_TARGET_ARCH_IA32 | 6491 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |