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 2415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2426 | 2426 |
2427 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), | 2427 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), |
2428 "TypeRecordingBinaryOpStub_%s_%s_%s", | 2428 "TypeRecordingBinaryOpStub_%s_%s_%s", |
2429 op_name, | 2429 op_name, |
2430 overwrite_name, | 2430 overwrite_name, |
2431 TRBinaryOpIC::GetName(operands_type_)); | 2431 TRBinaryOpIC::GetName(operands_type_)); |
2432 return name_; | 2432 return name_; |
2433 } | 2433 } |
2434 | 2434 |
2435 | 2435 |
2436 void TypeRecordingBinaryOpStub::GenerateOptimisticSmiOperation( | |
2437 MacroAssembler* masm) { | |
2438 Register left = r1; | |
2439 Register right = r0; | |
2440 | |
2441 ASSERT(right.is(r0)); | |
2442 | |
2443 switch (op_) { | |
2444 case Token::ADD: | |
2445 __ add(right, left, Operand(right), SetCC); // Add optimistically. | |
2446 __ Ret(vc); | |
2447 __ sub(right, right, Operand(left)); // Revert optimistic add. | |
2448 break; | |
2449 case Token::SUB: | |
2450 __ sub(right, left, Operand(right), SetCC); // Subtract optimistically. | |
2451 __ Ret(vc); | |
2452 __ sub(right, left, Operand(right)); // Revert optimistic subtract. | |
Alexandre
2011/01/25 16:51:15
Shouldn't it be an add(right, right, Operand(left)
Alexandre
2011/01/25 16:54:45
Sorry I messed up with these right and left.
On 20
| |
2453 break; | |
2454 default: | |
2455 UNREACHABLE(); | |
2456 } | |
2457 } | |
2458 | |
2459 | |
2460 void TypeRecordingBinaryOpStub::GenerateVFPOperation( | |
2461 MacroAssembler* masm) { | |
2462 switch (op_) { | |
2463 case Token::ADD: | |
2464 __ vadd(d5, d6, d7); | |
2465 break; | |
2466 case Token::SUB: | |
2467 __ vsub(d5, d6, d7); | |
2468 break; | |
2469 default: | |
2470 UNREACHABLE(); | |
2471 } | |
2472 | |
2473 } | |
2474 | |
2475 | |
2436 // Generate the smi code. If the operation on smis are successful this return is | 2476 // Generate the smi code. If the operation on smis are successful this return is |
2437 // generated. If the result is not a smi and heap number allocation is not | 2477 // generated. If the result is not a smi and heap number allocation is not |
2438 // requested the code falls through. If number allocation is requested but a | 2478 // requested the code falls through. If number allocation is requested but a |
2439 // heap number cannot be allocated the code jumps to the lable gc_required. | 2479 // heap number cannot be allocated the code jumps to the lable gc_required. |
2440 void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, | 2480 void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, |
2441 Label* gc_required, | 2481 Label* gc_required, |
2442 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) { | 2482 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) { |
2443 Label not_smis; | 2483 Label not_smis; |
2444 | 2484 |
2445 ASSERT(op_ == Token::ADD); | 2485 ASSERT(op_ == Token::ADD || op_ == Token::SUB); |
2446 | 2486 |
2447 Register left = r1; | 2487 Register left = r1; |
2448 Register right = r0; | 2488 Register right = r0; |
2449 Register scratch1 = r7; | 2489 Register scratch1 = r7; |
2450 Register scratch2 = r9; | 2490 Register scratch2 = r9; |
2451 | 2491 |
2452 // Perform combined smi check on both operands. | 2492 // Perform combined smi check on both operands. |
2453 __ orr(scratch1, left, Operand(right)); | 2493 __ orr(scratch1, left, Operand(right)); |
2454 STATIC_ASSERT(kSmiTag == 0); | 2494 STATIC_ASSERT(kSmiTag == 0); |
2455 __ tst(scratch1, Operand(kSmiTagMask)); | 2495 __ tst(scratch1, Operand(kSmiTagMask)); |
2456 __ b(ne, ¬_smis); | 2496 __ b(ne, ¬_smis); |
2457 | 2497 |
2458 __ add(right, right, Operand(left), SetCC); // Add optimistically. | 2498 GenerateOptimisticSmiOperation(masm); |
2459 | |
2460 // Return smi result if no overflow (r0 is the result). | |
2461 ASSERT(right.is(r0)); | |
2462 __ Ret(vc); | |
2463 | |
2464 // Result is not a smi. Revert the optimistic add. | |
2465 __ sub(right, right, Operand(left)); | |
2466 | 2499 |
2467 // If heap number results are possible generate the result in an allocated | 2500 // If heap number results are possible generate the result in an allocated |
2468 // heap number. | 2501 // heap number. |
2469 if (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) { | 2502 if (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) { |
2470 FloatingPointHelper::Destination destination = | 2503 FloatingPointHelper::Destination destination = |
2471 CpuFeatures::IsSupported(VFP3) && Token::MOD != op_ ? | 2504 CpuFeatures::IsSupported(VFP3) && Token::MOD != op_ ? |
2472 FloatingPointHelper::kVFPRegisters : | 2505 FloatingPointHelper::kVFPRegisters : |
2473 FloatingPointHelper::kCoreRegisters; | 2506 FloatingPointHelper::kCoreRegisters; |
2474 | 2507 |
2475 Register heap_number_map = r6; | 2508 Register heap_number_map = r6; |
2476 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); | 2509 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
2477 | 2510 |
2478 // Allocate new heap number for result. | 2511 // Allocate new heap number for result. |
2479 Register heap_number = r5; | 2512 Register heap_number = r5; |
2480 __ AllocateHeapNumber( | 2513 __ AllocateHeapNumber( |
2481 heap_number, scratch1, scratch2, heap_number_map, gc_required); | 2514 heap_number, scratch1, scratch2, heap_number_map, gc_required); |
2482 | 2515 |
2483 // Load the smis. | 2516 // Load the smis. |
2484 FloatingPointHelper::LoadSmis(masm, destination, scratch1, scratch2); | 2517 FloatingPointHelper::LoadSmis(masm, destination, scratch1, scratch2); |
2485 | 2518 |
2486 // Calculate the result. | 2519 // Calculate the result. |
2487 if (destination == FloatingPointHelper::kVFPRegisters) { | 2520 if (destination == FloatingPointHelper::kVFPRegisters) { |
2488 // Using VFP registers: | 2521 // Using VFP registers: |
2489 // d6: Left value | 2522 // d6: Left value |
2490 // d7: Right value | 2523 // d7: Right value |
2491 CpuFeatures::Scope scope(VFP3); | 2524 CpuFeatures::Scope scope(VFP3); |
2492 __ vadd(d5, d6, d7); | 2525 GenerateVFPOperation(masm); |
2493 | 2526 |
2494 __ sub(r0, heap_number, Operand(kHeapObjectTag)); | 2527 __ sub(r0, heap_number, Operand(kHeapObjectTag)); |
2495 __ vstr(d5, r0, HeapNumber::kValueOffset); | 2528 __ vstr(d5, r0, HeapNumber::kValueOffset); |
2496 __ add(r0, r0, Operand(kHeapObjectTag)); | 2529 __ add(r0, r0, Operand(kHeapObjectTag)); |
2497 __ Ret(); | 2530 __ Ret(); |
2498 } else { | 2531 } else { |
2499 // Using core registers: | 2532 // Using core registers: |
2500 // r0: Left value (least significant part of mantissa). | 2533 // r0: Left value (least significant part of mantissa). |
2501 // r1: Left value (sign, exponent, top of mantissa). | 2534 // r1: Left value (sign, exponent, top of mantissa). |
2502 // r2: Right value (least significant part of mantissa). | 2535 // r2: Right value (least significant part of mantissa). |
(...skipping 20 matching lines...) Expand all Loading... | |
2523 __ pop(pc); | 2556 __ pop(pc); |
2524 } | 2557 } |
2525 } | 2558 } |
2526 __ bind(¬_smis); | 2559 __ bind(¬_smis); |
2527 } | 2560 } |
2528 | 2561 |
2529 | 2562 |
2530 void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { | 2563 void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { |
2531 Label not_smis, call_runtime; | 2564 Label not_smis, call_runtime; |
2532 | 2565 |
2533 ASSERT(op_ == Token::ADD); | 2566 ASSERT(op_ == Token::ADD || op_ == Token::SUB); |
2534 | 2567 |
2535 if (result_type_ == TRBinaryOpIC::UNINITIALIZED || | 2568 if (result_type_ == TRBinaryOpIC::UNINITIALIZED || |
2536 result_type_ == TRBinaryOpIC::SMI) { | 2569 result_type_ == TRBinaryOpIC::SMI) { |
2537 // Only allow smi results. | 2570 // Only allow smi results. |
2538 GenerateSmiCode(masm, NULL, NO_HEAPNUMBER_RESULTS); | 2571 GenerateSmiCode(masm, NULL, NO_HEAPNUMBER_RESULTS); |
2539 } else { | 2572 } else { |
2540 // Allow heap number result and don't make a transition if a heap number | 2573 // Allow heap number result and don't make a transition if a heap number |
2541 // cannot be allocated. | 2574 // cannot be allocated. |
2542 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); | 2575 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); |
2543 } | 2576 } |
(...skipping 11 matching lines...) Expand all Loading... | |
2555 ASSERT(operands_type_ == TRBinaryOpIC::STRING); | 2588 ASSERT(operands_type_ == TRBinaryOpIC::STRING); |
2556 ASSERT(op_ == Token::ADD); | 2589 ASSERT(op_ == Token::ADD); |
2557 // Try to add arguments as strings, otherwise, transition to the generic | 2590 // Try to add arguments as strings, otherwise, transition to the generic |
2558 // TRBinaryOpIC type. | 2591 // TRBinaryOpIC type. |
2559 GenerateAddStrings(masm); | 2592 GenerateAddStrings(masm); |
2560 GenerateTypeTransition(masm); | 2593 GenerateTypeTransition(masm); |
2561 } | 2594 } |
2562 | 2595 |
2563 | 2596 |
2564 void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { | 2597 void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { |
2565 ASSERT(op_ == Token::ADD); | 2598 ASSERT(op_ == Token::ADD || op_ == Token::SUB); |
2566 | 2599 |
2567 ASSERT(operands_type_ == TRBinaryOpIC::INT32); | 2600 ASSERT(operands_type_ == TRBinaryOpIC::INT32); |
2568 | 2601 |
2569 GenerateTypeTransition(masm); | 2602 GenerateTypeTransition(masm); |
2570 } | 2603 } |
2571 | 2604 |
2572 | 2605 |
2573 void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { | 2606 void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { |
2574 ASSERT(op_ == Token::ADD); | 2607 ASSERT(op_ == Token::ADD || op_ == Token::SUB); |
2575 | 2608 |
2576 Register scratch1 = r7; | 2609 Register scratch1 = r7; |
2577 Register scratch2 = r9; | 2610 Register scratch2 = r9; |
2578 | 2611 |
2579 Label not_number, call_runtime; | 2612 Label not_number, call_runtime; |
2580 ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER); | 2613 ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER); |
2581 | 2614 |
2582 Register heap_number_map = r6; | 2615 Register heap_number_map = r6; |
2583 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); | 2616 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
2584 | 2617 |
2585 // Load left and right operands into d6 and d7 or r0/r1 and r2/r3 depending on | 2618 // Load left and right operands into d6 and d7 or r0/r1 and r2/r3 depending on |
2586 // whether VFP3 is available. | 2619 // whether VFP3 is available. |
2587 FloatingPointHelper::Destination destination = | 2620 FloatingPointHelper::Destination destination = |
2588 CpuFeatures::IsSupported(VFP3) ? | 2621 CpuFeatures::IsSupported(VFP3) ? |
2589 FloatingPointHelper::kVFPRegisters : | 2622 FloatingPointHelper::kVFPRegisters : |
2590 FloatingPointHelper::kCoreRegisters; | 2623 FloatingPointHelper::kCoreRegisters; |
2591 FloatingPointHelper::LoadOperands(masm, | 2624 FloatingPointHelper::LoadOperands(masm, |
2592 destination, | 2625 destination, |
2593 heap_number_map, | 2626 heap_number_map, |
2594 scratch1, | 2627 scratch1, |
2595 scratch2, | 2628 scratch2, |
2596 ¬_number); | 2629 ¬_number); |
2597 if (destination == FloatingPointHelper::kVFPRegisters) { | 2630 if (destination == FloatingPointHelper::kVFPRegisters) { |
2598 // Use floating point instructions for the binary operation. | 2631 // Use floating point instructions for the binary operation. |
2599 CpuFeatures::Scope scope(VFP3); | 2632 CpuFeatures::Scope scope(VFP3); |
2600 __ vadd(d5, d6, d7); | 2633 GenerateVFPOperation(masm); |
2601 | 2634 |
2602 // Get a heap number object for the result - might be left or right if one | 2635 // Get a heap number object for the result - might be left or right if one |
2603 // of these are overwritable. | 2636 // of these are overwritable. |
2604 GenerateHeapResultAllocation( | 2637 GenerateHeapResultAllocation( |
2605 masm, r4, heap_number_map, scratch1, scratch2, &call_runtime); | 2638 masm, r4, heap_number_map, scratch1, scratch2, &call_runtime); |
2606 | 2639 |
2607 // Fill the result into the allocated heap number and return. | 2640 // Fill the result into the allocated heap number and return. |
2608 __ sub(r0, r4, Operand(kHeapObjectTag)); | 2641 __ sub(r0, r4, Operand(kHeapObjectTag)); |
2609 __ vstr(d5, r0, HeapNumber::kValueOffset); | 2642 __ vstr(d5, r0, HeapNumber::kValueOffset); |
2610 __ add(r0, r0, Operand(kHeapObjectTag)); | 2643 __ add(r0, r0, Operand(kHeapObjectTag)); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2644 | 2677 |
2645 __ bind(¬_number); | 2678 __ bind(¬_number); |
2646 GenerateTypeTransition(masm); | 2679 GenerateTypeTransition(masm); |
2647 | 2680 |
2648 __ bind(&call_runtime); | 2681 __ bind(&call_runtime); |
2649 GenerateCallRuntime(masm); | 2682 GenerateCallRuntime(masm); |
2650 } | 2683 } |
2651 | 2684 |
2652 | 2685 |
2653 void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) { | 2686 void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) { |
2654 ASSERT(op_ == Token::ADD); | 2687 ASSERT(op_ == Token::ADD || op_ == Token::SUB); |
2655 | 2688 |
2656 Label call_runtime; | 2689 Label call_runtime; |
2657 | 2690 |
2658 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); | 2691 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); |
2659 | 2692 |
2660 // If all else fails, use the runtime system to get the correct | 2693 // If all else fails, use the runtime system to get the correct |
2661 // result. | 2694 // result. |
2662 __ bind(&call_runtime); | 2695 __ bind(&call_runtime); |
2663 | 2696 |
2664 // Try to add strings before calling runtime. | 2697 // Try to add strings before calling runtime. |
(...skipping 23 matching lines...) Expand all Loading... | |
2688 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); | 2721 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); |
2689 GenerateRegisterArgsPush(masm); | 2722 GenerateRegisterArgsPush(masm); |
2690 __ TailCallStub(&string_add_stub); | 2723 __ TailCallStub(&string_add_stub); |
2691 | 2724 |
2692 // At least one argument is not a string. | 2725 // At least one argument is not a string. |
2693 __ bind(&call_runtime); | 2726 __ bind(&call_runtime); |
2694 } | 2727 } |
2695 | 2728 |
2696 | 2729 |
2697 void TypeRecordingBinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) { | 2730 void TypeRecordingBinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) { |
2731 GenerateRegisterArgsPush(masm); | |
2698 switch (op_) { | 2732 switch (op_) { |
2699 case Token::ADD: | 2733 case Token::ADD: |
2700 GenerateRegisterArgsPush(masm); | |
2701 __ InvokeBuiltin(Builtins::ADD, JUMP_JS); | 2734 __ InvokeBuiltin(Builtins::ADD, JUMP_JS); |
2702 break; | 2735 break; |
2736 case Token::SUB: | |
2737 __ InvokeBuiltin(Builtins::SUB, JUMP_JS); | |
2738 break; | |
2703 default: | 2739 default: |
2704 UNREACHABLE(); | 2740 UNREACHABLE(); |
2705 } | 2741 } |
2706 } | 2742 } |
2707 | 2743 |
2708 | 2744 |
2709 void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation( | 2745 void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation( |
2710 MacroAssembler* masm, | 2746 MacroAssembler* masm, |
2711 Register result, | 2747 Register result, |
2712 Register heap_number_map, | 2748 Register heap_number_map, |
(...skipping 2907 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5620 __ pop(r1); | 5656 __ pop(r1); |
5621 __ Jump(r2); | 5657 __ Jump(r2); |
5622 } | 5658 } |
5623 | 5659 |
5624 | 5660 |
5625 #undef __ | 5661 #undef __ |
5626 | 5662 |
5627 } } // namespace v8::internal | 5663 } } // namespace v8::internal |
5628 | 5664 |
5629 #endif // V8_TARGET_ARCH_ARM | 5665 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |