OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_S390 | 5 #if V8_TARGET_ARCH_S390 |
6 | 6 |
7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 SetVar(arguments, r2, r3, r4); | 302 SetVar(arguments, r2, r3, r4); |
303 } | 303 } |
304 | 304 |
305 if (FLAG_trace) { | 305 if (FLAG_trace) { |
306 __ CallRuntime(Runtime::kTraceEnter); | 306 __ CallRuntime(Runtime::kTraceEnter); |
307 } | 307 } |
308 | 308 |
309 // Visit the declarations and body unless there is an illegal | 309 // Visit the declarations and body unless there is an illegal |
310 // redeclaration. | 310 // redeclaration. |
311 if (scope()->HasIllegalRedeclaration()) { | 311 if (scope()->HasIllegalRedeclaration()) { |
312 Comment cmnt(masm_, "[ Declarations"); | 312 EmitIllegalRedeclaration(); |
313 VisitForEffect(scope()->GetIllegalRedeclaration()); | |
314 | |
315 } else { | 313 } else { |
316 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); | 314 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); |
317 { | 315 { |
318 Comment cmnt(masm_, "[ Declarations"); | 316 Comment cmnt(masm_, "[ Declarations"); |
319 VisitDeclarations(scope()->declarations()); | 317 VisitDeclarations(scope()->declarations()); |
320 } | 318 } |
321 | 319 |
322 // Assert that the declarations do not use ICs. Otherwise the debugger | 320 // Assert that the declarations do not use ICs. Otherwise the debugger |
323 // won't be able to redirect a PC at an IC to the correct IC in newly | 321 // won't be able to redirect a PC at an IC to the correct IC in newly |
324 // recompiled code. | 322 // recompiled code. |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 | 502 |
505 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { | 503 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { |
506 // Immediates cannot be pushed directly. | 504 // Immediates cannot be pushed directly. |
507 __ mov(result_register(), Operand(lit)); | 505 __ mov(result_register(), Operand(lit)); |
508 codegen()->PushOperand(result_register()); | 506 codegen()->PushOperand(result_register()); |
509 } | 507 } |
510 | 508 |
511 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { | 509 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { |
512 codegen()->PrepareForBailoutBeforeSplit(condition(), true, true_label_, | 510 codegen()->PrepareForBailoutBeforeSplit(condition(), true, true_label_, |
513 false_label_); | 511 false_label_); |
514 DCHECK(lit->IsNull() || lit->IsUndefined() || !lit->IsUndetectableObject()); | 512 DCHECK(lit->IsNull() || lit->IsUndefined() || !lit->IsUndetectable()); |
515 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { | 513 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { |
516 if (false_label_ != fall_through_) __ b(false_label_); | 514 if (false_label_ != fall_through_) __ b(false_label_); |
517 } else if (lit->IsTrue() || lit->IsJSObject()) { | 515 } else if (lit->IsTrue() || lit->IsJSObject()) { |
518 if (true_label_ != fall_through_) __ b(true_label_); | 516 if (true_label_ != fall_through_) __ b(true_label_); |
519 } else if (lit->IsString()) { | 517 } else if (lit->IsString()) { |
520 if (String::cast(*lit)->length() == 0) { | 518 if (String::cast(*lit)->length() == 0) { |
521 if (false_label_ != fall_through_) __ b(false_label_); | 519 if (false_label_ != fall_through_) __ b(false_label_); |
522 } else { | 520 } else { |
523 if (true_label_ != fall_through_) __ b(true_label_); | 521 if (true_label_ != fall_through_) __ b(true_label_); |
524 } | 522 } |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
595 false_label_); | 593 false_label_); |
596 if (flag) { | 594 if (flag) { |
597 if (true_label_ != fall_through_) __ b(true_label_); | 595 if (true_label_ != fall_through_) __ b(true_label_); |
598 } else { | 596 } else { |
599 if (false_label_ != fall_through_) __ b(false_label_); | 597 if (false_label_ != fall_through_) __ b(false_label_); |
600 } | 598 } |
601 } | 599 } |
602 | 600 |
603 void FullCodeGenerator::DoTest(Expression* condition, Label* if_true, | 601 void FullCodeGenerator::DoTest(Expression* condition, Label* if_true, |
604 Label* if_false, Label* fall_through) { | 602 Label* if_false, Label* fall_through) { |
605 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); | 603 Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate()); |
606 CallIC(ic, condition->test_id()); | 604 CallIC(ic, condition->test_id()); |
607 __ CompareRoot(result_register(), Heap::kTrueValueRootIndex); | 605 __ CompareRoot(result_register(), Heap::kTrueValueRootIndex); |
608 Split(eq, if_true, if_false, fall_through); | 606 Split(eq, if_true, if_false, fall_through); |
609 } | 607 } |
610 | 608 |
611 void FullCodeGenerator::Split(Condition cond, Label* if_true, Label* if_false, | 609 void FullCodeGenerator::Split(Condition cond, Label* if_true, Label* if_false, |
612 Label* fall_through) { | 610 Label* fall_through) { |
613 if (if_false == fall_through) { | 611 if (if_false == fall_through) { |
614 __ b(cond, if_true); | 612 __ b(cond, if_true); |
615 } else if (if_true == fall_through) { | 613 } else if (if_true == fall_through) { |
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1001 __ Push(r4, r3, r2); | 999 __ Push(r4, r3, r2); |
1002 __ b(&loop); | 1000 __ b(&loop); |
1003 | 1001 |
1004 __ bind(&no_descriptors); | 1002 __ bind(&no_descriptors); |
1005 __ Drop(1); | 1003 __ Drop(1); |
1006 __ b(&exit); | 1004 __ b(&exit); |
1007 | 1005 |
1008 // We got a fixed array in register r2. Iterate through that. | 1006 // We got a fixed array in register r2. Iterate through that. |
1009 __ bind(&fixed_array); | 1007 __ bind(&fixed_array); |
1010 | 1008 |
1011 int const vector_index = SmiFromSlot(slot)->value(); | |
1012 __ EmitLoadTypeFeedbackVector(r3); | |
1013 __ mov(r4, Operand(TypeFeedbackVector::MegamorphicSentinel(isolate()))); | |
1014 __ StoreP( | |
1015 r4, FieldMemOperand(r3, FixedArray::OffsetOfElementAt(vector_index)), r0); | |
1016 __ LoadSmiLiteral(r3, Smi::FromInt(1)); // Smi(1) indicates slow check | 1009 __ LoadSmiLiteral(r3, Smi::FromInt(1)); // Smi(1) indicates slow check |
1017 __ Push(r3, r2); // Smi and array | 1010 __ Push(r3, r2); // Smi and array |
1018 __ LoadP(r3, FieldMemOperand(r2, FixedArray::kLengthOffset)); | 1011 __ LoadP(r3, FieldMemOperand(r2, FixedArray::kLengthOffset)); |
1019 __ Push(r3); // Fixed array length (as smi). | 1012 __ Push(r3); // Fixed array length (as smi). |
1020 PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS); | 1013 PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS); |
1021 __ LoadSmiLiteral(r2, Smi::FromInt(0)); | 1014 __ LoadSmiLiteral(r2, Smi::FromInt(0)); |
1022 __ Push(r2); // Initial index. | 1015 __ Push(r2); // Initial index. |
1023 | 1016 |
1024 // Generate code for doing the condition check. | 1017 // Generate code for doing the condition check. |
1025 __ bind(&loop); | 1018 __ bind(&loop); |
(...skipping 16 matching lines...) Expand all Loading... |
1042 __ LoadP(r4, MemOperand(sp, 3 * kPointerSize)); | 1035 __ LoadP(r4, MemOperand(sp, 3 * kPointerSize)); |
1043 | 1036 |
1044 // Check if the expected map still matches that of the enumerable. | 1037 // Check if the expected map still matches that of the enumerable. |
1045 // If not, we may have to filter the key. | 1038 // If not, we may have to filter the key. |
1046 Label update_each; | 1039 Label update_each; |
1047 __ LoadP(r3, MemOperand(sp, 4 * kPointerSize)); | 1040 __ LoadP(r3, MemOperand(sp, 4 * kPointerSize)); |
1048 __ LoadP(r6, FieldMemOperand(r3, HeapObject::kMapOffset)); | 1041 __ LoadP(r6, FieldMemOperand(r3, HeapObject::kMapOffset)); |
1049 __ CmpP(r6, r4); | 1042 __ CmpP(r6, r4); |
1050 __ beq(&update_each); | 1043 __ beq(&update_each); |
1051 | 1044 |
1052 // We might get here from TurboFan or Crankshaft when something in the | 1045 // We need to filter the key, record slow-path here. |
1053 // for-in loop body deopts and only now notice in fullcodegen, that we | 1046 int const vector_index = SmiFromSlot(slot)->value(); |
1054 // can now longer use the enum cache, i.e. left fast mode. So better record | |
1055 // this information here, in case we later OSR back into this loop or | |
1056 // reoptimize the whole function w/o rerunning the loop with the slow | |
1057 // mode object in fullcodegen (which would result in a deopt loop). | |
1058 __ EmitLoadTypeFeedbackVector(r2); | 1047 __ EmitLoadTypeFeedbackVector(r2); |
1059 __ mov(r4, Operand(TypeFeedbackVector::MegamorphicSentinel(isolate()))); | 1048 __ mov(r4, Operand(TypeFeedbackVector::MegamorphicSentinel(isolate()))); |
1060 __ StoreP( | 1049 __ StoreP( |
1061 r4, FieldMemOperand(r2, FixedArray::OffsetOfElementAt(vector_index)), r0); | 1050 r4, FieldMemOperand(r2, FixedArray::OffsetOfElementAt(vector_index)), r0); |
1062 | 1051 |
1063 // Convert the entry to a string or (smi) 0 if it isn't a property | 1052 // Convert the entry to a string or (smi) 0 if it isn't a property |
1064 // any more. If the property has been removed while iterating, we | 1053 // any more. If the property has been removed while iterating, we |
1065 // just skip it. | 1054 // just skip it. |
1066 __ Push(r3, r5); // Enumerable and current entry. | 1055 __ Push(r3, r5); // Enumerable and current entry. |
1067 __ CallRuntime(Runtime::kForInFilter); | 1056 __ CallRuntime(Runtime::kForInFilter); |
(...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1763 } | 1752 } |
1764 | 1753 |
1765 void FullCodeGenerator::VisitYield(Yield* expr) { | 1754 void FullCodeGenerator::VisitYield(Yield* expr) { |
1766 Comment cmnt(masm_, "[ Yield"); | 1755 Comment cmnt(masm_, "[ Yield"); |
1767 SetExpressionPosition(expr); | 1756 SetExpressionPosition(expr); |
1768 | 1757 |
1769 // Evaluate yielded value first; the initial iterator definition depends on | 1758 // Evaluate yielded value first; the initial iterator definition depends on |
1770 // this. It stays on the stack while we update the iterator. | 1759 // this. It stays on the stack while we update the iterator. |
1771 VisitForStackValue(expr->expression()); | 1760 VisitForStackValue(expr->expression()); |
1772 | 1761 |
1773 switch (expr->yield_kind()) { | 1762 Label suspend, continuation, post_runtime, resume; |
1774 case Yield::kSuspend: | |
1775 // Pop value from top-of-stack slot; box result into result register. | |
1776 EmitCreateIteratorResult(false); | |
1777 PushOperand(result_register()); | |
1778 // Fall through. | |
1779 case Yield::kInitial: { | |
1780 Label suspend, continuation, post_runtime, resume; | |
1781 | 1763 |
1782 __ b(&suspend, Label::kNear); | 1764 __ b(&suspend); |
1783 __ bind(&continuation); | 1765 __ bind(&continuation); |
1784 // When we arrive here, the stack top is the resume mode and | 1766 // When we arrive here, the stack top is the resume mode and |
1785 // result_register() holds the input value (the argument given to the | 1767 // result_register() holds the input value (the argument given to the |
1786 // respective resume operation). | 1768 // respective resume operation). |
1787 __ RecordGeneratorContinuation(); | 1769 __ RecordGeneratorContinuation(); |
1788 __ pop(r3); | 1770 __ pop(r3); |
1789 __ CmpSmiLiteral(r3, Smi::FromInt(JSGeneratorObject::RETURN), r0); | 1771 __ CmpSmiLiteral(r3, Smi::FromInt(JSGeneratorObject::RETURN), r0); |
1790 __ bne(&resume); | 1772 __ bne(&resume); |
1791 __ push(result_register()); | 1773 __ push(result_register()); |
1792 EmitCreateIteratorResult(true); | 1774 EmitCreateIteratorResult(true); |
1793 EmitUnwindAndReturn(); | 1775 EmitUnwindAndReturn(); |
1794 | 1776 |
1795 __ bind(&suspend); | 1777 __ bind(&suspend); |
1796 OperandStackDepthIncrement(1); // Not popped on this path. | 1778 OperandStackDepthIncrement(1); // Not popped on this path. |
1797 VisitForAccumulatorValue(expr->generator_object()); | 1779 VisitForAccumulatorValue(expr->generator_object()); |
1798 DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); | 1780 DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); |
1799 __ LoadSmiLiteral(r3, Smi::FromInt(continuation.pos())); | 1781 __ LoadSmiLiteral(r3, Smi::FromInt(continuation.pos())); |
1800 __ StoreP(r3, | 1782 __ StoreP(r3, FieldMemOperand(r2, JSGeneratorObject::kContinuationOffset), |
1801 FieldMemOperand(r2, JSGeneratorObject::kContinuationOffset)); | 1783 r0); |
1802 __ StoreP(cp, FieldMemOperand(r2, JSGeneratorObject::kContextOffset)); | 1784 __ StoreP(cp, FieldMemOperand(r2, JSGeneratorObject::kContextOffset), r0); |
1803 __ LoadRR(r3, cp); | 1785 __ LoadRR(r3, cp); |
1804 __ RecordWriteField(r2, JSGeneratorObject::kContextOffset, r3, r4, | 1786 __ RecordWriteField(r2, JSGeneratorObject::kContextOffset, r3, r4, |
1805 kLRHasBeenSaved, kDontSaveFPRegs); | 1787 kLRHasBeenSaved, kDontSaveFPRegs); |
1806 __ AddP(r3, fp, Operand(StandardFrameConstants::kExpressionsOffset)); | 1788 __ AddP(r3, fp, Operand(StandardFrameConstants::kExpressionsOffset)); |
1807 __ CmpP(sp, r3); | 1789 __ CmpP(sp, r3); |
1808 __ beq(&post_runtime); | 1790 __ beq(&post_runtime); |
1809 __ push(r2); // generator object | 1791 __ push(r2); // generator object |
1810 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 1792 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
1811 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1793 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1812 __ bind(&post_runtime); | 1794 __ bind(&post_runtime); |
1813 PopOperand(result_register()); | 1795 PopOperand(result_register()); |
1814 EmitReturnSequence(); | 1796 EmitReturnSequence(); |
1815 | 1797 |
1816 __ bind(&resume); | 1798 __ bind(&resume); |
1817 context()->Plug(result_register()); | 1799 context()->Plug(result_register()); |
1818 break; | |
1819 } | |
1820 | |
1821 case Yield::kFinal: { | |
1822 // Pop value from top-of-stack slot, box result into result register. | |
1823 EmitCreateIteratorResult(true); | |
1824 EmitUnwindAndReturn(); | |
1825 break; | |
1826 } | |
1827 | |
1828 case Yield::kDelegating: | |
1829 UNREACHABLE(); | |
1830 } | |
1831 } | 1800 } |
1832 | 1801 |
1833 void FullCodeGenerator::EmitGeneratorResume( | 1802 void FullCodeGenerator::EmitGeneratorResume( |
1834 Expression* generator, Expression* value, | 1803 Expression* generator, Expression* value, |
1835 JSGeneratorObject::ResumeMode resume_mode) { | 1804 JSGeneratorObject::ResumeMode resume_mode) { |
1836 // The value stays in r2, and is ultimately read by the resumed generator, as | 1805 // The value stays in r2, and is ultimately read by the resumed generator, as |
1837 // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it | 1806 // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it |
1838 // is read to throw the value when the resumed generator is already closed. | 1807 // is read to throw the value when the resumed generator is already closed. |
1839 // r3 will hold the generator object until the activation has been resumed. | 1808 // r3 will hold the generator object until the activation has been resumed. |
1840 VisitForStackValue(generator); | 1809 VisitForStackValue(generator); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1879 // the generator was suspended. | 1848 // the generator was suspended. |
1880 Label resume_frame, done; | 1849 Label resume_frame, done; |
1881 __ bind(&push_frame); | 1850 __ bind(&push_frame); |
1882 __ b(r14, &resume_frame); // brasl | 1851 __ b(r14, &resume_frame); // brasl |
1883 __ b(&done); | 1852 __ b(&done); |
1884 __ bind(&resume_frame); | 1853 __ bind(&resume_frame); |
1885 // lr = return address. | 1854 // lr = return address. |
1886 // fp = caller's frame pointer. | 1855 // fp = caller's frame pointer. |
1887 // cp = callee's context, | 1856 // cp = callee's context, |
1888 // r6 = callee's JS function. | 1857 // r6 = callee's JS function. |
1889 __ PushFixedFrame(r6); | 1858 __ PushStandardFrame(r6); |
1890 // Adjust FP to point to saved FP. | |
1891 __ lay(fp, MemOperand(sp, StandardFrameConstants::kFixedFrameSizeFromFp)); | |
1892 | 1859 |
1893 // Load the operand stack size. | 1860 // Load the operand stack size. |
1894 __ LoadP(r5, FieldMemOperand(r3, JSGeneratorObject::kOperandStackOffset)); | 1861 __ LoadP(r5, FieldMemOperand(r3, JSGeneratorObject::kOperandStackOffset)); |
1895 __ LoadP(r5, FieldMemOperand(r5, FixedArray::kLengthOffset)); | 1862 __ LoadP(r5, FieldMemOperand(r5, FixedArray::kLengthOffset)); |
1896 __ SmiUntag(r5); | 1863 __ SmiUntag(r5); |
1897 | 1864 |
1898 // If we are sending a value and there is no operand stack, we can jump back | 1865 // If we are sending a value and there is no operand stack, we can jump back |
1899 // in directly. | 1866 // in directly. |
1900 Label call_resume; | 1867 Label call_resume; |
1901 if (resume_mode == JSGeneratorObject::NEXT) { | 1868 if (resume_mode == JSGeneratorObject::NEXT) { |
(...skipping 1975 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3877 | 3844 |
3878 VisitForAccumulatorValue(sub_expr); | 3845 VisitForAccumulatorValue(sub_expr); |
3879 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3846 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3880 if (expr->op() == Token::EQ_STRICT) { | 3847 if (expr->op() == Token::EQ_STRICT) { |
3881 Heap::RootListIndex nil_value = nil == kNullValue | 3848 Heap::RootListIndex nil_value = nil == kNullValue |
3882 ? Heap::kNullValueRootIndex | 3849 ? Heap::kNullValueRootIndex |
3883 : Heap::kUndefinedValueRootIndex; | 3850 : Heap::kUndefinedValueRootIndex; |
3884 __ CompareRoot(r2, nil_value); | 3851 __ CompareRoot(r2, nil_value); |
3885 Split(eq, if_true, if_false, fall_through); | 3852 Split(eq, if_true, if_false, fall_through); |
3886 } else { | 3853 } else { |
3887 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); | 3854 __ JumpIfSmi(r2, if_false); |
3888 CallIC(ic, expr->CompareOperationFeedbackId()); | 3855 __ LoadP(r2, FieldMemOperand(r2, HeapObject::kMapOffset)); |
3889 __ CompareRoot(r2, Heap::kTrueValueRootIndex); | 3856 __ LoadlB(r3, FieldMemOperand(r2, Map::kBitFieldOffset)); |
3890 Split(eq, if_true, if_false, fall_through); | 3857 __ AndP(r0, r3, Operand(1 << Map::kIsUndetectable)); |
| 3858 Split(ne, if_true, if_false, fall_through); |
3891 } | 3859 } |
3892 context()->Plug(if_true, if_false); | 3860 context()->Plug(if_true, if_false); |
3893 } | 3861 } |
3894 | 3862 |
3895 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 3863 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
3896 __ LoadP(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 3864 __ LoadP(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
3897 context()->Plug(r2); | 3865 context()->Plug(r2); |
3898 } | 3866 } |
3899 | 3867 |
3900 Register FullCodeGenerator::result_register() { return r2; } | 3868 Register FullCodeGenerator::result_register() { return r2; } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3956 | 3924 |
3957 void FullCodeGenerator::ClearPendingMessage() { | 3925 void FullCodeGenerator::ClearPendingMessage() { |
3958 DCHECK(!result_register().is(r3)); | 3926 DCHECK(!result_register().is(r3)); |
3959 ExternalReference pending_message_obj = | 3927 ExternalReference pending_message_obj = |
3960 ExternalReference::address_of_pending_message_obj(isolate()); | 3928 ExternalReference::address_of_pending_message_obj(isolate()); |
3961 __ LoadRoot(r3, Heap::kTheHoleValueRootIndex); | 3929 __ LoadRoot(r3, Heap::kTheHoleValueRootIndex); |
3962 __ mov(ip, Operand(pending_message_obj)); | 3930 __ mov(ip, Operand(pending_message_obj)); |
3963 __ StoreP(r3, MemOperand(ip)); | 3931 __ StoreP(r3, MemOperand(ip)); |
3964 } | 3932 } |
3965 | 3933 |
3966 void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorSlot slot) { | |
3967 DCHECK(!slot.IsInvalid()); | |
3968 __ mov(VectorStoreICTrampolineDescriptor::SlotRegister(), | |
3969 Operand(SmiFromSlot(slot))); | |
3970 } | |
3971 | |
3972 void FullCodeGenerator::DeferredCommands::EmitCommands() { | 3934 void FullCodeGenerator::DeferredCommands::EmitCommands() { |
3973 DCHECK(!result_register().is(r3)); | 3935 DCHECK(!result_register().is(r3)); |
3974 // Restore the accumulator (r2) and token (r3). | 3936 // Restore the accumulator (r2) and token (r3). |
3975 __ Pop(r3, result_register()); | 3937 __ Pop(r3, result_register()); |
3976 for (DeferredCommand cmd : commands_) { | 3938 for (DeferredCommand cmd : commands_) { |
3977 Label skip; | 3939 Label skip; |
3978 __ CmpSmiLiteral(r3, Smi::FromInt(cmd.token), r0); | 3940 __ CmpSmiLiteral(r3, Smi::FromInt(cmd.token), r0); |
3979 __ bne(&skip); | 3941 __ bne(&skip); |
3980 switch (cmd.command) { | 3942 switch (cmd.command) { |
3981 case kReturn: | 3943 case kReturn: |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4020 case INTERRUPT: { | 3982 case INTERRUPT: { |
4021 // <decrement profiling counter> | 3983 // <decrement profiling counter> |
4022 // bge <ok> ;; patched to GE BRC | 3984 // bge <ok> ;; patched to GE BRC |
4023 // brasrl r14, <interrupt stub address> | 3985 // brasrl r14, <interrupt stub address> |
4024 // <reset profiling counter> | 3986 // <reset profiling counter> |
4025 // ok-label | 3987 // ok-label |
4026 patcher.masm()->brc(ge, Operand(kBackEdgeBranchOffset)); | 3988 patcher.masm()->brc(ge, Operand(kBackEdgeBranchOffset)); |
4027 break; | 3989 break; |
4028 } | 3990 } |
4029 case ON_STACK_REPLACEMENT: | 3991 case ON_STACK_REPLACEMENT: |
4030 case OSR_AFTER_STACK_CHECK: | |
4031 // <decrement profiling counter> | 3992 // <decrement profiling counter> |
4032 // brc 0x0, <ok> ;; patched to NOP BRC | 3993 // brc 0x0, <ok> ;; patched to NOP BRC |
4033 // brasrl r14, <interrupt stub address> | 3994 // brasrl r14, <interrupt stub address> |
4034 // <reset profiling counter> | 3995 // <reset profiling counter> |
4035 // ok-label ----- pc_after points here | 3996 // ok-label ----- pc_after points here |
4036 patcher.masm()->brc(CC_NOP, Operand(kBackEdgeBranchOffset)); | 3997 patcher.masm()->brc(CC_NOP, Operand(kBackEdgeBranchOffset)); |
4037 break; | 3998 break; |
4038 } | 3999 } |
4039 | 4000 |
4040 // Replace the stack check address in the mov sequence with the | 4001 // Replace the stack check address in the mov sequence with the |
4041 // entry address of the replacement code. | 4002 // entry address of the replacement code. |
4042 Assembler::set_target_address_at(isolate, call_address, unoptimized_code, | 4003 Assembler::set_target_address_at(isolate, call_address, unoptimized_code, |
4043 replacement_code->entry()); | 4004 replacement_code->entry()); |
4044 | 4005 |
4045 unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( | 4006 unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( |
4046 unoptimized_code, call_address, replacement_code); | 4007 unoptimized_code, call_address, replacement_code); |
4047 } | 4008 } |
4048 | 4009 |
4049 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( | 4010 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( |
4050 Isolate* isolate, Code* unoptimized_code, Address pc) { | 4011 Isolate* isolate, Code* unoptimized_code, Address pc) { |
4051 Address call_address = Assembler::target_address_from_return_address(pc); | 4012 Address call_address = Assembler::target_address_from_return_address(pc); |
4052 Address branch_address = call_address - 4; | 4013 Address branch_address = call_address - 4; |
| 4014 #ifdef DEBUG |
4053 Address interrupt_address = | 4015 Address interrupt_address = |
4054 Assembler::target_address_at(call_address, unoptimized_code); | 4016 Assembler::target_address_at(call_address, unoptimized_code); |
| 4017 #endif |
4055 | 4018 |
4056 DCHECK(BRC == Instruction::S390OpcodeValue(branch_address)); | 4019 DCHECK(BRC == Instruction::S390OpcodeValue(branch_address)); |
4057 // For interrupt, we expect a branch greater than or equal | 4020 // For interrupt, we expect a branch greater than or equal |
4058 // i.e. BRC 0xa, +XXXX (0xA7A4XXXX) | 4021 // i.e. BRC 0xa, +XXXX (0xA7A4XXXX) |
4059 FourByteInstr br_instr = Instruction::InstructionBits( | 4022 FourByteInstr br_instr = Instruction::InstructionBits( |
4060 reinterpret_cast<const byte*>(branch_address)); | 4023 reinterpret_cast<const byte*>(branch_address)); |
4061 if (kInterruptBranchInstruction == br_instr) { | 4024 if (kInterruptBranchInstruction == br_instr) { |
4062 DCHECK(interrupt_address == isolate->builtins()->InterruptCheck()->entry()); | 4025 DCHECK(interrupt_address == isolate->builtins()->InterruptCheck()->entry()); |
4063 return INTERRUPT; | 4026 return INTERRUPT; |
4064 } | 4027 } |
4065 | 4028 |
4066 // Expect BRC to be patched to NOP branch. | 4029 // Expect BRC to be patched to NOP branch. |
4067 // i.e. BRC 0x0, +XXXX (0xA704XXXX) | 4030 // i.e. BRC 0x0, +XXXX (0xA704XXXX) |
4068 USE(kOSRBranchInstruction); | 4031 USE(kOSRBranchInstruction); |
4069 DCHECK(kOSRBranchInstruction == br_instr); | 4032 DCHECK(kOSRBranchInstruction == br_instr); |
4070 | 4033 |
4071 if (interrupt_address == isolate->builtins()->OnStackReplacement()->entry()) { | |
4072 return ON_STACK_REPLACEMENT; | |
4073 } | |
4074 | |
4075 DCHECK(interrupt_address == | 4034 DCHECK(interrupt_address == |
4076 isolate->builtins()->OsrAfterStackCheck()->entry()); | 4035 isolate->builtins()->OnStackReplacement()->entry()); |
4077 return OSR_AFTER_STACK_CHECK; | 4036 return ON_STACK_REPLACEMENT; |
4078 } | 4037 } |
4079 | 4038 |
4080 } // namespace internal | 4039 } // namespace internal |
4081 } // namespace v8 | 4040 } // namespace v8 |
4082 #endif // V8_TARGET_ARCH_S390 | 4041 #endif // V8_TARGET_ARCH_S390 |
OLD | NEW |