| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 private: | 60 private: |
| 61 LCodeGen* codegen_; | 61 LCodeGen* codegen_; |
| 62 LPointerMap* pointers_; | 62 LPointerMap* pointers_; |
| 63 Safepoint::DeoptMode deopt_mode_; | 63 Safepoint::DeoptMode deopt_mode_; |
| 64 }; | 64 }; |
| 65 | 65 |
| 66 | 66 |
| 67 #define __ masm()-> | 67 #define __ masm()-> |
| 68 | 68 |
| 69 bool LCodeGen::GenerateCode() { | 69 bool LCodeGen::GenerateCode() { |
| 70 HPhase phase("Z_Code generation", chunk()); | 70 LPhase phase("Z_Code generation", chunk()); |
| 71 ASSERT(is_unused()); | 71 ASSERT(is_unused()); |
| 72 status_ = GENERATING; | 72 status_ = GENERATING; |
| 73 | 73 |
| 74 // Open a frame scope to indicate that there is a frame on the stack. The | 74 // Open a frame scope to indicate that there is a frame on the stack. The |
| 75 // MANUAL indicates that the scope shouldn't actually generate code to set up | 75 // MANUAL indicates that the scope shouldn't actually generate code to set up |
| 76 // the frame (that is done in GeneratePrologue). | 76 // the frame (that is done in GeneratePrologue). |
| 77 FrameScope frame_scope(masm_, StackFrame::MANUAL); | 77 FrameScope frame_scope(masm_, StackFrame::MANUAL); |
| 78 | 78 |
| 79 return GeneratePrologue() && | 79 return GeneratePrologue() && |
| 80 GenerateBody() && | 80 GenerateBody() && |
| 81 GenerateDeferredCode() && | 81 GenerateDeferredCode() && |
| 82 GenerateJumpTable() && | 82 GenerateJumpTable() && |
| 83 GenerateSafepointTable(); | 83 GenerateSafepointTable(); |
| 84 } | 84 } |
| 85 | 85 |
| 86 | 86 |
| 87 void LCodeGen::FinishCode(Handle<Code> code) { | 87 void LCodeGen::FinishCode(Handle<Code> code) { |
| 88 ASSERT(is_done()); | 88 ASSERT(is_done()); |
| 89 code->set_stack_slots(GetStackSlotCount()); | 89 code->set_stack_slots(GetStackSlotCount()); |
| 90 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); | 90 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); |
| 91 if (FLAG_weak_embedded_maps_in_optimized_code) { | 91 if (FLAG_weak_embedded_maps_in_optimized_code) { |
| 92 RegisterDependentCodeForEmbeddedMaps(code); | 92 RegisterDependentCodeForEmbeddedMaps(code); |
| 93 } | 93 } |
| 94 PopulateDeoptimizationData(code); | 94 PopulateDeoptimizationData(code); |
| 95 info()->CommitDependentMaps(code); | 95 info()->CommitDependencies(code); |
| 96 } | 96 } |
| 97 | 97 |
| 98 | 98 |
| 99 void LChunkBuilder::Abort(const char* reason) { | 99 void LChunkBuilder::Abort(const char* reason) { |
| 100 info()->set_bailout_reason(reason); | 100 info()->set_bailout_reason(reason); |
| 101 status_ = ABORTED; | 101 status_ = ABORTED; |
| 102 } | 102 } |
| 103 | 103 |
| 104 | 104 |
| 105 void LCodeGen::Comment(const char* format, ...) { | 105 void LCodeGen::Comment(const char* format, ...) { |
| (...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 case ARGUMENTS_ADAPTOR: | 504 case ARGUMENTS_ADAPTOR: |
| 505 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); | 505 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); |
| 506 break; | 506 break; |
| 507 case STUB: | 507 case STUB: |
| 508 translation->BeginCompiledStubFrame(); | 508 translation->BeginCompiledStubFrame(); |
| 509 break; | 509 break; |
| 510 } | 510 } |
| 511 | 511 |
| 512 for (int i = 0; i < translation_size; ++i) { | 512 for (int i = 0; i < translation_size; ++i) { |
| 513 LOperand* value = environment->values()->at(i); | 513 LOperand* value = environment->values()->at(i); |
| 514 // spilled_registers_ and spilled_double_registers_ are either | |
| 515 // both NULL or both set. | |
| 516 if (environment->spilled_registers() != NULL && value != NULL) { | |
| 517 if (value->IsRegister() && | |
| 518 environment->spilled_registers()[value->index()] != NULL) { | |
| 519 translation->MarkDuplicate(); | |
| 520 AddToTranslation(translation, | |
| 521 environment->spilled_registers()[value->index()], | |
| 522 environment->HasTaggedValueAt(i), | |
| 523 environment->HasUint32ValueAt(i)); | |
| 524 } else if ( | |
| 525 value->IsDoubleRegister() && | |
| 526 environment->spilled_double_registers()[value->index()] != NULL) { | |
| 527 translation->MarkDuplicate(); | |
| 528 AddToTranslation( | |
| 529 translation, | |
| 530 environment->spilled_double_registers()[value->index()], | |
| 531 false, | |
| 532 false); | |
| 533 } | |
| 534 } | |
| 535 | 514 |
| 536 // TODO(mstarzinger): Introduce marker operands to indicate that this value | 515 // TODO(mstarzinger): Introduce marker operands to indicate that this value |
| 537 // is not present and must be reconstructed from the deoptimizer. Currently | 516 // is not present and must be reconstructed from the deoptimizer. Currently |
| 538 // this is only used for the arguments object. | 517 // this is only used for the arguments object. |
| 539 if (value == NULL) { | 518 if (value == NULL) { |
| 540 int arguments_count = environment->values()->length() - translation_size; | 519 int arguments_count = environment->values()->length() - translation_size; |
| 541 translation->BeginArgumentsObject(arguments_count); | 520 translation->BeginArgumentsObject(arguments_count); |
| 542 for (int i = 0; i < arguments_count; ++i) { | 521 for (int i = 0; i < arguments_count; ++i) { |
| 543 LOperand* value = environment->values()->at(translation_size + i); | 522 LOperand* value = environment->values()->at(translation_size + i); |
| 544 ASSERT(environment->spilled_registers() == NULL || | |
| 545 !value->IsRegister() || | |
| 546 environment->spilled_registers()[value->index()] == NULL); | |
| 547 ASSERT(environment->spilled_registers() == NULL || | |
| 548 !value->IsDoubleRegister() || | |
| 549 environment->spilled_double_registers()[value->index()] == NULL); | |
| 550 AddToTranslation(translation, | 523 AddToTranslation(translation, |
| 551 value, | 524 value, |
| 552 environment->HasTaggedValueAt(translation_size + i), | 525 environment->HasTaggedValueAt(translation_size + i), |
| 553 environment->HasUint32ValueAt(translation_size + i)); | 526 environment->HasUint32ValueAt(translation_size + i)); |
| 554 } | 527 } |
| 555 continue; | 528 continue; |
| 556 } | 529 } |
| 557 | 530 |
| 558 AddToTranslation(translation, | 531 AddToTranslation(translation, |
| 559 value, | 532 value, |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 993 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 966 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 994 break; | 967 break; |
| 995 } | 968 } |
| 996 default: | 969 default: |
| 997 UNREACHABLE(); | 970 UNREACHABLE(); |
| 998 } | 971 } |
| 999 } | 972 } |
| 1000 | 973 |
| 1001 | 974 |
| 1002 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 975 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
| 1003 // Nothing to do. | 976 // Record the address of the first unknown OSR value as the place to enter. |
| 977 if (osr_pc_offset_ == -1) osr_pc_offset_ = masm()->pc_offset(); |
| 1004 } | 978 } |
| 1005 | 979 |
| 1006 | 980 |
| 1007 void LCodeGen::DoModI(LModI* instr) { | 981 void LCodeGen::DoModI(LModI* instr) { |
| 1008 HMod* hmod = instr->hydrogen(); | 982 HMod* hmod = instr->hydrogen(); |
| 1009 HValue* left = hmod->left(); | 983 HValue* left = hmod->left(); |
| 1010 HValue* right = hmod->right(); | 984 HValue* right = hmod->right(); |
| 1011 if (hmod->HasPowerOf2Divisor()) { | 985 if (hmod->HasPowerOf2Divisor()) { |
| 1012 // TODO(svenpanne) We should really do the strength reduction on the | 986 // TODO(svenpanne) We should really do the strength reduction on the |
| 1013 // Hydrogen level. | 987 // Hydrogen level. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1027 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1001 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1028 DeoptimizeIf(zero, instr->environment()); | 1002 DeoptimizeIf(zero, instr->environment()); |
| 1029 } | 1003 } |
| 1030 __ jmp(&done, Label::kNear); | 1004 __ jmp(&done, Label::kNear); |
| 1031 } | 1005 } |
| 1032 | 1006 |
| 1033 __ bind(&left_is_not_negative); | 1007 __ bind(&left_is_not_negative); |
| 1034 __ andl(left_reg, Immediate(divisor - 1)); | 1008 __ andl(left_reg, Immediate(divisor - 1)); |
| 1035 __ bind(&done); | 1009 __ bind(&done); |
| 1036 | 1010 |
| 1037 } else if (hmod->has_fixed_right_arg()) { | 1011 } else if (hmod->fixed_right_arg().has_value) { |
| 1038 Register left_reg = ToRegister(instr->left()); | 1012 Register left_reg = ToRegister(instr->left()); |
| 1039 ASSERT(left_reg.is(ToRegister(instr->result()))); | 1013 ASSERT(left_reg.is(ToRegister(instr->result()))); |
| 1040 Register right_reg = ToRegister(instr->right()); | 1014 Register right_reg = ToRegister(instr->right()); |
| 1041 | 1015 |
| 1042 int32_t divisor = hmod->fixed_right_arg_value(); | 1016 int32_t divisor = hmod->fixed_right_arg().value; |
| 1043 ASSERT(IsPowerOf2(divisor)); | 1017 ASSERT(IsPowerOf2(divisor)); |
| 1044 | 1018 |
| 1045 // Check if our assumption of a fixed right operand still holds. | 1019 // Check if our assumption of a fixed right operand still holds. |
| 1046 __ cmpl(right_reg, Immediate(divisor)); | 1020 __ cmpl(right_reg, Immediate(divisor)); |
| 1047 DeoptimizeIf(not_equal, instr->environment()); | 1021 DeoptimizeIf(not_equal, instr->environment()); |
| 1048 | 1022 |
| 1049 Label left_is_not_negative, done; | 1023 Label left_is_not_negative, done; |
| 1050 if (left->CanBeNegative()) { | 1024 if (left->CanBeNegative()) { |
| 1051 __ testl(left_reg, left_reg); | 1025 __ testl(left_reg, left_reg); |
| 1052 __ j(not_sign, &left_is_not_negative, Label::kNear); | 1026 __ j(not_sign, &left_is_not_negative, Label::kNear); |
| (...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1605 __ and_(result, Immediate(Map::kElementsKindMask)); | 1579 __ and_(result, Immediate(Map::kElementsKindMask)); |
| 1606 __ shr(result, Immediate(Map::kElementsKindShift)); | 1580 __ shr(result, Immediate(Map::kElementsKindShift)); |
| 1607 } | 1581 } |
| 1608 | 1582 |
| 1609 | 1583 |
| 1610 void LCodeGen::DoValueOf(LValueOf* instr) { | 1584 void LCodeGen::DoValueOf(LValueOf* instr) { |
| 1611 Register input = ToRegister(instr->value()); | 1585 Register input = ToRegister(instr->value()); |
| 1612 Register result = ToRegister(instr->result()); | 1586 Register result = ToRegister(instr->result()); |
| 1613 ASSERT(input.is(result)); | 1587 ASSERT(input.is(result)); |
| 1614 Label done; | 1588 Label done; |
| 1615 // If the object is a smi return the object. | 1589 |
| 1616 __ JumpIfSmi(input, &done, Label::kNear); | 1590 if (!instr->hydrogen()->value()->IsHeapObject()) { |
| 1591 // If the object is a smi return the object. |
| 1592 __ JumpIfSmi(input, &done, Label::kNear); |
| 1593 } |
| 1617 | 1594 |
| 1618 // If the object is not a value type, return the object. | 1595 // If the object is not a value type, return the object. |
| 1619 __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister); | 1596 __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister); |
| 1620 __ j(not_equal, &done, Label::kNear); | 1597 __ j(not_equal, &done, Label::kNear); |
| 1621 __ movq(result, FieldOperand(input, JSValue::kValueOffset)); | 1598 __ movq(result, FieldOperand(input, JSValue::kValueOffset)); |
| 1622 | 1599 |
| 1623 __ bind(&done); | 1600 __ bind(&done); |
| 1624 } | 1601 } |
| 1625 | 1602 |
| 1626 | 1603 |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1855 | 1832 |
| 1856 | 1833 |
| 1857 int LCodeGen::GetNextEmittedBlock() const { | 1834 int LCodeGen::GetNextEmittedBlock() const { |
| 1858 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { | 1835 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { |
| 1859 if (!chunk_->GetLabel(i)->HasReplacement()) return i; | 1836 if (!chunk_->GetLabel(i)->HasReplacement()) return i; |
| 1860 } | 1837 } |
| 1861 return -1; | 1838 return -1; |
| 1862 } | 1839 } |
| 1863 | 1840 |
| 1864 | 1841 |
| 1865 void LCodeGen::EmitBranch(int left_block, int right_block, Condition cc) { | 1842 template<class InstrType> |
| 1843 void LCodeGen::EmitBranch(InstrType instr, Condition cc) { |
| 1844 int right_block = instr->FalseDestination(chunk_); |
| 1845 int left_block = instr->TrueDestination(chunk_); |
| 1846 |
| 1866 int next_block = GetNextEmittedBlock(); | 1847 int next_block = GetNextEmittedBlock(); |
| 1867 right_block = chunk_->LookupDestination(right_block); | |
| 1868 left_block = chunk_->LookupDestination(left_block); | |
| 1869 | 1848 |
| 1870 if (right_block == left_block) { | 1849 if (right_block == left_block) { |
| 1871 EmitGoto(left_block); | 1850 EmitGoto(left_block); |
| 1872 } else if (left_block == next_block) { | 1851 } else if (left_block == next_block) { |
| 1873 __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); | 1852 __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); |
| 1874 } else if (right_block == next_block) { | 1853 } else if (right_block == next_block) { |
| 1875 __ j(cc, chunk_->GetAssemblyLabel(left_block)); | 1854 __ j(cc, chunk_->GetAssemblyLabel(left_block)); |
| 1876 } else { | 1855 } else { |
| 1877 __ j(cc, chunk_->GetAssemblyLabel(left_block)); | 1856 __ j(cc, chunk_->GetAssemblyLabel(left_block)); |
| 1878 if (cc != always) { | 1857 if (cc != always) { |
| 1879 __ jmp(chunk_->GetAssemblyLabel(right_block)); | 1858 __ jmp(chunk_->GetAssemblyLabel(right_block)); |
| 1880 } | 1859 } |
| 1881 } | 1860 } |
| 1882 } | 1861 } |
| 1883 | 1862 |
| 1884 | 1863 |
| 1885 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { | 1864 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { |
| 1886 __ int3(); | 1865 __ int3(); |
| 1887 } | 1866 } |
| 1888 | 1867 |
| 1889 | 1868 |
| 1890 void LCodeGen::DoBranch(LBranch* instr) { | 1869 void LCodeGen::DoBranch(LBranch* instr) { |
| 1891 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 1892 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 1893 | |
| 1894 Representation r = instr->hydrogen()->value()->representation(); | 1870 Representation r = instr->hydrogen()->value()->representation(); |
| 1895 if (r.IsInteger32()) { | 1871 if (r.IsInteger32()) { |
| 1896 ASSERT(!info()->IsStub()); | 1872 ASSERT(!info()->IsStub()); |
| 1897 Register reg = ToRegister(instr->value()); | 1873 Register reg = ToRegister(instr->value()); |
| 1898 __ testl(reg, reg); | 1874 __ testl(reg, reg); |
| 1899 EmitBranch(true_block, false_block, not_zero); | 1875 EmitBranch(instr, not_zero); |
| 1900 } else if (r.IsSmi()) { | 1876 } else if (r.IsSmi()) { |
| 1901 ASSERT(!info()->IsStub()); | 1877 ASSERT(!info()->IsStub()); |
| 1902 Register reg = ToRegister(instr->value()); | 1878 Register reg = ToRegister(instr->value()); |
| 1903 __ testq(reg, reg); | 1879 __ testq(reg, reg); |
| 1904 EmitBranch(true_block, false_block, not_zero); | 1880 EmitBranch(instr, not_zero); |
| 1905 } else if (r.IsDouble()) { | 1881 } else if (r.IsDouble()) { |
| 1906 ASSERT(!info()->IsStub()); | 1882 ASSERT(!info()->IsStub()); |
| 1907 XMMRegister reg = ToDoubleRegister(instr->value()); | 1883 XMMRegister reg = ToDoubleRegister(instr->value()); |
| 1908 __ xorps(xmm0, xmm0); | 1884 __ xorps(xmm0, xmm0); |
| 1909 __ ucomisd(reg, xmm0); | 1885 __ ucomisd(reg, xmm0); |
| 1910 EmitBranch(true_block, false_block, not_equal); | 1886 EmitBranch(instr, not_equal); |
| 1911 } else { | 1887 } else { |
| 1912 ASSERT(r.IsTagged()); | 1888 ASSERT(r.IsTagged()); |
| 1913 Register reg = ToRegister(instr->value()); | 1889 Register reg = ToRegister(instr->value()); |
| 1914 HType type = instr->hydrogen()->value()->type(); | 1890 HType type = instr->hydrogen()->value()->type(); |
| 1915 if (type.IsBoolean()) { | 1891 if (type.IsBoolean()) { |
| 1916 ASSERT(!info()->IsStub()); | 1892 ASSERT(!info()->IsStub()); |
| 1917 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 1893 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
| 1918 EmitBranch(true_block, false_block, equal); | 1894 EmitBranch(instr, equal); |
| 1919 } else if (type.IsSmi()) { | 1895 } else if (type.IsSmi()) { |
| 1920 ASSERT(!info()->IsStub()); | 1896 ASSERT(!info()->IsStub()); |
| 1921 __ SmiCompare(reg, Smi::FromInt(0)); | 1897 __ SmiCompare(reg, Smi::FromInt(0)); |
| 1922 EmitBranch(true_block, false_block, not_equal); | 1898 EmitBranch(instr, not_equal); |
| 1899 } else if (type.IsJSArray()) { |
| 1900 ASSERT(!info()->IsStub()); |
| 1901 EmitBranch(instr, no_condition); |
| 1902 } else if (type.IsHeapNumber()) { |
| 1903 ASSERT(!info()->IsStub()); |
| 1904 __ xorps(xmm0, xmm0); |
| 1905 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); |
| 1906 EmitBranch(instr, not_equal); |
| 1907 } else if (type.IsString()) { |
| 1908 ASSERT(!info()->IsStub()); |
| 1909 __ cmpq(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
| 1910 EmitBranch(instr, not_equal); |
| 1923 } else { | 1911 } else { |
| 1924 Label* true_label = chunk_->GetAssemblyLabel(true_block); | |
| 1925 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
| 1926 | |
| 1927 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); | 1912 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
| 1928 // Avoid deopts in the case where we've never executed this path before. | 1913 // Avoid deopts in the case where we've never executed this path before. |
| 1929 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); | 1914 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); |
| 1930 | 1915 |
| 1931 if (expected.Contains(ToBooleanStub::UNDEFINED)) { | 1916 if (expected.Contains(ToBooleanStub::UNDEFINED)) { |
| 1932 // undefined -> false. | 1917 // undefined -> false. |
| 1933 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | 1918 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); |
| 1934 __ j(equal, false_label); | 1919 __ j(equal, instr->FalseLabel(chunk_)); |
| 1935 } | 1920 } |
| 1936 if (expected.Contains(ToBooleanStub::BOOLEAN)) { | 1921 if (expected.Contains(ToBooleanStub::BOOLEAN)) { |
| 1937 // true -> true. | 1922 // true -> true. |
| 1938 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 1923 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
| 1939 __ j(equal, true_label); | 1924 __ j(equal, instr->TrueLabel(chunk_)); |
| 1940 // false -> false. | 1925 // false -> false. |
| 1941 __ CompareRoot(reg, Heap::kFalseValueRootIndex); | 1926 __ CompareRoot(reg, Heap::kFalseValueRootIndex); |
| 1942 __ j(equal, false_label); | 1927 __ j(equal, instr->FalseLabel(chunk_)); |
| 1943 } | 1928 } |
| 1944 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { | 1929 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { |
| 1945 // 'null' -> false. | 1930 // 'null' -> false. |
| 1946 __ CompareRoot(reg, Heap::kNullValueRootIndex); | 1931 __ CompareRoot(reg, Heap::kNullValueRootIndex); |
| 1947 __ j(equal, false_label); | 1932 __ j(equal, instr->FalseLabel(chunk_)); |
| 1948 } | 1933 } |
| 1949 | 1934 |
| 1950 if (expected.Contains(ToBooleanStub::SMI)) { | 1935 if (expected.Contains(ToBooleanStub::SMI)) { |
| 1951 // Smis: 0 -> false, all other -> true. | 1936 // Smis: 0 -> false, all other -> true. |
| 1952 __ Cmp(reg, Smi::FromInt(0)); | 1937 __ Cmp(reg, Smi::FromInt(0)); |
| 1953 __ j(equal, false_label); | 1938 __ j(equal, instr->FalseLabel(chunk_)); |
| 1954 __ JumpIfSmi(reg, true_label); | 1939 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
| 1955 } else if (expected.NeedsMap()) { | 1940 } else if (expected.NeedsMap()) { |
| 1956 // If we need a map later and have a Smi -> deopt. | 1941 // If we need a map later and have a Smi -> deopt. |
| 1957 __ testb(reg, Immediate(kSmiTagMask)); | 1942 __ testb(reg, Immediate(kSmiTagMask)); |
| 1958 DeoptimizeIf(zero, instr->environment()); | 1943 DeoptimizeIf(zero, instr->environment()); |
| 1959 } | 1944 } |
| 1960 | 1945 |
| 1961 const Register map = kScratchRegister; | 1946 const Register map = kScratchRegister; |
| 1962 if (expected.NeedsMap()) { | 1947 if (expected.NeedsMap()) { |
| 1963 __ movq(map, FieldOperand(reg, HeapObject::kMapOffset)); | 1948 __ movq(map, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1964 | 1949 |
| 1965 if (expected.CanBeUndetectable()) { | 1950 if (expected.CanBeUndetectable()) { |
| 1966 // Undetectable -> false. | 1951 // Undetectable -> false. |
| 1967 __ testb(FieldOperand(map, Map::kBitFieldOffset), | 1952 __ testb(FieldOperand(map, Map::kBitFieldOffset), |
| 1968 Immediate(1 << Map::kIsUndetectable)); | 1953 Immediate(1 << Map::kIsUndetectable)); |
| 1969 __ j(not_zero, false_label); | 1954 __ j(not_zero, instr->FalseLabel(chunk_)); |
| 1970 } | 1955 } |
| 1971 } | 1956 } |
| 1972 | 1957 |
| 1973 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { | 1958 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { |
| 1974 // spec object -> true. | 1959 // spec object -> true. |
| 1975 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); | 1960 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); |
| 1976 __ j(above_equal, true_label); | 1961 __ j(above_equal, instr->TrueLabel(chunk_)); |
| 1977 } | 1962 } |
| 1978 | 1963 |
| 1979 if (expected.Contains(ToBooleanStub::STRING)) { | 1964 if (expected.Contains(ToBooleanStub::STRING)) { |
| 1980 // String value -> false iff empty. | 1965 // String value -> false iff empty. |
| 1981 Label not_string; | 1966 Label not_string; |
| 1982 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); | 1967 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); |
| 1983 __ j(above_equal, ¬_string, Label::kNear); | 1968 __ j(above_equal, ¬_string, Label::kNear); |
| 1984 __ cmpq(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | 1969 __ cmpq(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
| 1985 __ j(not_zero, true_label); | 1970 __ j(not_zero, instr->TrueLabel(chunk_)); |
| 1986 __ jmp(false_label); | 1971 __ jmp(instr->FalseLabel(chunk_)); |
| 1987 __ bind(¬_string); | 1972 __ bind(¬_string); |
| 1988 } | 1973 } |
| 1989 | 1974 |
| 1990 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 1975 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
| 1991 // heap number -> false iff +0, -0, or NaN. | 1976 // heap number -> false iff +0, -0, or NaN. |
| 1992 Label not_heap_number; | 1977 Label not_heap_number; |
| 1993 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 1978 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
| 1994 __ j(not_equal, ¬_heap_number, Label::kNear); | 1979 __ j(not_equal, ¬_heap_number, Label::kNear); |
| 1995 __ xorps(xmm0, xmm0); | 1980 __ xorps(xmm0, xmm0); |
| 1996 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); | 1981 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); |
| 1997 __ j(zero, false_label); | 1982 __ j(zero, instr->FalseLabel(chunk_)); |
| 1998 __ jmp(true_label); | 1983 __ jmp(instr->TrueLabel(chunk_)); |
| 1999 __ bind(¬_heap_number); | 1984 __ bind(¬_heap_number); |
| 2000 } | 1985 } |
| 2001 | 1986 |
| 2002 // We've seen something for the first time -> deopt. | 1987 if (!expected.IsGeneric()) { |
| 2003 DeoptimizeIf(no_condition, instr->environment()); | 1988 // We've seen something for the first time -> deopt. |
| 1989 // This can only happen if we are not generic already. |
| 1990 DeoptimizeIf(no_condition, instr->environment()); |
| 1991 } |
| 2004 } | 1992 } |
| 2005 } | 1993 } |
| 2006 } | 1994 } |
| 2007 | 1995 |
| 2008 | 1996 |
| 2009 void LCodeGen::EmitGoto(int block) { | 1997 void LCodeGen::EmitGoto(int block) { |
| 2010 if (!IsNextEmittedBlock(block)) { | 1998 if (!IsNextEmittedBlock(block)) { |
| 2011 __ jmp(chunk_->GetAssemblyLabel(chunk_->LookupDestination(block))); | 1999 __ jmp(chunk_->GetAssemblyLabel(chunk_->LookupDestination(block))); |
| 2012 } | 2000 } |
| 2013 } | 2001 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2042 default: | 2030 default: |
| 2043 UNREACHABLE(); | 2031 UNREACHABLE(); |
| 2044 } | 2032 } |
| 2045 return cond; | 2033 return cond; |
| 2046 } | 2034 } |
| 2047 | 2035 |
| 2048 | 2036 |
| 2049 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 2037 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
| 2050 LOperand* left = instr->left(); | 2038 LOperand* left = instr->left(); |
| 2051 LOperand* right = instr->right(); | 2039 LOperand* right = instr->right(); |
| 2052 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 2053 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 2054 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 2040 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
| 2055 | 2041 |
| 2056 if (left->IsConstantOperand() && right->IsConstantOperand()) { | 2042 if (left->IsConstantOperand() && right->IsConstantOperand()) { |
| 2057 // We can statically evaluate the comparison. | 2043 // We can statically evaluate the comparison. |
| 2058 double left_val = ToDouble(LConstantOperand::cast(left)); | 2044 double left_val = ToDouble(LConstantOperand::cast(left)); |
| 2059 double right_val = ToDouble(LConstantOperand::cast(right)); | 2045 double right_val = ToDouble(LConstantOperand::cast(right)); |
| 2060 int next_block = | 2046 int next_block = EvalComparison(instr->op(), left_val, right_val) ? |
| 2061 EvalComparison(instr->op(), left_val, right_val) ? true_block | 2047 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); |
| 2062 : false_block; | |
| 2063 EmitGoto(next_block); | 2048 EmitGoto(next_block); |
| 2064 } else { | 2049 } else { |
| 2065 if (instr->is_double()) { | 2050 if (instr->is_double()) { |
| 2066 // Don't base result on EFLAGS when a NaN is involved. Instead | 2051 // Don't base result on EFLAGS when a NaN is involved. Instead |
| 2067 // jump to the false block. | 2052 // jump to the false block. |
| 2068 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | 2053 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
| 2069 __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); | 2054 __ j(parity_even, instr->FalseLabel(chunk_)); |
| 2070 } else { | 2055 } else { |
| 2071 int32_t value; | 2056 int32_t value; |
| 2072 if (right->IsConstantOperand()) { | 2057 if (right->IsConstantOperand()) { |
| 2073 value = ToInteger32(LConstantOperand::cast(right)); | 2058 value = ToInteger32(LConstantOperand::cast(right)); |
| 2074 if (instr->hydrogen_value()->representation().IsSmi()) { | 2059 if (instr->hydrogen_value()->representation().IsSmi()) { |
| 2075 __ Cmp(ToRegister(left), Smi::FromInt(value)); | 2060 __ Cmp(ToRegister(left), Smi::FromInt(value)); |
| 2076 } else { | 2061 } else { |
| 2077 __ cmpl(ToRegister(left), Immediate(value)); | 2062 __ cmpl(ToRegister(left), Immediate(value)); |
| 2078 } | 2063 } |
| 2079 } else if (left->IsConstantOperand()) { | 2064 } else if (left->IsConstantOperand()) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2098 __ cmpq(ToRegister(left), ToOperand(right)); | 2083 __ cmpq(ToRegister(left), ToOperand(right)); |
| 2099 } | 2084 } |
| 2100 } else { | 2085 } else { |
| 2101 if (right->IsRegister()) { | 2086 if (right->IsRegister()) { |
| 2102 __ cmpl(ToRegister(left), ToRegister(right)); | 2087 __ cmpl(ToRegister(left), ToRegister(right)); |
| 2103 } else { | 2088 } else { |
| 2104 __ cmpl(ToRegister(left), ToOperand(right)); | 2089 __ cmpl(ToRegister(left), ToOperand(right)); |
| 2105 } | 2090 } |
| 2106 } | 2091 } |
| 2107 } | 2092 } |
| 2108 EmitBranch(true_block, false_block, cc); | 2093 EmitBranch(instr, cc); |
| 2109 } | 2094 } |
| 2110 } | 2095 } |
| 2111 | 2096 |
| 2112 | 2097 |
| 2113 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 2098 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
| 2114 Register left = ToRegister(instr->left()); | 2099 Register left = ToRegister(instr->left()); |
| 2115 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 2116 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 2117 | 2100 |
| 2118 if (instr->right()->IsConstantOperand()) { | 2101 if (instr->right()->IsConstantOperand()) { |
| 2119 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); | 2102 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); |
| 2120 __ CmpObject(left, right); | 2103 __ CmpObject(left, right); |
| 2121 } else { | 2104 } else { |
| 2122 Register right = ToRegister(instr->right()); | 2105 Register right = ToRegister(instr->right()); |
| 2123 __ cmpq(left, right); | 2106 __ cmpq(left, right); |
| 2124 } | 2107 } |
| 2125 EmitBranch(true_block, false_block, equal); | 2108 EmitBranch(instr, equal); |
| 2126 } | 2109 } |
| 2127 | 2110 |
| 2128 | 2111 |
| 2129 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { | 2112 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { |
| 2130 Register left = ToRegister(instr->left()); | 2113 Register left = ToRegister(instr->left()); |
| 2131 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 2132 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 2133 | 2114 |
| 2134 __ cmpq(left, Immediate(instr->hydrogen()->right())); | 2115 __ cmpq(left, Immediate(instr->hydrogen()->right())); |
| 2135 EmitBranch(true_block, false_block, equal); | 2116 EmitBranch(instr, equal); |
| 2136 } | 2117 } |
| 2137 | 2118 |
| 2138 | 2119 |
| 2139 Condition LCodeGen::EmitIsObject(Register input, | 2120 Condition LCodeGen::EmitIsObject(Register input, |
| 2140 Label* is_not_object, | 2121 Label* is_not_object, |
| 2141 Label* is_object) { | 2122 Label* is_object) { |
| 2142 ASSERT(!input.is(kScratchRegister)); | 2123 ASSERT(!input.is(kScratchRegister)); |
| 2143 | 2124 |
| 2144 __ JumpIfSmi(input, is_not_object); | 2125 __ JumpIfSmi(input, is_not_object); |
| 2145 | 2126 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2157 __ cmpb(kScratchRegister, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 2138 __ cmpb(kScratchRegister, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
| 2158 __ j(below, is_not_object); | 2139 __ j(below, is_not_object); |
| 2159 __ cmpb(kScratchRegister, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 2140 __ cmpb(kScratchRegister, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
| 2160 return below_equal; | 2141 return below_equal; |
| 2161 } | 2142 } |
| 2162 | 2143 |
| 2163 | 2144 |
| 2164 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 2145 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
| 2165 Register reg = ToRegister(instr->value()); | 2146 Register reg = ToRegister(instr->value()); |
| 2166 | 2147 |
| 2167 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2148 Condition true_cond = EmitIsObject( |
| 2168 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2149 reg, instr->FalseLabel(chunk_), instr->TrueLabel(chunk_)); |
| 2169 Label* true_label = chunk_->GetAssemblyLabel(true_block); | |
| 2170 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
| 2171 | 2150 |
| 2172 Condition true_cond = EmitIsObject(reg, false_label, true_label); | 2151 EmitBranch(instr, true_cond); |
| 2173 | |
| 2174 EmitBranch(true_block, false_block, true_cond); | |
| 2175 } | 2152 } |
| 2176 | 2153 |
| 2177 | 2154 |
| 2178 Condition LCodeGen::EmitIsString(Register input, | 2155 Condition LCodeGen::EmitIsString(Register input, |
| 2179 Register temp1, | 2156 Register temp1, |
| 2180 Label* is_not_string) { | 2157 Label* is_not_string, |
| 2181 __ JumpIfSmi(input, is_not_string); | 2158 SmiCheck check_needed = INLINE_SMI_CHECK) { |
| 2159 if (check_needed == INLINE_SMI_CHECK) { |
| 2160 __ JumpIfSmi(input, is_not_string); |
| 2161 } |
| 2162 |
| 2182 Condition cond = masm_->IsObjectStringType(input, temp1, temp1); | 2163 Condition cond = masm_->IsObjectStringType(input, temp1, temp1); |
| 2183 | 2164 |
| 2184 return cond; | 2165 return cond; |
| 2185 } | 2166 } |
| 2186 | 2167 |
| 2187 | 2168 |
| 2188 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { | 2169 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { |
| 2189 Register reg = ToRegister(instr->value()); | 2170 Register reg = ToRegister(instr->value()); |
| 2190 Register temp = ToRegister(instr->temp()); | 2171 Register temp = ToRegister(instr->temp()); |
| 2191 | 2172 |
| 2192 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2173 SmiCheck check_needed = |
| 2193 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2174 instr->hydrogen()->value()->IsHeapObject() |
| 2194 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 2175 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 2195 | 2176 |
| 2196 Condition true_cond = EmitIsString(reg, temp, false_label); | 2177 Condition true_cond = EmitIsString( |
| 2178 reg, temp, instr->FalseLabel(chunk_), check_needed); |
| 2197 | 2179 |
| 2198 EmitBranch(true_block, false_block, true_cond); | 2180 EmitBranch(instr, true_cond); |
| 2199 } | 2181 } |
| 2200 | 2182 |
| 2201 | 2183 |
| 2202 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 2184 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
| 2203 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 2204 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 2205 | |
| 2206 Condition is_smi; | 2185 Condition is_smi; |
| 2207 if (instr->value()->IsRegister()) { | 2186 if (instr->value()->IsRegister()) { |
| 2208 Register input = ToRegister(instr->value()); | 2187 Register input = ToRegister(instr->value()); |
| 2209 is_smi = masm()->CheckSmi(input); | 2188 is_smi = masm()->CheckSmi(input); |
| 2210 } else { | 2189 } else { |
| 2211 Operand input = ToOperand(instr->value()); | 2190 Operand input = ToOperand(instr->value()); |
| 2212 is_smi = masm()->CheckSmi(input); | 2191 is_smi = masm()->CheckSmi(input); |
| 2213 } | 2192 } |
| 2214 EmitBranch(true_block, false_block, is_smi); | 2193 EmitBranch(instr, is_smi); |
| 2215 } | 2194 } |
| 2216 | 2195 |
| 2217 | 2196 |
| 2218 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { | 2197 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
| 2219 Register input = ToRegister(instr->value()); | 2198 Register input = ToRegister(instr->value()); |
| 2220 Register temp = ToRegister(instr->temp()); | 2199 Register temp = ToRegister(instr->temp()); |
| 2221 | 2200 |
| 2222 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2201 if (!instr->hydrogen()->value()->IsHeapObject()) { |
| 2223 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2202 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); |
| 2224 | 2203 } |
| 2225 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); | |
| 2226 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); | 2204 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); |
| 2227 __ testb(FieldOperand(temp, Map::kBitFieldOffset), | 2205 __ testb(FieldOperand(temp, Map::kBitFieldOffset), |
| 2228 Immediate(1 << Map::kIsUndetectable)); | 2206 Immediate(1 << Map::kIsUndetectable)); |
| 2229 EmitBranch(true_block, false_block, not_zero); | 2207 EmitBranch(instr, not_zero); |
| 2230 } | 2208 } |
| 2231 | 2209 |
| 2232 | 2210 |
| 2233 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { | 2211 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { |
| 2234 Token::Value op = instr->op(); | 2212 Token::Value op = instr->op(); |
| 2235 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 2236 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 2237 | 2213 |
| 2238 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2214 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
| 2239 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2215 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2240 | 2216 |
| 2241 Condition condition = TokenToCondition(op, false); | 2217 Condition condition = TokenToCondition(op, false); |
| 2242 __ testq(rax, rax); | 2218 __ testq(rax, rax); |
| 2243 | 2219 |
| 2244 EmitBranch(true_block, false_block, condition); | 2220 EmitBranch(instr, condition); |
| 2245 } | 2221 } |
| 2246 | 2222 |
| 2247 | 2223 |
| 2248 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { | 2224 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { |
| 2249 InstanceType from = instr->from(); | 2225 InstanceType from = instr->from(); |
| 2250 InstanceType to = instr->to(); | 2226 InstanceType to = instr->to(); |
| 2251 if (from == FIRST_TYPE) return to; | 2227 if (from == FIRST_TYPE) return to; |
| 2252 ASSERT(from == to || to == LAST_TYPE); | 2228 ASSERT(from == to || to == LAST_TYPE); |
| 2253 return from; | 2229 return from; |
| 2254 } | 2230 } |
| 2255 | 2231 |
| 2256 | 2232 |
| 2257 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { | 2233 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { |
| 2258 InstanceType from = instr->from(); | 2234 InstanceType from = instr->from(); |
| 2259 InstanceType to = instr->to(); | 2235 InstanceType to = instr->to(); |
| 2260 if (from == to) return equal; | 2236 if (from == to) return equal; |
| 2261 if (to == LAST_TYPE) return above_equal; | 2237 if (to == LAST_TYPE) return above_equal; |
| 2262 if (from == FIRST_TYPE) return below_equal; | 2238 if (from == FIRST_TYPE) return below_equal; |
| 2263 UNREACHABLE(); | 2239 UNREACHABLE(); |
| 2264 return equal; | 2240 return equal; |
| 2265 } | 2241 } |
| 2266 | 2242 |
| 2267 | 2243 |
| 2268 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 2244 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
| 2269 Register input = ToRegister(instr->value()); | 2245 Register input = ToRegister(instr->value()); |
| 2270 | 2246 |
| 2271 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2247 if (!instr->hydrogen()->value()->IsHeapObject()) { |
| 2272 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2248 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); |
| 2273 | 2249 } |
| 2274 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
| 2275 | |
| 2276 __ JumpIfSmi(input, false_label); | |
| 2277 | 2250 |
| 2278 __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister); | 2251 __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister); |
| 2279 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); | 2252 EmitBranch(instr, BranchCondition(instr->hydrogen())); |
| 2280 } | 2253 } |
| 2281 | 2254 |
| 2282 | 2255 |
| 2283 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { | 2256 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
| 2284 Register input = ToRegister(instr->value()); | 2257 Register input = ToRegister(instr->value()); |
| 2285 Register result = ToRegister(instr->result()); | 2258 Register result = ToRegister(instr->result()); |
| 2286 | 2259 |
| 2287 __ AssertString(input); | 2260 __ AssertString(input); |
| 2288 | 2261 |
| 2289 __ movl(result, FieldOperand(input, String::kHashFieldOffset)); | 2262 __ movl(result, FieldOperand(input, String::kHashFieldOffset)); |
| 2290 ASSERT(String::kHashShift >= kSmiTagSize); | 2263 ASSERT(String::kHashShift >= kSmiTagSize); |
| 2291 __ IndexFromHash(result, result); | 2264 __ IndexFromHash(result, result); |
| 2292 } | 2265 } |
| 2293 | 2266 |
| 2294 | 2267 |
| 2295 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 2268 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
| 2296 LHasCachedArrayIndexAndBranch* instr) { | 2269 LHasCachedArrayIndexAndBranch* instr) { |
| 2297 Register input = ToRegister(instr->value()); | 2270 Register input = ToRegister(instr->value()); |
| 2298 | 2271 |
| 2299 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 2300 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 2301 | |
| 2302 __ testl(FieldOperand(input, String::kHashFieldOffset), | 2272 __ testl(FieldOperand(input, String::kHashFieldOffset), |
| 2303 Immediate(String::kContainsCachedArrayIndexMask)); | 2273 Immediate(String::kContainsCachedArrayIndexMask)); |
| 2304 EmitBranch(true_block, false_block, equal); | 2274 EmitBranch(instr, equal); |
| 2305 } | 2275 } |
| 2306 | 2276 |
| 2307 | 2277 |
| 2308 // Branches to a label or falls through with the answer in the z flag. | 2278 // Branches to a label or falls through with the answer in the z flag. |
| 2309 // Trashes the temp register. | 2279 // Trashes the temp register. |
| 2310 void LCodeGen::EmitClassOfTest(Label* is_true, | 2280 void LCodeGen::EmitClassOfTest(Label* is_true, |
| 2311 Label* is_false, | 2281 Label* is_false, |
| 2312 Handle<String> class_name, | 2282 Handle<String> class_name, |
| 2313 Register input, | 2283 Register input, |
| 2314 Register temp, | 2284 Register temp, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2372 // End with the answer in the z flag. | 2342 // End with the answer in the z flag. |
| 2373 } | 2343 } |
| 2374 | 2344 |
| 2375 | 2345 |
| 2376 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 2346 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
| 2377 Register input = ToRegister(instr->value()); | 2347 Register input = ToRegister(instr->value()); |
| 2378 Register temp = ToRegister(instr->temp()); | 2348 Register temp = ToRegister(instr->temp()); |
| 2379 Register temp2 = ToRegister(instr->temp2()); | 2349 Register temp2 = ToRegister(instr->temp2()); |
| 2380 Handle<String> class_name = instr->hydrogen()->class_name(); | 2350 Handle<String> class_name = instr->hydrogen()->class_name(); |
| 2381 | 2351 |
| 2382 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2352 EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), |
| 2383 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2353 class_name, input, temp, temp2); |
| 2384 | 2354 |
| 2385 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 2355 EmitBranch(instr, equal); |
| 2386 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
| 2387 | |
| 2388 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | |
| 2389 | |
| 2390 EmitBranch(true_block, false_block, equal); | |
| 2391 } | 2356 } |
| 2392 | 2357 |
| 2393 | 2358 |
| 2394 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 2359 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
| 2395 Register reg = ToRegister(instr->value()); | 2360 Register reg = ToRegister(instr->value()); |
| 2396 int true_block = instr->true_block_id(); | |
| 2397 int false_block = instr->false_block_id(); | |
| 2398 | 2361 |
| 2399 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 2362 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
| 2400 EmitBranch(true_block, false_block, equal); | 2363 EmitBranch(instr, equal); |
| 2401 } | 2364 } |
| 2402 | 2365 |
| 2403 | 2366 |
| 2404 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2367 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| 2405 InstanceofStub stub(InstanceofStub::kNoFlags); | 2368 InstanceofStub stub(InstanceofStub::kNoFlags); |
| 2406 __ push(ToRegister(instr->left())); | 2369 __ push(ToRegister(instr->left())); |
| 2407 __ push(ToRegister(instr->right())); | 2370 __ push(ToRegister(instr->right())); |
| 2408 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 2371 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 2409 Label true_value, done; | 2372 Label true_value, done; |
| 2410 __ testq(rax, rax); | 2373 __ testq(rax, rax); |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2686 __ CompareRoot(target, Heap::kTheHoleValueRootIndex); | 2649 __ CompareRoot(target, Heap::kTheHoleValueRootIndex); |
| 2687 if (instr->hydrogen()->DeoptimizesOnHole()) { | 2650 if (instr->hydrogen()->DeoptimizesOnHole()) { |
| 2688 DeoptimizeIf(equal, instr->environment()); | 2651 DeoptimizeIf(equal, instr->environment()); |
| 2689 } else { | 2652 } else { |
| 2690 __ j(not_equal, &skip_assignment); | 2653 __ j(not_equal, &skip_assignment); |
| 2691 } | 2654 } |
| 2692 } | 2655 } |
| 2693 __ movq(target, value); | 2656 __ movq(target, value); |
| 2694 | 2657 |
| 2695 if (instr->hydrogen()->NeedsWriteBarrier()) { | 2658 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 2696 HType type = instr->hydrogen()->value()->type(); | |
| 2697 SmiCheck check_needed = | 2659 SmiCheck check_needed = |
| 2698 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 2660 instr->hydrogen()->value()->IsHeapObject() |
| 2661 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 2699 int offset = Context::SlotOffset(instr->slot_index()); | 2662 int offset = Context::SlotOffset(instr->slot_index()); |
| 2700 Register scratch = ToRegister(instr->temp()); | 2663 Register scratch = ToRegister(instr->temp()); |
| 2701 __ RecordWriteContextSlot(context, | 2664 __ RecordWriteContextSlot(context, |
| 2702 offset, | 2665 offset, |
| 2703 value, | 2666 value, |
| 2704 scratch, | 2667 scratch, |
| 2705 kSaveFPRegs, | 2668 kSaveFPRegs, |
| 2706 EMIT_REMEMBERED_SET, | 2669 EMIT_REMEMBERED_SET, |
| 2707 check_needed); | 2670 check_needed); |
| 2708 } | 2671 } |
| (...skipping 1183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3892 CALL_AS_FUNCTION, | 3855 CALL_AS_FUNCTION, |
| 3893 RDI_UNINITIALIZED); | 3856 RDI_UNINITIALIZED); |
| 3894 } | 3857 } |
| 3895 | 3858 |
| 3896 | 3859 |
| 3897 void LCodeGen::DoCallNew(LCallNew* instr) { | 3860 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 3898 ASSERT(ToRegister(instr->constructor()).is(rdi)); | 3861 ASSERT(ToRegister(instr->constructor()).is(rdi)); |
| 3899 ASSERT(ToRegister(instr->result()).is(rax)); | 3862 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3900 | 3863 |
| 3901 __ Set(rax, instr->arity()); | 3864 __ Set(rax, instr->arity()); |
| 3902 if (FLAG_optimize_constructed_arrays) { | 3865 // No cell in ebx for construct type feedback in optimized code |
| 3903 // No cell in ebx for construct type feedback in optimized code | 3866 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); |
| 3904 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); | 3867 __ Move(rbx, undefined_value); |
| 3905 __ Move(rbx, undefined_value); | |
| 3906 } | |
| 3907 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 3868 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
| 3908 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 3869 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3909 } | 3870 } |
| 3910 | 3871 |
| 3911 | 3872 |
| 3912 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { | 3873 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
| 3913 ASSERT(ToRegister(instr->constructor()).is(rdi)); | 3874 ASSERT(ToRegister(instr->constructor()).is(rdi)); |
| 3914 ASSERT(ToRegister(instr->result()).is(rax)); | 3875 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3915 ASSERT(FLAG_optimize_constructed_arrays); | |
| 3916 | 3876 |
| 3917 __ Set(rax, instr->arity()); | 3877 __ Set(rax, instr->arity()); |
| 3918 __ Move(rbx, instr->hydrogen()->property_cell()); | 3878 __ Move(rbx, instr->hydrogen()->property_cell()); |
| 3919 ElementsKind kind = instr->hydrogen()->elements_kind(); | 3879 ElementsKind kind = instr->hydrogen()->elements_kind(); |
| 3920 bool disable_allocation_sites = | 3880 bool disable_allocation_sites = |
| 3921 (AllocationSiteInfo::GetMode(kind) == TRACK_ALLOCATION_SITE); | 3881 (AllocationSiteInfo::GetMode(kind) == TRACK_ALLOCATION_SITE); |
| 3922 | 3882 |
| 3923 if (instr->arity() == 0) { | 3883 if (instr->arity() == 0) { |
| 3924 ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites); | 3884 ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites); |
| 3925 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 3885 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4014 HeapObject::kMapOffset, | 3974 HeapObject::kMapOffset, |
| 4015 kScratchRegister, | 3975 kScratchRegister, |
| 4016 temp, | 3976 temp, |
| 4017 kSaveFPRegs, | 3977 kSaveFPRegs, |
| 4018 OMIT_REMEMBERED_SET, | 3978 OMIT_REMEMBERED_SET, |
| 4019 OMIT_SMI_CHECK); | 3979 OMIT_SMI_CHECK); |
| 4020 } | 3980 } |
| 4021 } | 3981 } |
| 4022 | 3982 |
| 4023 // Do the store. | 3983 // Do the store. |
| 4024 HType type = instr->hydrogen()->value()->type(); | |
| 4025 SmiCheck check_needed = | 3984 SmiCheck check_needed = |
| 4026 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 3985 instr->hydrogen()->value()->IsHeapObject() |
| 3986 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 4027 | 3987 |
| 4028 Register write_register = object; | 3988 Register write_register = object; |
| 4029 if (!access.IsInobject()) { | 3989 if (!access.IsInobject()) { |
| 4030 write_register = ToRegister(instr->temp()); | 3990 write_register = ToRegister(instr->temp()); |
| 4031 __ movq(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); | 3991 __ movq(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 4032 } | 3992 } |
| 4033 | 3993 |
| 4034 if (instr->value()->IsConstantOperand()) { | 3994 if (instr->value()->IsConstantOperand()) { |
| 4035 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 3995 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 4036 if (operand_value->IsRegister()) { | 3996 if (operand_value->IsRegister()) { |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4255 } else { | 4215 } else { |
| 4256 Handle<Object> handle_value = ToHandle(operand_value); | 4216 Handle<Object> handle_value = ToHandle(operand_value); |
| 4257 __ Move(operand, handle_value); | 4217 __ Move(operand, handle_value); |
| 4258 } | 4218 } |
| 4259 } | 4219 } |
| 4260 | 4220 |
| 4261 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4221 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 4262 ASSERT(instr->value()->IsRegister()); | 4222 ASSERT(instr->value()->IsRegister()); |
| 4263 Register value = ToRegister(instr->value()); | 4223 Register value = ToRegister(instr->value()); |
| 4264 ASSERT(!instr->key()->IsConstantOperand()); | 4224 ASSERT(!instr->key()->IsConstantOperand()); |
| 4265 HType type = instr->hydrogen()->value()->type(); | |
| 4266 SmiCheck check_needed = | 4225 SmiCheck check_needed = |
| 4267 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 4226 instr->hydrogen()->value()->IsHeapObject() |
| 4227 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 4268 // Compute address of modified element and store it into key register. | 4228 // Compute address of modified element and store it into key register. |
| 4269 Register key_reg(ToRegister(key)); | 4229 Register key_reg(ToRegister(key)); |
| 4270 __ lea(key_reg, operand); | 4230 __ lea(key_reg, operand); |
| 4271 __ RecordWrite(elements, | 4231 __ RecordWrite(elements, |
| 4272 key_reg, | 4232 key_reg, |
| 4273 value, | 4233 value, |
| 4274 kSaveFPRegs, | 4234 kSaveFPRegs, |
| 4275 EMIT_REMEMBERED_SET, | 4235 EMIT_REMEMBERED_SET, |
| 4276 check_needed); | 4236 check_needed); |
| 4277 } | 4237 } |
| (...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4923 | 4883 |
| 4924 | 4884 |
| 4925 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 4885 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
| 4926 LOperand* input = instr->value(); | 4886 LOperand* input = instr->value(); |
| 4927 Condition cc = masm()->CheckSmi(ToRegister(input)); | 4887 Condition cc = masm()->CheckSmi(ToRegister(input)); |
| 4928 DeoptimizeIf(NegateCondition(cc), instr->environment()); | 4888 DeoptimizeIf(NegateCondition(cc), instr->environment()); |
| 4929 } | 4889 } |
| 4930 | 4890 |
| 4931 | 4891 |
| 4932 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 4892 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
| 4933 LOperand* input = instr->value(); | 4893 if (!instr->hydrogen()->value()->IsHeapObject()) { |
| 4934 Condition cc = masm()->CheckSmi(ToRegister(input)); | 4894 LOperand* input = instr->value(); |
| 4935 DeoptimizeIf(cc, instr->environment()); | 4895 Condition cc = masm()->CheckSmi(ToRegister(input)); |
| 4896 DeoptimizeIf(cc, instr->environment()); |
| 4897 } |
| 4936 } | 4898 } |
| 4937 | 4899 |
| 4938 | 4900 |
| 4939 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 4901 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
| 4940 Register input = ToRegister(instr->value()); | 4902 Register input = ToRegister(instr->value()); |
| 4941 | 4903 |
| 4942 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); | 4904 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); |
| 4943 | 4905 |
| 4944 if (instr->hydrogen()->is_interval_check()) { | 4906 if (instr->hydrogen()->is_interval_check()) { |
| 4945 InstanceType first; | 4907 InstanceType first; |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5077 | 5039 |
| 5078 if (!instr->hydrogen()->CanOmitPrototypeChecks()) { | 5040 if (!instr->hydrogen()->CanOmitPrototypeChecks()) { |
| 5079 for (int i = 0; i < prototypes->length(); i++) { | 5041 for (int i = 0; i < prototypes->length(); i++) { |
| 5080 __ LoadHeapObject(reg, prototypes->at(i)); | 5042 __ LoadHeapObject(reg, prototypes->at(i)); |
| 5081 DoCheckMapCommon(reg, maps->at(i), instr); | 5043 DoCheckMapCommon(reg, maps->at(i), instr); |
| 5082 } | 5044 } |
| 5083 } | 5045 } |
| 5084 } | 5046 } |
| 5085 | 5047 |
| 5086 | 5048 |
| 5049 void LCodeGen::DoAllocateObject(LAllocateObject* instr) { |
| 5050 class DeferredAllocateObject: public LDeferredCode { |
| 5051 public: |
| 5052 DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr) |
| 5053 : LDeferredCode(codegen), instr_(instr) { } |
| 5054 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } |
| 5055 virtual LInstruction* instr() { return instr_; } |
| 5056 private: |
| 5057 LAllocateObject* instr_; |
| 5058 }; |
| 5059 |
| 5060 DeferredAllocateObject* deferred = |
| 5061 new(zone()) DeferredAllocateObject(this, instr); |
| 5062 |
| 5063 Register result = ToRegister(instr->result()); |
| 5064 Register scratch = ToRegister(instr->temp()); |
| 5065 Handle<JSFunction> constructor = instr->hydrogen()->constructor(); |
| 5066 Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map(); |
| 5067 int instance_size = initial_map->instance_size(); |
| 5068 ASSERT(initial_map->pre_allocated_property_fields() + |
| 5069 initial_map->unused_property_fields() - |
| 5070 initial_map->inobject_properties() == 0); |
| 5071 |
| 5072 __ Allocate(instance_size, result, no_reg, scratch, deferred->entry(), |
| 5073 TAG_OBJECT); |
| 5074 |
| 5075 __ bind(deferred->exit()); |
| 5076 if (FLAG_debug_code) { |
| 5077 Label is_in_new_space; |
| 5078 __ JumpIfInNewSpace(result, scratch, &is_in_new_space); |
| 5079 __ Abort("Allocated object is not in new-space"); |
| 5080 __ bind(&is_in_new_space); |
| 5081 } |
| 5082 |
| 5083 // Load the initial map. |
| 5084 Register map = scratch; |
| 5085 __ LoadHeapObject(scratch, constructor); |
| 5086 __ movq(map, FieldOperand(scratch, JSFunction::kPrototypeOrInitialMapOffset)); |
| 5087 |
| 5088 if (FLAG_debug_code) { |
| 5089 __ AssertNotSmi(map); |
| 5090 __ cmpb(FieldOperand(map, Map::kInstanceSizeOffset), |
| 5091 Immediate(instance_size >> kPointerSizeLog2)); |
| 5092 __ Assert(equal, "Unexpected instance size"); |
| 5093 __ cmpb(FieldOperand(map, Map::kPreAllocatedPropertyFieldsOffset), |
| 5094 Immediate(initial_map->pre_allocated_property_fields())); |
| 5095 __ Assert(equal, "Unexpected pre-allocated property fields count"); |
| 5096 __ cmpb(FieldOperand(map, Map::kUnusedPropertyFieldsOffset), |
| 5097 Immediate(initial_map->unused_property_fields())); |
| 5098 __ Assert(equal, "Unexpected unused property fields count"); |
| 5099 __ cmpb(FieldOperand(map, Map::kInObjectPropertiesOffset), |
| 5100 Immediate(initial_map->inobject_properties())); |
| 5101 __ Assert(equal, "Unexpected in-object property fields count"); |
| 5102 } |
| 5103 |
| 5104 // Initialize map and fields of the newly allocated object. |
| 5105 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); |
| 5106 __ movq(FieldOperand(result, JSObject::kMapOffset), map); |
| 5107 __ LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex); |
| 5108 __ movq(FieldOperand(result, JSObject::kElementsOffset), scratch); |
| 5109 __ movq(FieldOperand(result, JSObject::kPropertiesOffset), scratch); |
| 5110 if (initial_map->inobject_properties() != 0) { |
| 5111 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); |
| 5112 for (int i = 0; i < initial_map->inobject_properties(); i++) { |
| 5113 int property_offset = JSObject::kHeaderSize + i * kPointerSize; |
| 5114 __ movq(FieldOperand(result, property_offset), scratch); |
| 5115 } |
| 5116 } |
| 5117 } |
| 5118 |
| 5119 |
| 5120 void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) { |
| 5121 Register result = ToRegister(instr->result()); |
| 5122 Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map(); |
| 5123 int instance_size = initial_map->instance_size(); |
| 5124 |
| 5125 // TODO(3095996): Get rid of this. For now, we need to make the |
| 5126 // result register contain a valid pointer because it is already |
| 5127 // contained in the register pointer map. |
| 5128 __ Set(result, 0); |
| 5129 |
| 5130 PushSafepointRegistersScope scope(this); |
| 5131 __ Push(Smi::FromInt(instance_size)); |
| 5132 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr); |
| 5133 __ StoreToSafepointRegisterSlot(result, rax); |
| 5134 } |
| 5135 |
| 5136 |
| 5087 void LCodeGen::DoAllocate(LAllocate* instr) { | 5137 void LCodeGen::DoAllocate(LAllocate* instr) { |
| 5088 class DeferredAllocate: public LDeferredCode { | 5138 class DeferredAllocate: public LDeferredCode { |
| 5089 public: | 5139 public: |
| 5090 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) | 5140 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) |
| 5091 : LDeferredCode(codegen), instr_(instr) { } | 5141 : LDeferredCode(codegen), instr_(instr) { } |
| 5092 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } | 5142 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } |
| 5093 virtual LInstruction* instr() { return instr_; } | 5143 virtual LInstruction* instr() { return instr_; } |
| 5094 private: | 5144 private: |
| 5095 LAllocate* instr_; | 5145 LAllocate* instr_; |
| 5096 }; | 5146 }; |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5252 } else if (operand->IsRegister()) { | 5302 } else if (operand->IsRegister()) { |
| 5253 __ push(ToRegister(operand)); | 5303 __ push(ToRegister(operand)); |
| 5254 } else { | 5304 } else { |
| 5255 __ push(ToOperand(operand)); | 5305 __ push(ToOperand(operand)); |
| 5256 } | 5306 } |
| 5257 } | 5307 } |
| 5258 | 5308 |
| 5259 | 5309 |
| 5260 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 5310 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
| 5261 Register input = ToRegister(instr->value()); | 5311 Register input = ToRegister(instr->value()); |
| 5262 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 5263 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 5264 Label* true_label = chunk_->GetAssemblyLabel(true_block); | |
| 5265 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
| 5266 | 5312 |
| 5267 Condition final_branch_condition = | 5313 Condition final_branch_condition = |
| 5268 EmitTypeofIs(true_label, false_label, input, instr->type_literal()); | 5314 EmitTypeofIs(instr->TrueLabel(chunk_), |
| 5315 instr->FalseLabel(chunk_), input, instr->type_literal()); |
| 5269 if (final_branch_condition != no_condition) { | 5316 if (final_branch_condition != no_condition) { |
| 5270 EmitBranch(true_block, false_block, final_branch_condition); | 5317 EmitBranch(instr, final_branch_condition); |
| 5271 } | 5318 } |
| 5272 } | 5319 } |
| 5273 | 5320 |
| 5274 | 5321 |
| 5275 Condition LCodeGen::EmitTypeofIs(Label* true_label, | 5322 Condition LCodeGen::EmitTypeofIs(Label* true_label, |
| 5276 Label* false_label, | 5323 Label* false_label, |
| 5277 Register input, | 5324 Register input, |
| 5278 Handle<String> type_name) { | 5325 Handle<String> type_name) { |
| 5279 Condition final_branch_condition = no_condition; | 5326 Condition final_branch_condition = no_condition; |
| 5280 if (type_name->Equals(heap()->number_string())) { | 5327 if (type_name->Equals(heap()->number_string())) { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5343 } else { | 5390 } else { |
| 5344 __ jmp(false_label); | 5391 __ jmp(false_label); |
| 5345 } | 5392 } |
| 5346 | 5393 |
| 5347 return final_branch_condition; | 5394 return final_branch_condition; |
| 5348 } | 5395 } |
| 5349 | 5396 |
| 5350 | 5397 |
| 5351 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 5398 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
| 5352 Register temp = ToRegister(instr->temp()); | 5399 Register temp = ToRegister(instr->temp()); |
| 5353 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 5354 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 5355 | 5400 |
| 5356 EmitIsConstructCall(temp); | 5401 EmitIsConstructCall(temp); |
| 5357 EmitBranch(true_block, false_block, equal); | 5402 EmitBranch(instr, equal); |
| 5358 } | 5403 } |
| 5359 | 5404 |
| 5360 | 5405 |
| 5361 void LCodeGen::EmitIsConstructCall(Register temp) { | 5406 void LCodeGen::EmitIsConstructCall(Register temp) { |
| 5362 // Get the frame pointer for the calling frame. | 5407 // Get the frame pointer for the calling frame. |
| 5363 __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 5408 __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 5364 | 5409 |
| 5365 // Skip the arguments adaptor frame if it exists. | 5410 // Skip the arguments adaptor frame if it exists. |
| 5366 Label check_frame_marker; | 5411 Label check_frame_marker; |
| 5367 __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset), | 5412 __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset), |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5499 // the deferred code. | 5544 // the deferred code. |
| 5500 } | 5545 } |
| 5501 } | 5546 } |
| 5502 | 5547 |
| 5503 | 5548 |
| 5504 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { | 5549 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { |
| 5505 // This is a pseudo-instruction that ensures that the environment here is | 5550 // This is a pseudo-instruction that ensures that the environment here is |
| 5506 // properly registered for deoptimization and records the assembler's PC | 5551 // properly registered for deoptimization and records the assembler's PC |
| 5507 // offset. | 5552 // offset. |
| 5508 LEnvironment* environment = instr->environment(); | 5553 LEnvironment* environment = instr->environment(); |
| 5509 environment->SetSpilledRegisters(instr->SpilledRegisterArray(), | |
| 5510 instr->SpilledDoubleRegisterArray()); | |
| 5511 | 5554 |
| 5512 // If the environment were already registered, we would have no way of | 5555 // If the environment were already registered, we would have no way of |
| 5513 // backpatching it with the spill slot operands. | 5556 // backpatching it with the spill slot operands. |
| 5514 ASSERT(!environment->HasBeenRegistered()); | 5557 ASSERT(!environment->HasBeenRegistered()); |
| 5515 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 5558 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
| 5516 ASSERT(osr_pc_offset_ == -1); | 5559 |
| 5517 osr_pc_offset_ = masm()->pc_offset(); | 5560 // Normally we record the first unknown OSR value as the entrypoint to the OSR |
| 5561 // code, but if there were none, record the entrypoint here. |
| 5562 if (osr_pc_offset_ == -1) osr_pc_offset_ = masm()->pc_offset(); |
| 5518 } | 5563 } |
| 5519 | 5564 |
| 5520 | 5565 |
| 5521 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { | 5566 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { |
| 5522 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 5567 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
| 5523 DeoptimizeIf(equal, instr->environment()); | 5568 DeoptimizeIf(equal, instr->environment()); |
| 5524 | 5569 |
| 5525 Register null_value = rdi; | 5570 Register null_value = rdi; |
| 5526 __ LoadRoot(null_value, Heap::kNullValueRootIndex); | 5571 __ LoadRoot(null_value, Heap::kNullValueRootIndex); |
| 5527 __ cmpq(rax, null_value); | 5572 __ cmpq(rax, null_value); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5605 FixedArray::kHeaderSize - kPointerSize)); | 5650 FixedArray::kHeaderSize - kPointerSize)); |
| 5606 __ bind(&done); | 5651 __ bind(&done); |
| 5607 } | 5652 } |
| 5608 | 5653 |
| 5609 | 5654 |
| 5610 #undef __ | 5655 #undef __ |
| 5611 | 5656 |
| 5612 } } // namespace v8::internal | 5657 } } // namespace v8::internal |
| 5613 | 5658 |
| 5614 #endif // V8_TARGET_ARCH_X64 | 5659 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |