Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(728)

Side by Side Diff: src/x64/lithium-codegen-x64.cc

Issue 142813003: A64: Synchronize with r15358. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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, &not_string, Label::kNear); 1968 __ j(above_equal, &not_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(&not_string); 1972 __ bind(&not_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, &not_heap_number, Label::kNear); 1979 __ j(not_equal, &not_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(&not_heap_number); 1984 __ bind(&not_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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698