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 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
477 translation->StoreLiteral(src_index); | 477 translation->StoreLiteral(src_index); |
478 } else { | 478 } else { |
479 UNREACHABLE(); | 479 UNREACHABLE(); |
480 } | 480 } |
481 } | 481 } |
482 | 482 |
483 | 483 |
484 void LCodeGen::CallCode(Handle<Code> code, | 484 void LCodeGen::CallCode(Handle<Code> code, |
485 RelocInfo::Mode mode, | 485 RelocInfo::Mode mode, |
486 LInstruction* instr) { | 486 LInstruction* instr) { |
| 487 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); |
| 488 } |
| 489 |
| 490 |
| 491 void LCodeGen::CallCodeGeneric(Handle<Code> code, |
| 492 RelocInfo::Mode mode, |
| 493 LInstruction* instr, |
| 494 SafepointMode safepoint_mode) { |
487 ASSERT(instr != NULL); | 495 ASSERT(instr != NULL); |
488 LPointerMap* pointers = instr->pointer_map(); | 496 LPointerMap* pointers = instr->pointer_map(); |
489 RecordPosition(pointers->position()); | 497 RecordPosition(pointers->position()); |
490 __ Call(code, mode); | 498 __ Call(code, mode); |
491 RegisterLazyDeoptimization(instr); | 499 RegisterLazyDeoptimization(instr, safepoint_mode); |
492 } | 500 } |
493 | 501 |
494 | 502 |
495 void LCodeGen::CallRuntime(const Runtime::Function* function, | 503 void LCodeGen::CallRuntime(const Runtime::Function* function, |
496 int num_arguments, | 504 int num_arguments, |
497 LInstruction* instr) { | 505 LInstruction* instr) { |
498 ASSERT(instr != NULL); | 506 ASSERT(instr != NULL); |
499 LPointerMap* pointers = instr->pointer_map(); | 507 LPointerMap* pointers = instr->pointer_map(); |
500 ASSERT(pointers != NULL); | 508 ASSERT(pointers != NULL); |
501 RecordPosition(pointers->position()); | 509 RecordPosition(pointers->position()); |
502 | 510 |
503 __ CallRuntime(function, num_arguments); | 511 __ CallRuntime(function, num_arguments); |
504 RegisterLazyDeoptimization(instr); | 512 RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT); |
505 } | 513 } |
506 | 514 |
507 | 515 |
508 void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr) { | 516 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, |
| 517 int argc, |
| 518 LInstruction* instr) { |
| 519 __ CallRuntimeSaveDoubles(id); |
| 520 RecordSafepointWithRegisters( |
| 521 instr->pointer_map(), argc, Safepoint::kNoDeoptimizationIndex); |
| 522 } |
| 523 |
| 524 |
| 525 void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr, |
| 526 SafepointMode safepoint_mode) { |
509 // Create the environment to bailout to. If the call has side effects | 527 // Create the environment to bailout to. If the call has side effects |
510 // execution has to continue after the call otherwise execution can continue | 528 // execution has to continue after the call otherwise execution can continue |
511 // from a previous bailout point repeating the call. | 529 // from a previous bailout point repeating the call. |
512 LEnvironment* deoptimization_environment; | 530 LEnvironment* deoptimization_environment; |
513 if (instr->HasDeoptimizationEnvironment()) { | 531 if (instr->HasDeoptimizationEnvironment()) { |
514 deoptimization_environment = instr->deoptimization_environment(); | 532 deoptimization_environment = instr->deoptimization_environment(); |
515 } else { | 533 } else { |
516 deoptimization_environment = instr->environment(); | 534 deoptimization_environment = instr->environment(); |
517 } | 535 } |
518 | 536 |
519 RegisterEnvironmentForDeoptimization(deoptimization_environment); | 537 RegisterEnvironmentForDeoptimization(deoptimization_environment); |
520 RecordSafepoint(instr->pointer_map(), | 538 if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { |
521 deoptimization_environment->deoptimization_index()); | 539 RecordSafepoint(instr->pointer_map(), |
| 540 deoptimization_environment->deoptimization_index()); |
| 541 } else { |
| 542 ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
| 543 RecordSafepointWithRegisters( |
| 544 instr->pointer_map(), |
| 545 0, |
| 546 deoptimization_environment->deoptimization_index()); |
| 547 } |
522 } | 548 } |
523 | 549 |
524 | 550 |
525 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment) { | 551 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment) { |
526 if (!environment->HasBeenRegistered()) { | 552 if (!environment->HasBeenRegistered()) { |
527 // Physical stack frame layout: | 553 // Physical stack frame layout: |
528 // -x ............. -4 0 ..................................... y | 554 // -x ............. -4 0 ..................................... y |
529 // [incoming arguments] [spill slots] [pushed outgoing arguments] | 555 // [incoming arguments] [spill slots] [pushed outgoing arguments] |
530 | 556 |
531 // Layout of the environment: | 557 // Layout of the environment: |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
643 | 669 |
644 inlined_function_count_ = deoptimization_literals_.length(); | 670 inlined_function_count_ = deoptimization_literals_.length(); |
645 } | 671 } |
646 | 672 |
647 | 673 |
648 void LCodeGen::RecordSafepoint( | 674 void LCodeGen::RecordSafepoint( |
649 LPointerMap* pointers, | 675 LPointerMap* pointers, |
650 Safepoint::Kind kind, | 676 Safepoint::Kind kind, |
651 int arguments, | 677 int arguments, |
652 int deoptimization_index) { | 678 int deoptimization_index) { |
| 679 ASSERT(expected_safepoint_kind_ == kind); |
| 680 |
653 const ZoneList<LOperand*>* operands = pointers->operands(); | 681 const ZoneList<LOperand*>* operands = pointers->operands(); |
654 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), | 682 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), |
655 kind, arguments, deoptimization_index); | 683 kind, arguments, deoptimization_index); |
656 for (int i = 0; i < operands->length(); i++) { | 684 for (int i = 0; i < operands->length(); i++) { |
657 LOperand* pointer = operands->at(i); | 685 LOperand* pointer = operands->at(i); |
658 if (pointer->IsStackSlot()) { | 686 if (pointer->IsStackSlot()) { |
659 safepoint.DefinePointerSlot(pointer->index()); | 687 safepoint.DefinePointerSlot(pointer->index()); |
660 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { | 688 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { |
661 safepoint.DefinePointerRegister(ToRegister(pointer)); | 689 safepoint.DefinePointerRegister(ToRegister(pointer)); |
662 } | 690 } |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1008 __ bind(&done); | 1036 __ bind(&done); |
1009 } | 1037 } |
1010 | 1038 |
1011 | 1039 |
1012 template<int T> | 1040 template<int T> |
1013 void LCodeGen::DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr, | 1041 void LCodeGen::DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr, |
1014 Token::Value op) { | 1042 Token::Value op) { |
1015 Register left = ToRegister(instr->InputAt(0)); | 1043 Register left = ToRegister(instr->InputAt(0)); |
1016 Register right = ToRegister(instr->InputAt(1)); | 1044 Register right = ToRegister(instr->InputAt(1)); |
1017 | 1045 |
1018 __ PushSafepointRegistersAndDoubles(); | 1046 PushSafepointRegistersScope scope(this, Safepoint::kWithRegistersAndDoubles); |
1019 // Move left to r1 and right to r0 for the stub call. | 1047 // Move left to r1 and right to r0 for the stub call. |
1020 if (left.is(r1)) { | 1048 if (left.is(r1)) { |
1021 __ Move(r0, right); | 1049 __ Move(r0, right); |
1022 } else if (left.is(r0) && right.is(r1)) { | 1050 } else if (left.is(r0) && right.is(r1)) { |
1023 __ Swap(r0, r1, r2); | 1051 __ Swap(r0, r1, r2); |
1024 } else if (left.is(r0)) { | 1052 } else if (left.is(r0)) { |
1025 ASSERT(!right.is(r1)); | 1053 ASSERT(!right.is(r1)); |
1026 __ mov(r1, r0); | 1054 __ mov(r1, r0); |
1027 __ mov(r0, right); | 1055 __ mov(r0, right); |
1028 } else { | 1056 } else { |
1029 ASSERT(!left.is(r0) && !right.is(r0)); | 1057 ASSERT(!left.is(r0) && !right.is(r0)); |
1030 __ mov(r0, right); | 1058 __ mov(r0, right); |
1031 __ mov(r1, left); | 1059 __ mov(r1, left); |
1032 } | 1060 } |
1033 TypeRecordingBinaryOpStub stub(op, OVERWRITE_LEFT); | 1061 TypeRecordingBinaryOpStub stub(op, OVERWRITE_LEFT); |
1034 __ CallStub(&stub); | 1062 __ CallStub(&stub); |
1035 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), | 1063 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), |
1036 0, | 1064 0, |
1037 Safepoint::kNoDeoptimizationIndex); | 1065 Safepoint::kNoDeoptimizationIndex); |
1038 // Overwrite the stored value of r0 with the result of the stub. | 1066 // Overwrite the stored value of r0 with the result of the stub. |
1039 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); | 1067 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); |
1040 __ PopSafepointRegistersAndDoubles(); | |
1041 } | 1068 } |
1042 | 1069 |
1043 | 1070 |
1044 void LCodeGen::DoMulI(LMulI* instr) { | 1071 void LCodeGen::DoMulI(LMulI* instr) { |
1045 Register scratch = scratch0(); | 1072 Register scratch = scratch0(); |
1046 Register left = ToRegister(instr->InputAt(0)); | 1073 Register left = ToRegister(instr->InputAt(0)); |
1047 Register right = EmitLoadRegister(instr->InputAt(1), scratch); | 1074 Register right = EmitLoadRegister(instr->InputAt(1), scratch); |
1048 | 1075 |
1049 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && | 1076 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && |
1050 !instr->InputAt(1)->IsConstantOperand()) { | 1077 !instr->InputAt(1)->IsConstantOperand()) { |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1453 __ jmp(deferred_stack_check->entry()); | 1480 __ jmp(deferred_stack_check->entry()); |
1454 deferred_stack_check->SetExit(chunk_->GetAssemblyLabel(block)); | 1481 deferred_stack_check->SetExit(chunk_->GetAssemblyLabel(block)); |
1455 } else { | 1482 } else { |
1456 __ jmp(chunk_->GetAssemblyLabel(block)); | 1483 __ jmp(chunk_->GetAssemblyLabel(block)); |
1457 } | 1484 } |
1458 } | 1485 } |
1459 } | 1486 } |
1460 | 1487 |
1461 | 1488 |
1462 void LCodeGen::DoDeferredStackCheck(LGoto* instr) { | 1489 void LCodeGen::DoDeferredStackCheck(LGoto* instr) { |
1463 __ PushSafepointRegisters(); | 1490 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
1464 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); | 1491 CallRuntimeFromDeferred(Runtime::kStackGuard, 0, instr); |
1465 RecordSafepointWithRegisters( | |
1466 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | |
1467 __ PopSafepointRegisters(); | |
1468 } | 1492 } |
1469 | 1493 |
1470 | 1494 |
1471 void LCodeGen::DoGoto(LGoto* instr) { | 1495 void LCodeGen::DoGoto(LGoto* instr) { |
1472 class DeferredStackCheck: public LDeferredCode { | 1496 class DeferredStackCheck: public LDeferredCode { |
1473 public: | 1497 public: |
1474 DeferredStackCheck(LCodeGen* codegen, LGoto* instr) | 1498 DeferredStackCheck(LCodeGen* codegen, LGoto* instr) |
1475 : LDeferredCode(codegen), instr_(instr) { } | 1499 : LDeferredCode(codegen), instr_(instr) { } |
1476 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } | 1500 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } |
1477 private: | 1501 private: |
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2058 | 2082 |
2059 InstanceofStub::Flags flags = InstanceofStub::kNoFlags; | 2083 InstanceofStub::Flags flags = InstanceofStub::kNoFlags; |
2060 flags = static_cast<InstanceofStub::Flags>( | 2084 flags = static_cast<InstanceofStub::Flags>( |
2061 flags | InstanceofStub::kArgsInRegisters); | 2085 flags | InstanceofStub::kArgsInRegisters); |
2062 flags = static_cast<InstanceofStub::Flags>( | 2086 flags = static_cast<InstanceofStub::Flags>( |
2063 flags | InstanceofStub::kCallSiteInlineCheck); | 2087 flags | InstanceofStub::kCallSiteInlineCheck); |
2064 flags = static_cast<InstanceofStub::Flags>( | 2088 flags = static_cast<InstanceofStub::Flags>( |
2065 flags | InstanceofStub::kReturnTrueFalseObject); | 2089 flags | InstanceofStub::kReturnTrueFalseObject); |
2066 InstanceofStub stub(flags); | 2090 InstanceofStub stub(flags); |
2067 | 2091 |
2068 __ PushSafepointRegisters(); | 2092 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
2069 | 2093 |
2070 // Get the temp register reserved by the instruction. This needs to be r4 as | 2094 // Get the temp register reserved by the instruction. This needs to be r4 as |
2071 // its slot of the pushing of safepoint registers is used to communicate the | 2095 // its slot of the pushing of safepoint registers is used to communicate the |
2072 // offset to the location of the map check. | 2096 // offset to the location of the map check. |
2073 Register temp = ToRegister(instr->TempAt(0)); | 2097 Register temp = ToRegister(instr->TempAt(0)); |
2074 ASSERT(temp.is(r4)); | 2098 ASSERT(temp.is(r4)); |
2075 __ mov(InstanceofStub::right(), Operand(instr->function())); | 2099 __ mov(InstanceofStub::right(), Operand(instr->function())); |
2076 static const int kAdditionalDelta = 4; | 2100 static const int kAdditionalDelta = 4; |
2077 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; | 2101 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; |
2078 Label before_push_delta; | 2102 Label before_push_delta; |
2079 __ bind(&before_push_delta); | 2103 __ bind(&before_push_delta); |
2080 __ BlockConstPoolFor(kAdditionalDelta); | 2104 __ BlockConstPoolFor(kAdditionalDelta); |
2081 __ mov(temp, Operand(delta * kPointerSize)); | 2105 __ mov(temp, Operand(delta * kPointerSize)); |
2082 __ StoreToSafepointRegisterSlot(temp, temp); | 2106 __ StoreToSafepointRegisterSlot(temp, temp); |
2083 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 2107 CallCodeGeneric(stub.GetCode(), |
| 2108 RelocInfo::CODE_TARGET, |
| 2109 instr, |
| 2110 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
2084 // Put the result value into the result register slot and | 2111 // Put the result value into the result register slot and |
2085 // restore all registers. | 2112 // restore all registers. |
2086 __ StoreToSafepointRegisterSlot(result, result); | 2113 __ StoreToSafepointRegisterSlot(result, result); |
2087 | |
2088 __ PopSafepointRegisters(); | |
2089 } | 2114 } |
2090 | 2115 |
2091 | 2116 |
2092 static Condition ComputeCompareCondition(Token::Value op) { | 2117 static Condition ComputeCompareCondition(Token::Value op) { |
2093 switch (op) { | 2118 switch (op) { |
2094 case Token::EQ_STRICT: | 2119 case Token::EQ_STRICT: |
2095 case Token::EQ: | 2120 case Token::EQ: |
2096 return eq; | 2121 return eq; |
2097 case Token::LT: | 2122 case Token::LT: |
2098 return lt; | 2123 return lt; |
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2632 } | 2657 } |
2633 | 2658 |
2634 LPointerMap* pointers = instr->pointer_map(); | 2659 LPointerMap* pointers = instr->pointer_map(); |
2635 RecordPosition(pointers->position()); | 2660 RecordPosition(pointers->position()); |
2636 | 2661 |
2637 // Invoke function. | 2662 // Invoke function. |
2638 __ ldr(ip, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | 2663 __ ldr(ip, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); |
2639 __ Call(ip); | 2664 __ Call(ip); |
2640 | 2665 |
2641 // Setup deoptimization. | 2666 // Setup deoptimization. |
2642 RegisterLazyDeoptimization(instr); | 2667 RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT); |
2643 | 2668 |
2644 // Restore context. | 2669 // Restore context. |
2645 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2670 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2646 } | 2671 } |
2647 | 2672 |
2648 | 2673 |
2649 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 2674 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
2650 ASSERT(ToRegister(instr->result()).is(r0)); | 2675 ASSERT(ToRegister(instr->result()).is(r0)); |
2651 __ mov(r1, Operand(instr->function())); | 2676 __ mov(r1, Operand(instr->function())); |
2652 CallKnownFunction(instr->function(), instr->arity(), instr); | 2677 CallKnownFunction(instr->function(), instr->arity(), instr); |
(...skipping 17 matching lines...) Expand all Loading... |
2670 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | 2695 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
2671 // Check the sign of the argument. If the argument is positive, just | 2696 // Check the sign of the argument. If the argument is positive, just |
2672 // return it. We do not need to patch the stack since |input| and | 2697 // return it. We do not need to patch the stack since |input| and |
2673 // |result| are the same register and |input| would be restored | 2698 // |result| are the same register and |input| would be restored |
2674 // unchanged by popping safepoint registers. | 2699 // unchanged by popping safepoint registers. |
2675 __ tst(exponent, Operand(HeapNumber::kSignMask)); | 2700 __ tst(exponent, Operand(HeapNumber::kSignMask)); |
2676 __ b(eq, &done); | 2701 __ b(eq, &done); |
2677 | 2702 |
2678 // Input is negative. Reverse its sign. | 2703 // Input is negative. Reverse its sign. |
2679 // Preserve the value of all registers. | 2704 // Preserve the value of all registers. |
2680 __ PushSafepointRegisters(); | 2705 { |
| 2706 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
2681 | 2707 |
2682 // Registers were saved at the safepoint, so we can use | 2708 // Registers were saved at the safepoint, so we can use |
2683 // many scratch registers. | 2709 // many scratch registers. |
2684 Register tmp1 = input.is(r1) ? r0 : r1; | 2710 Register tmp1 = input.is(r1) ? r0 : r1; |
2685 Register tmp2 = input.is(r2) ? r0 : r2; | 2711 Register tmp2 = input.is(r2) ? r0 : r2; |
2686 Register tmp3 = input.is(r3) ? r0 : r3; | 2712 Register tmp3 = input.is(r3) ? r0 : r3; |
2687 Register tmp4 = input.is(r4) ? r0 : r4; | 2713 Register tmp4 = input.is(r4) ? r0 : r4; |
2688 | 2714 |
2689 // exponent: floating point exponent value. | 2715 // exponent: floating point exponent value. |
2690 | 2716 |
2691 Label allocated, slow; | 2717 Label allocated, slow; |
2692 __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex); | 2718 __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex); |
2693 __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow); | 2719 __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow); |
2694 __ b(&allocated); | 2720 __ b(&allocated); |
2695 | 2721 |
2696 // Slow case: Call the runtime system to do the number allocation. | 2722 // Slow case: Call the runtime system to do the number allocation. |
2697 __ bind(&slow); | 2723 __ bind(&slow); |
2698 | 2724 |
2699 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 2725 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
2700 RecordSafepointWithRegisters( | 2726 // Set the pointer to the new heap number in tmp. |
2701 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | 2727 if (!tmp1.is(r0)) __ mov(tmp1, Operand(r0)); |
2702 // Set the pointer to the new heap number in tmp. | 2728 // Restore input_reg after call to runtime. |
2703 if (!tmp1.is(r0)) __ mov(tmp1, Operand(r0)); | 2729 __ LoadFromSafepointRegisterSlot(input, input); |
2704 // Restore input_reg after call to runtime. | 2730 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
2705 __ LoadFromSafepointRegisterSlot(input, input); | |
2706 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | |
2707 | 2731 |
2708 __ bind(&allocated); | 2732 __ bind(&allocated); |
2709 // exponent: floating point exponent value. | 2733 // exponent: floating point exponent value. |
2710 // tmp1: allocated heap number. | 2734 // tmp1: allocated heap number. |
2711 __ bic(exponent, exponent, Operand(HeapNumber::kSignMask)); | 2735 __ bic(exponent, exponent, Operand(HeapNumber::kSignMask)); |
2712 __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset)); | 2736 __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset)); |
2713 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); | 2737 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); |
2714 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); | 2738 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); |
2715 | 2739 |
2716 __ StoreToSafepointRegisterSlot(tmp1, input); | 2740 __ StoreToSafepointRegisterSlot(tmp1, input); |
2717 __ PopSafepointRegisters(); | 2741 } |
2718 | 2742 |
2719 __ bind(&done); | 2743 __ bind(&done); |
2720 } | 2744 } |
2721 | 2745 |
2722 | 2746 |
2723 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { | 2747 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { |
2724 Register input = ToRegister(instr->InputAt(0)); | 2748 Register input = ToRegister(instr->InputAt(0)); |
2725 __ cmp(input, Operand(0)); | 2749 __ cmp(input, Operand(0)); |
2726 // We can make rsb conditional because the previous cmp instruction | 2750 // We can make rsb conditional because the previous cmp instruction |
2727 // will clear the V (overflow) flag and rsb won't set this flag | 2751 // will clear the V (overflow) flag and rsb won't set this flag |
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3245 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { | 3269 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { |
3246 Register string = ToRegister(instr->string()); | 3270 Register string = ToRegister(instr->string()); |
3247 Register result = ToRegister(instr->result()); | 3271 Register result = ToRegister(instr->result()); |
3248 Register scratch = scratch0(); | 3272 Register scratch = scratch0(); |
3249 | 3273 |
3250 // TODO(3095996): Get rid of this. For now, we need to make the | 3274 // TODO(3095996): Get rid of this. For now, we need to make the |
3251 // result register contain a valid pointer because it is already | 3275 // result register contain a valid pointer because it is already |
3252 // contained in the register pointer map. | 3276 // contained in the register pointer map. |
3253 __ mov(result, Operand(0)); | 3277 __ mov(result, Operand(0)); |
3254 | 3278 |
3255 __ PushSafepointRegisters(); | 3279 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
3256 __ push(string); | 3280 __ push(string); |
3257 // Push the index as a smi. This is safe because of the checks in | 3281 // Push the index as a smi. This is safe because of the checks in |
3258 // DoStringCharCodeAt above. | 3282 // DoStringCharCodeAt above. |
3259 if (instr->index()->IsConstantOperand()) { | 3283 if (instr->index()->IsConstantOperand()) { |
3260 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 3284 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
3261 __ mov(scratch, Operand(Smi::FromInt(const_index))); | 3285 __ mov(scratch, Operand(Smi::FromInt(const_index))); |
3262 __ push(scratch); | 3286 __ push(scratch); |
3263 } else { | 3287 } else { |
3264 Register index = ToRegister(instr->index()); | 3288 Register index = ToRegister(instr->index()); |
3265 __ SmiTag(index); | 3289 __ SmiTag(index); |
3266 __ push(index); | 3290 __ push(index); |
3267 } | 3291 } |
3268 __ CallRuntimeSaveDoubles(Runtime::kStringCharCodeAt); | 3292 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); |
3269 RecordSafepointWithRegisters( | |
3270 instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex); | |
3271 if (FLAG_debug_code) { | 3293 if (FLAG_debug_code) { |
3272 __ AbortIfNotSmi(r0); | 3294 __ AbortIfNotSmi(r0); |
3273 } | 3295 } |
3274 __ SmiUntag(r0); | 3296 __ SmiUntag(r0); |
3275 __ StoreToSafepointRegisterSlot(r0, result); | 3297 __ StoreToSafepointRegisterSlot(r0, result); |
3276 __ PopSafepointRegisters(); | |
3277 } | 3298 } |
3278 | 3299 |
3279 | 3300 |
3280 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { | 3301 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
3281 class DeferredStringCharFromCode: public LDeferredCode { | 3302 class DeferredStringCharFromCode: public LDeferredCode { |
3282 public: | 3303 public: |
3283 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) | 3304 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) |
3284 : LDeferredCode(codegen), instr_(instr) { } | 3305 : LDeferredCode(codegen), instr_(instr) { } |
3285 virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } | 3306 virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } |
3286 private: | 3307 private: |
(...skipping 22 matching lines...) Expand all Loading... |
3309 | 3330 |
3310 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { | 3331 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { |
3311 Register char_code = ToRegister(instr->char_code()); | 3332 Register char_code = ToRegister(instr->char_code()); |
3312 Register result = ToRegister(instr->result()); | 3333 Register result = ToRegister(instr->result()); |
3313 | 3334 |
3314 // TODO(3095996): Get rid of this. For now, we need to make the | 3335 // TODO(3095996): Get rid of this. For now, we need to make the |
3315 // result register contain a valid pointer because it is already | 3336 // result register contain a valid pointer because it is already |
3316 // contained in the register pointer map. | 3337 // contained in the register pointer map. |
3317 __ mov(result, Operand(0)); | 3338 __ mov(result, Operand(0)); |
3318 | 3339 |
3319 __ PushSafepointRegisters(); | 3340 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
3320 __ SmiTag(char_code); | 3341 __ SmiTag(char_code); |
3321 __ push(char_code); | 3342 __ push(char_code); |
3322 __ CallRuntimeSaveDoubles(Runtime::kCharFromCode); | 3343 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); |
3323 RecordSafepointWithRegisters( | |
3324 instr->pointer_map(), 1, Safepoint::kNoDeoptimizationIndex); | |
3325 __ StoreToSafepointRegisterSlot(r0, result); | 3344 __ StoreToSafepointRegisterSlot(r0, result); |
3326 __ PopSafepointRegisters(); | |
3327 } | 3345 } |
3328 | 3346 |
3329 | 3347 |
3330 void LCodeGen::DoStringLength(LStringLength* instr) { | 3348 void LCodeGen::DoStringLength(LStringLength* instr) { |
3331 Register string = ToRegister(instr->InputAt(0)); | 3349 Register string = ToRegister(instr->InputAt(0)); |
3332 Register result = ToRegister(instr->result()); | 3350 Register result = ToRegister(instr->result()); |
3333 __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); | 3351 __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); |
3334 } | 3352 } |
3335 | 3353 |
3336 | 3354 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3372 } | 3390 } |
3373 | 3391 |
3374 | 3392 |
3375 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { | 3393 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { |
3376 Label slow; | 3394 Label slow; |
3377 Register reg = ToRegister(instr->InputAt(0)); | 3395 Register reg = ToRegister(instr->InputAt(0)); |
3378 DoubleRegister dbl_scratch = d0; | 3396 DoubleRegister dbl_scratch = d0; |
3379 SwVfpRegister flt_scratch = s0; | 3397 SwVfpRegister flt_scratch = s0; |
3380 | 3398 |
3381 // Preserve the value of all registers. | 3399 // Preserve the value of all registers. |
3382 __ PushSafepointRegisters(); | 3400 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
3383 | 3401 |
3384 // There was overflow, so bits 30 and 31 of the original integer | 3402 // There was overflow, so bits 30 and 31 of the original integer |
3385 // disagree. Try to allocate a heap number in new space and store | 3403 // disagree. Try to allocate a heap number in new space and store |
3386 // the value in there. If that fails, call the runtime system. | 3404 // the value in there. If that fails, call the runtime system. |
3387 Label done; | 3405 Label done; |
3388 __ SmiUntag(reg); | 3406 __ SmiUntag(reg); |
3389 __ eor(reg, reg, Operand(0x80000000)); | 3407 __ eor(reg, reg, Operand(0x80000000)); |
3390 __ vmov(flt_scratch, reg); | 3408 __ vmov(flt_scratch, reg); |
3391 __ vcvt_f64_s32(dbl_scratch, flt_scratch); | 3409 __ vcvt_f64_s32(dbl_scratch, flt_scratch); |
3392 if (FLAG_inline_new) { | 3410 if (FLAG_inline_new) { |
3393 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); | 3411 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); |
3394 __ AllocateHeapNumber(r5, r3, r4, r6, &slow); | 3412 __ AllocateHeapNumber(r5, r3, r4, r6, &slow); |
3395 if (!reg.is(r5)) __ mov(reg, r5); | 3413 if (!reg.is(r5)) __ mov(reg, r5); |
3396 __ b(&done); | 3414 __ b(&done); |
3397 } | 3415 } |
3398 | 3416 |
3399 // Slow case: Call the runtime system to do the number allocation. | 3417 // Slow case: Call the runtime system to do the number allocation. |
3400 __ bind(&slow); | 3418 __ bind(&slow); |
3401 | 3419 |
3402 // TODO(3095996): Put a valid pointer value in the stack slot where the result | 3420 // TODO(3095996): Put a valid pointer value in the stack slot where the result |
3403 // register is stored, as this register is in the pointer map, but contains an | 3421 // register is stored, as this register is in the pointer map, but contains an |
3404 // integer value. | 3422 // integer value. |
3405 __ mov(ip, Operand(0)); | 3423 __ mov(ip, Operand(0)); |
3406 __ StoreToSafepointRegisterSlot(ip, reg); | 3424 __ StoreToSafepointRegisterSlot(ip, reg); |
3407 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 3425 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
3408 RecordSafepointWithRegisters( | |
3409 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | |
3410 if (!reg.is(r0)) __ mov(reg, r0); | 3426 if (!reg.is(r0)) __ mov(reg, r0); |
3411 | 3427 |
3412 // Done. Put the value in dbl_scratch into the value of the allocated heap | 3428 // Done. Put the value in dbl_scratch into the value of the allocated heap |
3413 // number. | 3429 // number. |
3414 __ bind(&done); | 3430 __ bind(&done); |
3415 __ sub(ip, reg, Operand(kHeapObjectTag)); | 3431 __ sub(ip, reg, Operand(kHeapObjectTag)); |
3416 __ vstr(dbl_scratch, ip, HeapNumber::kValueOffset); | 3432 __ vstr(dbl_scratch, ip, HeapNumber::kValueOffset); |
3417 __ StoreToSafepointRegisterSlot(reg, reg); | 3433 __ StoreToSafepointRegisterSlot(reg, reg); |
3418 __ PopSafepointRegisters(); | |
3419 } | 3434 } |
3420 | 3435 |
3421 | 3436 |
3422 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 3437 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
3423 class DeferredNumberTagD: public LDeferredCode { | 3438 class DeferredNumberTagD: public LDeferredCode { |
3424 public: | 3439 public: |
3425 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 3440 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
3426 : LDeferredCode(codegen), instr_(instr) { } | 3441 : LDeferredCode(codegen), instr_(instr) { } |
3427 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 3442 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
3428 private: | 3443 private: |
(...skipping 19 matching lines...) Expand all Loading... |
3448 } | 3463 } |
3449 | 3464 |
3450 | 3465 |
3451 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 3466 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
3452 // TODO(3095996): Get rid of this. For now, we need to make the | 3467 // TODO(3095996): Get rid of this. For now, we need to make the |
3453 // result register contain a valid pointer because it is already | 3468 // result register contain a valid pointer because it is already |
3454 // contained in the register pointer map. | 3469 // contained in the register pointer map. |
3455 Register reg = ToRegister(instr->result()); | 3470 Register reg = ToRegister(instr->result()); |
3456 __ mov(reg, Operand(0)); | 3471 __ mov(reg, Operand(0)); |
3457 | 3472 |
3458 __ PushSafepointRegisters(); | 3473 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
3459 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 3474 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
3460 RecordSafepointWithRegisters( | |
3461 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | |
3462 __ StoreToSafepointRegisterSlot(r0, reg); | 3475 __ StoreToSafepointRegisterSlot(r0, reg); |
3463 __ PopSafepointRegisters(); | |
3464 } | 3476 } |
3465 | 3477 |
3466 | 3478 |
3467 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 3479 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
3468 LOperand* input = instr->InputAt(0); | 3480 LOperand* input = instr->InputAt(0); |
3469 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 3481 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
3470 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 3482 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
3471 __ SmiTag(ToRegister(input)); | 3483 __ SmiTag(ToRegister(input)); |
3472 } | 3484 } |
3473 | 3485 |
(...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4123 ASSERT(!environment->HasBeenRegistered()); | 4135 ASSERT(!environment->HasBeenRegistered()); |
4124 RegisterEnvironmentForDeoptimization(environment); | 4136 RegisterEnvironmentForDeoptimization(environment); |
4125 ASSERT(osr_pc_offset_ == -1); | 4137 ASSERT(osr_pc_offset_ == -1); |
4126 osr_pc_offset_ = masm()->pc_offset(); | 4138 osr_pc_offset_ = masm()->pc_offset(); |
4127 } | 4139 } |
4128 | 4140 |
4129 | 4141 |
4130 #undef __ | 4142 #undef __ |
4131 | 4143 |
4132 } } // namespace v8::internal | 4144 } } // namespace v8::internal |
OLD | NEW |