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 2416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2427 | 2427 |
2428 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), | 2428 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), |
2429 "TypeRecordingBinaryOpStub_%s_%s_%s", | 2429 "TypeRecordingBinaryOpStub_%s_%s_%s", |
2430 op_name, | 2430 op_name, |
2431 overwrite_name, | 2431 overwrite_name, |
2432 TRBinaryOpIC::GetName(operands_type_)); | 2432 TRBinaryOpIC::GetName(operands_type_)); |
2433 return name_; | 2433 return name_; |
2434 } | 2434 } |
2435 | 2435 |
2436 | 2436 |
2437 void TypeRecordingBinaryOpStub::GenerateOptimisticSmiOperation( | 2437 void TypeRecordingBinaryOpStub::GenerateSmiSmiOperation( |
2438 MacroAssembler* masm) { | 2438 MacroAssembler* masm) { |
2439 Register left = r1; | 2439 Register left = r1; |
2440 Register right = r0; | 2440 Register right = r0; |
| 2441 Register scratch1 = r7; |
| 2442 Register scratch2 = r9; |
2441 | 2443 |
2442 ASSERT(right.is(r0)); | 2444 ASSERT(right.is(r0)); |
| 2445 STATIC_ASSERT(kSmiTag == 0); |
2443 | 2446 |
| 2447 Label not_smi_result; |
2444 switch (op_) { | 2448 switch (op_) { |
2445 case Token::ADD: | 2449 case Token::ADD: |
2446 __ add(right, left, Operand(right), SetCC); // Add optimistically. | 2450 __ add(right, left, Operand(right), SetCC); // Add optimistically. |
2447 __ Ret(vc); | 2451 __ Ret(vc); |
2448 __ sub(right, right, Operand(left)); // Revert optimistic add. | 2452 __ sub(right, right, Operand(left)); // Revert optimistic add. |
2449 break; | 2453 break; |
2450 case Token::SUB: | 2454 case Token::SUB: |
2451 __ sub(right, left, Operand(right), SetCC); // Subtract optimistically. | 2455 __ sub(right, left, Operand(right), SetCC); // Subtract optimistically. |
2452 __ Ret(vc); | 2456 __ Ret(vc); |
2453 __ sub(right, left, Operand(right)); // Revert optimistic subtract. | 2457 __ sub(right, left, Operand(right)); // Revert optimistic subtract. |
2454 break; | 2458 break; |
| 2459 case Token::MUL: |
| 2460 // Remove tag from one of the operands. This way the multiplication result |
| 2461 // will be a smi if it fits the smi range. |
| 2462 __ SmiUntag(ip, right); |
| 2463 // Do multiplication |
| 2464 // scratch1 = lower 32 bits of ip * left. |
| 2465 // scratch2 = higher 32 bits of ip * left. |
| 2466 __ smull(scratch1, scratch2, left, ip); |
| 2467 // Check for overflowing the smi range - no overflow if higher 33 bits of |
| 2468 // the result are identical. |
| 2469 __ mov(ip, Operand(scratch1, ASR, 31)); |
| 2470 __ cmp(ip, Operand(scratch2)); |
| 2471 __ b(ne, ¬_smi_result); |
| 2472 // Go slow on zero result to handle -0. |
| 2473 __ tst(scratch1, Operand(scratch1)); |
| 2474 __ mov(right, Operand(scratch1), LeaveCC, ne); |
| 2475 __ Ret(ne); |
| 2476 // We need -0 if we were multiplying a negative number with 0 to get 0. |
| 2477 // We know one of them was zero. |
| 2478 __ add(scratch2, right, Operand(left), SetCC); |
| 2479 __ mov(right, Operand(Smi::FromInt(0)), LeaveCC, pl); |
| 2480 __ Ret(pl); // Return smi 0 if the non-zero one was positive. |
| 2481 // We fall through here if we multiplied a negative number with 0, because |
| 2482 // that would mean we should produce -0. |
| 2483 break; |
2455 default: | 2484 default: |
2456 UNREACHABLE(); | 2485 UNREACHABLE(); |
2457 } | 2486 } |
| 2487 __ bind(¬_smi_result); |
2458 } | 2488 } |
2459 | 2489 |
2460 | 2490 |
2461 void TypeRecordingBinaryOpStub::GenerateVFPOperation( | 2491 void TypeRecordingBinaryOpStub::GenerateVFPOperation( |
2462 MacroAssembler* masm) { | 2492 MacroAssembler* masm) { |
2463 switch (op_) { | 2493 switch (op_) { |
2464 case Token::ADD: | 2494 case Token::ADD: |
2465 __ vadd(d5, d6, d7); | 2495 __ vadd(d5, d6, d7); |
2466 break; | 2496 break; |
2467 case Token::SUB: | 2497 case Token::SUB: |
2468 __ vsub(d5, d6, d7); | 2498 __ vsub(d5, d6, d7); |
2469 break; | 2499 break; |
| 2500 case Token::MUL: |
| 2501 __ vmul(d5, d6, d7); |
| 2502 break; |
2470 default: | 2503 default: |
2471 UNREACHABLE(); | 2504 UNREACHABLE(); |
2472 } | 2505 } |
2473 } | 2506 } |
2474 | 2507 |
2475 | 2508 |
2476 // Generate the smi code. If the operation on smis are successful this return is | 2509 // Generate the smi code. If the operation on smis are successful this return is |
2477 // generated. If the result is not a smi and heap number allocation is not | 2510 // generated. If the result is not a smi and heap number allocation is not |
2478 // requested the code falls through. If number allocation is requested but a | 2511 // requested the code falls through. If number allocation is requested but a |
2479 // heap number cannot be allocated the code jumps to the lable gc_required. | 2512 // heap number cannot be allocated the code jumps to the lable gc_required. |
2480 void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, | 2513 void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, |
2481 Label* gc_required, | 2514 Label* gc_required, |
2482 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) { | 2515 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) { |
2483 Label not_smis; | 2516 Label not_smis; |
2484 | 2517 |
2485 ASSERT(op_ == Token::ADD || op_ == Token::SUB); | 2518 ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::MUL); |
2486 | 2519 |
2487 Register left = r1; | 2520 Register left = r1; |
2488 Register right = r0; | 2521 Register right = r0; |
2489 Register scratch1 = r7; | 2522 Register scratch1 = r7; |
2490 Register scratch2 = r9; | 2523 Register scratch2 = r9; |
2491 | 2524 |
2492 // Perform combined smi check on both operands. | 2525 // Perform combined smi check on both operands. |
2493 __ orr(scratch1, left, Operand(right)); | 2526 __ orr(scratch1, left, Operand(right)); |
2494 STATIC_ASSERT(kSmiTag == 0); | 2527 STATIC_ASSERT(kSmiTag == 0); |
2495 __ tst(scratch1, Operand(kSmiTagMask)); | 2528 __ tst(scratch1, Operand(kSmiTagMask)); |
2496 __ b(ne, ¬_smis); | 2529 __ b(ne, ¬_smis); |
2497 | 2530 |
2498 GenerateOptimisticSmiOperation(masm); | 2531 GenerateSmiSmiOperation(masm); |
2499 | 2532 |
2500 // If heap number results are possible generate the result in an allocated | 2533 // If heap number results are possible generate the result in an allocated |
2501 // heap number. | 2534 // heap number. |
2502 if (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) { | 2535 if (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) { |
2503 FloatingPointHelper::Destination destination = | 2536 FloatingPointHelper::Destination destination = |
2504 CpuFeatures::IsSupported(VFP3) && Token::MOD != op_ ? | 2537 CpuFeatures::IsSupported(VFP3) && Token::MOD != op_ ? |
2505 FloatingPointHelper::kVFPRegisters : | 2538 FloatingPointHelper::kVFPRegisters : |
2506 FloatingPointHelper::kCoreRegisters; | 2539 FloatingPointHelper::kCoreRegisters; |
2507 | 2540 |
2508 Register heap_number_map = r6; | 2541 Register heap_number_map = r6; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2556 __ pop(pc); | 2589 __ pop(pc); |
2557 } | 2590 } |
2558 } | 2591 } |
2559 __ bind(¬_smis); | 2592 __ bind(¬_smis); |
2560 } | 2593 } |
2561 | 2594 |
2562 | 2595 |
2563 void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { | 2596 void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { |
2564 Label not_smis, call_runtime; | 2597 Label not_smis, call_runtime; |
2565 | 2598 |
2566 ASSERT(op_ == Token::ADD || op_ == Token::SUB); | 2599 ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::MUL); |
2567 | 2600 |
2568 if (result_type_ == TRBinaryOpIC::UNINITIALIZED || | 2601 if (result_type_ == TRBinaryOpIC::UNINITIALIZED || |
2569 result_type_ == TRBinaryOpIC::SMI) { | 2602 result_type_ == TRBinaryOpIC::SMI) { |
2570 // Only allow smi results. | 2603 // Only allow smi results. |
2571 GenerateSmiCode(masm, NULL, NO_HEAPNUMBER_RESULTS); | 2604 GenerateSmiCode(masm, NULL, NO_HEAPNUMBER_RESULTS); |
2572 } else { | 2605 } else { |
2573 // Allow heap number result and don't make a transition if a heap number | 2606 // Allow heap number result and don't make a transition if a heap number |
2574 // cannot be allocated. | 2607 // cannot be allocated. |
2575 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); | 2608 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); |
2576 } | 2609 } |
(...skipping 11 matching lines...) Expand all Loading... |
2588 ASSERT(operands_type_ == TRBinaryOpIC::STRING); | 2621 ASSERT(operands_type_ == TRBinaryOpIC::STRING); |
2589 ASSERT(op_ == Token::ADD); | 2622 ASSERT(op_ == Token::ADD); |
2590 // Try to add arguments as strings, otherwise, transition to the generic | 2623 // Try to add arguments as strings, otherwise, transition to the generic |
2591 // TRBinaryOpIC type. | 2624 // TRBinaryOpIC type. |
2592 GenerateAddStrings(masm); | 2625 GenerateAddStrings(masm); |
2593 GenerateTypeTransition(masm); | 2626 GenerateTypeTransition(masm); |
2594 } | 2627 } |
2595 | 2628 |
2596 | 2629 |
2597 void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { | 2630 void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { |
2598 ASSERT(op_ == Token::ADD || op_ == Token::SUB); | 2631 ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::SUB); |
2599 | 2632 |
2600 ASSERT(operands_type_ == TRBinaryOpIC::INT32); | 2633 ASSERT(operands_type_ == TRBinaryOpIC::INT32); |
2601 | 2634 |
2602 GenerateTypeTransition(masm); | 2635 GenerateTypeTransition(masm); |
2603 } | 2636 } |
2604 | 2637 |
2605 | 2638 |
2606 void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { | 2639 void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { |
2607 ASSERT(op_ == Token::ADD || op_ == Token::SUB); | 2640 ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::MUL); |
2608 | 2641 |
2609 Register scratch1 = r7; | 2642 Register scratch1 = r7; |
2610 Register scratch2 = r9; | 2643 Register scratch2 = r9; |
2611 | 2644 |
2612 Label not_number, call_runtime; | 2645 Label not_number, call_runtime; |
2613 ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER); | 2646 ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER); |
2614 | 2647 |
2615 Register heap_number_map = r6; | 2648 Register heap_number_map = r6; |
2616 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); | 2649 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
2617 | 2650 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2677 | 2710 |
2678 __ bind(¬_number); | 2711 __ bind(¬_number); |
2679 GenerateTypeTransition(masm); | 2712 GenerateTypeTransition(masm); |
2680 | 2713 |
2681 __ bind(&call_runtime); | 2714 __ bind(&call_runtime); |
2682 GenerateCallRuntime(masm); | 2715 GenerateCallRuntime(masm); |
2683 } | 2716 } |
2684 | 2717 |
2685 | 2718 |
2686 void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) { | 2719 void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) { |
2687 ASSERT(op_ == Token::ADD || op_ == Token::SUB); | 2720 ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::MUL); |
2688 | 2721 |
2689 Label call_runtime; | 2722 Label call_runtime; |
2690 | 2723 |
2691 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); | 2724 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); |
2692 | 2725 |
2693 // If all else fails, use the runtime system to get the correct | 2726 // If all else fails, use the runtime system to get the correct |
2694 // result. | 2727 // result. |
2695 __ bind(&call_runtime); | 2728 __ bind(&call_runtime); |
2696 | 2729 |
2697 // Try to add strings before calling runtime. | 2730 // Try to add strings before calling runtime. |
(...skipping 2962 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5660 __ pop(r1); | 5693 __ pop(r1); |
5661 __ Jump(r2); | 5694 __ Jump(r2); |
5662 } | 5695 } |
5663 | 5696 |
5664 | 5697 |
5665 #undef __ | 5698 #undef __ |
5666 | 5699 |
5667 } } // namespace v8::internal | 5700 } } // namespace v8::internal |
5668 | 5701 |
5669 #endif // V8_TARGET_ARCH_ARM | 5702 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |