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

Side by Side Diff: src/ia32/lithium-codegen-ia32.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/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-ia32.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 private: 67 private:
68 LCodeGen* codegen_; 68 LCodeGen* codegen_;
69 LPointerMap* pointers_; 69 LPointerMap* pointers_;
70 Safepoint::DeoptMode deopt_mode_; 70 Safepoint::DeoptMode deopt_mode_;
71 }; 71 };
72 72
73 73
74 #define __ masm()-> 74 #define __ masm()->
75 75
76 bool LCodeGen::GenerateCode() { 76 bool LCodeGen::GenerateCode() {
77 HPhase phase("Z_Code generation", chunk()); 77 LPhase phase("Z_Code generation", chunk());
78 ASSERT(is_unused()); 78 ASSERT(is_unused());
79 status_ = GENERATING; 79 status_ = GENERATING;
80 80
81 // Open a frame scope to indicate that there is a frame on the stack. The 81 // Open a frame scope to indicate that there is a frame on the stack. The
82 // MANUAL indicates that the scope shouldn't actually generate code to set up 82 // MANUAL indicates that the scope shouldn't actually generate code to set up
83 // the frame (that is done in GeneratePrologue). 83 // the frame (that is done in GeneratePrologue).
84 FrameScope frame_scope(masm_, StackFrame::MANUAL); 84 FrameScope frame_scope(masm_, StackFrame::MANUAL);
85 85
86 support_aligned_spilled_doubles_ = info()->IsOptimizing(); 86 support_aligned_spilled_doubles_ = info()->IsOptimizing();
87 87
(...skipping 14 matching lines...) Expand all
102 ASSERT(is_done()); 102 ASSERT(is_done());
103 code->set_stack_slots(GetStackSlotCount()); 103 code->set_stack_slots(GetStackSlotCount());
104 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); 104 code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
105 if (FLAG_weak_embedded_maps_in_optimized_code) { 105 if (FLAG_weak_embedded_maps_in_optimized_code) {
106 RegisterDependentCodeForEmbeddedMaps(code); 106 RegisterDependentCodeForEmbeddedMaps(code);
107 } 107 }
108 PopulateDeoptimizationData(code); 108 PopulateDeoptimizationData(code);
109 if (!info()->IsStub()) { 109 if (!info()->IsStub()) {
110 Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code); 110 Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
111 } 111 }
112 info()->CommitDependentMaps(code); 112 info()->CommitDependencies(code);
113 } 113 }
114 114
115 115
116 void LCodeGen::Abort(const char* reason) { 116 void LCodeGen::Abort(const char* reason) {
117 info()->set_bailout_reason(reason); 117 info()->set_bailout_reason(reason);
118 status_ = ABORTED; 118 status_ = ABORTED;
119 } 119 }
120 120
121 121
122 void LCodeGen::Comment(const char* format, ...) { 122 void LCodeGen::Comment(const char* format, ...) {
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 break; 650 break;
651 case STUB: 651 case STUB:
652 translation->BeginCompiledStubFrame(); 652 translation->BeginCompiledStubFrame();
653 break; 653 break;
654 default: 654 default:
655 UNREACHABLE(); 655 UNREACHABLE();
656 } 656 }
657 657
658 for (int i = 0; i < translation_size; ++i) { 658 for (int i = 0; i < translation_size; ++i) {
659 LOperand* value = environment->values()->at(i); 659 LOperand* value = environment->values()->at(i);
660 // spilled_registers_ and spilled_double_registers_ are either
661 // both NULL or both set.
662 if (environment->spilled_registers() != NULL && value != NULL) {
663 if (value->IsRegister() &&
664 environment->spilled_registers()[value->index()] != NULL) {
665 translation->MarkDuplicate();
666 AddToTranslation(translation,
667 environment->spilled_registers()[value->index()],
668 environment->HasTaggedValueAt(i),
669 environment->HasUint32ValueAt(i));
670 } else if (
671 value->IsDoubleRegister() &&
672 environment->spilled_double_registers()[value->index()] != NULL) {
673 translation->MarkDuplicate();
674 AddToTranslation(
675 translation,
676 environment->spilled_double_registers()[value->index()],
677 false,
678 false);
679 }
680 }
681 660
682 // TODO(mstarzinger): Introduce marker operands to indicate that this value 661 // TODO(mstarzinger): Introduce marker operands to indicate that this value
683 // is not present and must be reconstructed from the deoptimizer. Currently 662 // is not present and must be reconstructed from the deoptimizer. Currently
684 // this is only used for the arguments object. 663 // this is only used for the arguments object.
685 if (value == NULL) { 664 if (value == NULL) {
686 int arguments_count = environment->values()->length() - translation_size; 665 int arguments_count = environment->values()->length() - translation_size;
687 translation->BeginArgumentsObject(arguments_count); 666 translation->BeginArgumentsObject(arguments_count);
688 for (int i = 0; i < arguments_count; ++i) { 667 for (int i = 0; i < arguments_count; ++i) {
689 LOperand* value = environment->values()->at(translation_size + i); 668 LOperand* value = environment->values()->at(translation_size + i);
690 ASSERT(environment->spilled_registers() == NULL ||
691 !value->IsRegister() ||
692 environment->spilled_registers()[value->index()] == NULL);
693 ASSERT(environment->spilled_registers() == NULL ||
694 !value->IsDoubleRegister() ||
695 environment->spilled_double_registers()[value->index()] == NULL);
696 AddToTranslation(translation, 669 AddToTranslation(translation,
697 value, 670 value,
698 environment->HasTaggedValueAt(translation_size + i), 671 environment->HasTaggedValueAt(translation_size + i),
699 environment->HasUint32ValueAt(translation_size + i)); 672 environment->HasUint32ValueAt(translation_size + i));
700 } 673 }
701 continue; 674 continue;
702 } 675 }
703 676
704 AddToTranslation(translation, 677 AddToTranslation(translation,
705 value, 678 value,
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
1182 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 1155 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
1183 break; 1156 break;
1184 } 1157 }
1185 default: 1158 default:
1186 UNREACHABLE(); 1159 UNREACHABLE();
1187 } 1160 }
1188 } 1161 }
1189 1162
1190 1163
1191 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 1164 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
1192 // Nothing to do. 1165 // Record the address of the first unknown OSR value as the place to enter.
1166 if (osr_pc_offset_ == -1) osr_pc_offset_ = masm()->pc_offset();
1193 } 1167 }
1194 1168
1195 1169
1196 void LCodeGen::DoModI(LModI* instr) { 1170 void LCodeGen::DoModI(LModI* instr) {
1197 HMod* hmod = instr->hydrogen(); 1171 HMod* hmod = instr->hydrogen();
1198 HValue* left = hmod->left(); 1172 HValue* left = hmod->left();
1199 HValue* right = hmod->right(); 1173 HValue* right = hmod->right();
1200 if (hmod->HasPowerOf2Divisor()) { 1174 if (hmod->HasPowerOf2Divisor()) {
1201 // TODO(svenpanne) We should really do the strength reduction on the 1175 // TODO(svenpanne) We should really do the strength reduction on the
1202 // Hydrogen level. 1176 // Hydrogen level.
(...skipping 13 matching lines...) Expand all
1216 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1190 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1217 DeoptimizeIf(zero, instr->environment()); 1191 DeoptimizeIf(zero, instr->environment());
1218 } 1192 }
1219 __ jmp(&done, Label::kNear); 1193 __ jmp(&done, Label::kNear);
1220 } 1194 }
1221 1195
1222 __ bind(&left_is_not_negative); 1196 __ bind(&left_is_not_negative);
1223 __ and_(left_reg, divisor - 1); 1197 __ and_(left_reg, divisor - 1);
1224 __ bind(&done); 1198 __ bind(&done);
1225 1199
1226 } else if (hmod->has_fixed_right_arg()) { 1200 } else if (hmod->fixed_right_arg().has_value) {
1227 Register left_reg = ToRegister(instr->left()); 1201 Register left_reg = ToRegister(instr->left());
1228 ASSERT(left_reg.is(ToRegister(instr->result()))); 1202 ASSERT(left_reg.is(ToRegister(instr->result())));
1229 Register right_reg = ToRegister(instr->right()); 1203 Register right_reg = ToRegister(instr->right());
1230 1204
1231 int32_t divisor = hmod->fixed_right_arg_value(); 1205 int32_t divisor = hmod->fixed_right_arg().value;
1232 ASSERT(IsPowerOf2(divisor)); 1206 ASSERT(IsPowerOf2(divisor));
1233 1207
1234 // Check if our assumption of a fixed right operand still holds. 1208 // Check if our assumption of a fixed right operand still holds.
1235 __ cmp(right_reg, Immediate(divisor)); 1209 __ cmp(right_reg, Immediate(divisor));
1236 DeoptimizeIf(not_equal, instr->environment()); 1210 DeoptimizeIf(not_equal, instr->environment());
1237 1211
1238 Label left_is_not_negative, done; 1212 Label left_is_not_negative, done;
1239 if (left->CanBeNegative()) { 1213 if (left->CanBeNegative()) {
1240 __ test(left_reg, Operand(left_reg)); 1214 __ test(left_reg, Operand(left_reg));
1241 __ j(not_sign, &left_is_not_negative, Label::kNear); 1215 __ j(not_sign, &left_is_not_negative, Label::kNear);
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after
1829 } 1803 }
1830 1804
1831 1805
1832 void LCodeGen::DoValueOf(LValueOf* instr) { 1806 void LCodeGen::DoValueOf(LValueOf* instr) {
1833 Register input = ToRegister(instr->value()); 1807 Register input = ToRegister(instr->value());
1834 Register result = ToRegister(instr->result()); 1808 Register result = ToRegister(instr->result());
1835 Register map = ToRegister(instr->temp()); 1809 Register map = ToRegister(instr->temp());
1836 ASSERT(input.is(result)); 1810 ASSERT(input.is(result));
1837 1811
1838 Label done; 1812 Label done;
1839 // If the object is a smi return the object. 1813
1840 __ JumpIfSmi(input, &done, Label::kNear); 1814 if (!instr->hydrogen()->value()->IsHeapObject()) {
1815 // If the object is a smi return the object.
1816 __ JumpIfSmi(input, &done, Label::kNear);
1817 }
1841 1818
1842 // If the object is not a value type, return the object. 1819 // If the object is not a value type, return the object.
1843 __ CmpObjectType(input, JS_VALUE_TYPE, map); 1820 __ CmpObjectType(input, JS_VALUE_TYPE, map);
1844 __ j(not_equal, &done, Label::kNear); 1821 __ j(not_equal, &done, Label::kNear);
1845 __ mov(result, FieldOperand(input, JSValue::kValueOffset)); 1822 __ mov(result, FieldOperand(input, JSValue::kValueOffset));
1846 1823
1847 __ bind(&done); 1824 __ bind(&done);
1848 } 1825 }
1849 1826
1850 1827
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
2080 2057
2081 2058
2082 int LCodeGen::GetNextEmittedBlock() const { 2059 int LCodeGen::GetNextEmittedBlock() const {
2083 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { 2060 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) {
2084 if (!chunk_->GetLabel(i)->HasReplacement()) return i; 2061 if (!chunk_->GetLabel(i)->HasReplacement()) return i;
2085 } 2062 }
2086 return -1; 2063 return -1;
2087 } 2064 }
2088 2065
2089 2066
2090 void LCodeGen::EmitBranch(int left_block, int right_block, Condition cc) { 2067 template<class InstrType>
2068 void LCodeGen::EmitBranch(InstrType instr, Condition cc) {
2069 int right_block = instr->FalseDestination(chunk_);
2070 int left_block = instr->TrueDestination(chunk_);
2071
2091 int next_block = GetNextEmittedBlock(); 2072 int next_block = GetNextEmittedBlock();
2092 right_block = chunk_->LookupDestination(right_block);
2093 left_block = chunk_->LookupDestination(left_block);
2094 2073
2095 if (right_block == left_block) { 2074 if (right_block == left_block) {
2096 EmitGoto(left_block); 2075 EmitGoto(left_block);
2097 } else if (left_block == next_block) { 2076 } else if (left_block == next_block) {
2098 __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); 2077 __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block));
2099 } else if (right_block == next_block) { 2078 } else if (right_block == next_block) {
2100 __ j(cc, chunk_->GetAssemblyLabel(left_block)); 2079 __ j(cc, chunk_->GetAssemblyLabel(left_block));
2101 } else { 2080 } else {
2102 __ j(cc, chunk_->GetAssemblyLabel(left_block)); 2081 __ j(cc, chunk_->GetAssemblyLabel(left_block));
2103 __ jmp(chunk_->GetAssemblyLabel(right_block)); 2082 __ jmp(chunk_->GetAssemblyLabel(right_block));
2104 } 2083 }
2105 } 2084 }
2106 2085
2107 2086
2108 void LCodeGen::DoBranch(LBranch* instr) { 2087 void LCodeGen::DoBranch(LBranch* instr) {
2109 int true_block = chunk_->LookupDestination(instr->true_block_id());
2110 int false_block = chunk_->LookupDestination(instr->false_block_id());
2111
2112 Representation r = instr->hydrogen()->value()->representation(); 2088 Representation r = instr->hydrogen()->value()->representation();
2113 if (r.IsSmiOrInteger32()) { 2089 if (r.IsSmiOrInteger32()) {
2114 ASSERT(!info()->IsStub()); 2090 ASSERT(!info()->IsStub());
2115 Register reg = ToRegister(instr->value()); 2091 Register reg = ToRegister(instr->value());
2116 __ test(reg, Operand(reg)); 2092 __ test(reg, Operand(reg));
2117 EmitBranch(true_block, false_block, not_zero); 2093 EmitBranch(instr, not_zero);
2118 } else if (r.IsDouble()) { 2094 } else if (r.IsDouble()) {
2119 ASSERT(!info()->IsStub()); 2095 ASSERT(!info()->IsStub());
2120 CpuFeatureScope scope(masm(), SSE2); 2096 CpuFeatureScope scope(masm(), SSE2);
2121 XMMRegister reg = ToDoubleRegister(instr->value()); 2097 XMMRegister reg = ToDoubleRegister(instr->value());
2122 __ xorps(xmm0, xmm0); 2098 __ xorps(xmm0, xmm0);
2123 __ ucomisd(reg, xmm0); 2099 __ ucomisd(reg, xmm0);
2124 EmitBranch(true_block, false_block, not_equal); 2100 EmitBranch(instr, not_equal);
2125 } else { 2101 } else {
2126 ASSERT(r.IsTagged()); 2102 ASSERT(r.IsTagged());
2127 Register reg = ToRegister(instr->value()); 2103 Register reg = ToRegister(instr->value());
2128 HType type = instr->hydrogen()->value()->type(); 2104 HType type = instr->hydrogen()->value()->type();
2129 if (type.IsBoolean()) { 2105 if (type.IsBoolean()) {
2130 ASSERT(!info()->IsStub()); 2106 ASSERT(!info()->IsStub());
2131 __ cmp(reg, factory()->true_value()); 2107 __ cmp(reg, factory()->true_value());
2132 EmitBranch(true_block, false_block, equal); 2108 EmitBranch(instr, equal);
2133 } else if (type.IsSmi()) { 2109 } else if (type.IsSmi()) {
2134 ASSERT(!info()->IsStub()); 2110 ASSERT(!info()->IsStub());
2135 __ test(reg, Operand(reg)); 2111 __ test(reg, Operand(reg));
2136 EmitBranch(true_block, false_block, not_equal); 2112 EmitBranch(instr, not_equal);
2113 } else if (type.IsJSArray()) {
2114 ASSERT(!info()->IsStub());
2115 EmitBranch(instr, no_condition);
2116 } else if (type.IsHeapNumber()) {
2117 ASSERT(!info()->IsStub());
2118 CpuFeatureScope scope(masm(), SSE2);
2119 __ xorps(xmm0, xmm0);
2120 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset));
2121 EmitBranch(instr, not_equal);
2122 } else if (type.IsString()) {
2123 ASSERT(!info()->IsStub());
2124 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0));
2125 EmitBranch(instr, not_equal);
2137 } else { 2126 } else {
2138 Label* true_label = chunk_->GetAssemblyLabel(true_block);
2139 Label* false_label = chunk_->GetAssemblyLabel(false_block);
2140
2141 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); 2127 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
2142 // Avoid deopts in the case where we've never executed this path before. 2128 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();
2143 if (expected.IsEmpty()) expected = ToBooleanStub::all_types();
2144 2129
2145 if (expected.Contains(ToBooleanStub::UNDEFINED)) { 2130 if (expected.Contains(ToBooleanStub::UNDEFINED)) {
2146 // undefined -> false. 2131 // undefined -> false.
2147 __ cmp(reg, factory()->undefined_value()); 2132 __ cmp(reg, factory()->undefined_value());
2148 __ j(equal, false_label); 2133 __ j(equal, instr->FalseLabel(chunk_));
2149 } 2134 }
2150 if (expected.Contains(ToBooleanStub::BOOLEAN)) { 2135 if (expected.Contains(ToBooleanStub::BOOLEAN)) {
2151 // true -> true. 2136 // true -> true.
2152 __ cmp(reg, factory()->true_value()); 2137 __ cmp(reg, factory()->true_value());
2153 __ j(equal, true_label); 2138 __ j(equal, instr->TrueLabel(chunk_));
2154 // false -> false. 2139 // false -> false.
2155 __ cmp(reg, factory()->false_value()); 2140 __ cmp(reg, factory()->false_value());
2156 __ j(equal, false_label); 2141 __ j(equal, instr->FalseLabel(chunk_));
2157 } 2142 }
2158 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { 2143 if (expected.Contains(ToBooleanStub::NULL_TYPE)) {
2159 // 'null' -> false. 2144 // 'null' -> false.
2160 __ cmp(reg, factory()->null_value()); 2145 __ cmp(reg, factory()->null_value());
2161 __ j(equal, false_label); 2146 __ j(equal, instr->FalseLabel(chunk_));
2162 } 2147 }
2163 2148
2164 if (expected.Contains(ToBooleanStub::SMI)) { 2149 if (expected.Contains(ToBooleanStub::SMI)) {
2165 // Smis: 0 -> false, all other -> true. 2150 // Smis: 0 -> false, all other -> true.
2166 __ test(reg, Operand(reg)); 2151 __ test(reg, Operand(reg));
2167 __ j(equal, false_label); 2152 __ j(equal, instr->FalseLabel(chunk_));
2168 __ JumpIfSmi(reg, true_label); 2153 __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2169 } else if (expected.NeedsMap()) { 2154 } else if (expected.NeedsMap()) {
2170 // If we need a map later and have a Smi -> deopt. 2155 // If we need a map later and have a Smi -> deopt.
2171 __ test(reg, Immediate(kSmiTagMask)); 2156 __ test(reg, Immediate(kSmiTagMask));
2172 DeoptimizeIf(zero, instr->environment()); 2157 DeoptimizeIf(zero, instr->environment());
2173 } 2158 }
2174 2159
2175 Register map = no_reg; // Keep the compiler happy. 2160 Register map = no_reg; // Keep the compiler happy.
2176 if (expected.NeedsMap()) { 2161 if (expected.NeedsMap()) {
2177 map = ToRegister(instr->temp()); 2162 map = ToRegister(instr->temp());
2178 ASSERT(!map.is(reg)); 2163 ASSERT(!map.is(reg));
2179 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); 2164 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset));
2180 2165
2181 if (expected.CanBeUndetectable()) { 2166 if (expected.CanBeUndetectable()) {
2182 // Undetectable -> false. 2167 // Undetectable -> false.
2183 __ test_b(FieldOperand(map, Map::kBitFieldOffset), 2168 __ test_b(FieldOperand(map, Map::kBitFieldOffset),
2184 1 << Map::kIsUndetectable); 2169 1 << Map::kIsUndetectable);
2185 __ j(not_zero, false_label); 2170 __ j(not_zero, instr->FalseLabel(chunk_));
2186 } 2171 }
2187 } 2172 }
2188 2173
2189 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { 2174 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) {
2190 // spec object -> true. 2175 // spec object -> true.
2191 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); 2176 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
2192 __ j(above_equal, true_label); 2177 __ j(above_equal, instr->TrueLabel(chunk_));
2193 } 2178 }
2194 2179
2195 if (expected.Contains(ToBooleanStub::STRING)) { 2180 if (expected.Contains(ToBooleanStub::STRING)) {
2196 // String value -> false iff empty. 2181 // String value -> false iff empty.
2197 Label not_string; 2182 Label not_string;
2198 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); 2183 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
2199 __ j(above_equal, &not_string, Label::kNear); 2184 __ j(above_equal, &not_string, Label::kNear);
2200 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); 2185 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0));
2201 __ j(not_zero, true_label); 2186 __ j(not_zero, instr->TrueLabel(chunk_));
2202 __ jmp(false_label); 2187 __ jmp(instr->FalseLabel(chunk_));
2203 __ bind(&not_string); 2188 __ bind(&not_string);
2204 } 2189 }
2205 2190
2206 if (expected.Contains(ToBooleanStub::SYMBOL)) { 2191 if (expected.Contains(ToBooleanStub::SYMBOL)) {
2207 // Symbol value -> true. 2192 // Symbol value -> true.
2208 __ CmpInstanceType(map, SYMBOL_TYPE); 2193 __ CmpInstanceType(map, SYMBOL_TYPE);
2209 __ j(equal, true_label); 2194 __ j(equal, instr->TrueLabel(chunk_));
2210 } 2195 }
2211 2196
2212 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { 2197 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
2213 // heap number -> false iff +0, -0, or NaN. 2198 // heap number -> false iff +0, -0, or NaN.
2214 Label not_heap_number; 2199 Label not_heap_number;
2215 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 2200 __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
2216 factory()->heap_number_map()); 2201 factory()->heap_number_map());
2217 __ j(not_equal, &not_heap_number, Label::kNear); 2202 __ j(not_equal, &not_heap_number, Label::kNear);
2218 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { 2203 if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
2219 CpuFeatureScope scope(masm(), SSE2); 2204 CpuFeatureScope scope(masm(), SSE2);
2220 __ xorps(xmm0, xmm0); 2205 __ xorps(xmm0, xmm0);
2221 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); 2206 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset));
2222 } else { 2207 } else {
2223 __ fldz(); 2208 __ fldz();
2224 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); 2209 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset));
2225 __ FCmp(); 2210 __ FCmp();
2226 } 2211 }
2227 __ j(zero, false_label); 2212 __ j(zero, instr->FalseLabel(chunk_));
2228 __ jmp(true_label); 2213 __ jmp(instr->TrueLabel(chunk_));
2229 __ bind(&not_heap_number); 2214 __ bind(&not_heap_number);
2230 } 2215 }
2231 2216
2232 // We've seen something for the first time -> deopt. 2217 if (!expected.IsGeneric()) {
2233 DeoptimizeIf(no_condition, instr->environment()); 2218 // We've seen something for the first time -> deopt.
2219 // This can only happen if we are not generic already.
2220 DeoptimizeIf(no_condition, instr->environment());
2221 }
2234 } 2222 }
2235 } 2223 }
2236 } 2224 }
2237 2225
2238 2226
2239 void LCodeGen::EmitGoto(int block) { 2227 void LCodeGen::EmitGoto(int block) {
2240 if (!IsNextEmittedBlock(block)) { 2228 if (!IsNextEmittedBlock(block)) {
2241 __ jmp(chunk_->GetAssemblyLabel(chunk_->LookupDestination(block))); 2229 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block)));
2242 } 2230 }
2243 } 2231 }
2244 2232
2245 2233
2246 void LCodeGen::DoGoto(LGoto* instr) { 2234 void LCodeGen::DoGoto(LGoto* instr) {
2247 EmitGoto(instr->block_id()); 2235 EmitGoto(instr->block_id());
2248 } 2236 }
2249 2237
2250 2238
2251 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { 2239 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) {
(...skipping 20 matching lines...) Expand all
2272 default: 2260 default:
2273 UNREACHABLE(); 2261 UNREACHABLE();
2274 } 2262 }
2275 return cond; 2263 return cond;
2276 } 2264 }
2277 2265
2278 2266
2279 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { 2267 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
2280 LOperand* left = instr->left(); 2268 LOperand* left = instr->left();
2281 LOperand* right = instr->right(); 2269 LOperand* right = instr->right();
2282 int false_block = chunk_->LookupDestination(instr->false_block_id());
2283 int true_block = chunk_->LookupDestination(instr->true_block_id());
2284 Condition cc = TokenToCondition(instr->op(), instr->is_double()); 2270 Condition cc = TokenToCondition(instr->op(), instr->is_double());
2285 2271
2286 if (left->IsConstantOperand() && right->IsConstantOperand()) { 2272 if (left->IsConstantOperand() && right->IsConstantOperand()) {
2287 // We can statically evaluate the comparison. 2273 // We can statically evaluate the comparison.
2288 double left_val = ToDouble(LConstantOperand::cast(left)); 2274 double left_val = ToDouble(LConstantOperand::cast(left));
2289 double right_val = ToDouble(LConstantOperand::cast(right)); 2275 double right_val = ToDouble(LConstantOperand::cast(right));
2290 int next_block = 2276 int next_block = EvalComparison(instr->op(), left_val, right_val) ?
2291 EvalComparison(instr->op(), left_val, right_val) ? true_block 2277 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_);
2292 : false_block;
2293 EmitGoto(next_block); 2278 EmitGoto(next_block);
2294 } else { 2279 } else {
2295 if (instr->is_double()) { 2280 if (instr->is_double()) {
2296 CpuFeatureScope scope(masm(), SSE2); 2281 CpuFeatureScope scope(masm(), SSE2);
2297 // Don't base result on EFLAGS when a NaN is involved. Instead 2282 // Don't base result on EFLAGS when a NaN is involved. Instead
2298 // jump to the false block. 2283 // jump to the false block.
2299 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); 2284 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
2300 __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); 2285 __ j(parity_even, instr->FalseLabel(chunk_));
2301 } else { 2286 } else {
2302 if (right->IsConstantOperand()) { 2287 if (right->IsConstantOperand()) {
2303 int32_t const_value = ToInteger32(LConstantOperand::cast(right)); 2288 int32_t const_value = ToInteger32(LConstantOperand::cast(right));
2304 if (instr->hydrogen_value()->representation().IsSmi()) { 2289 if (instr->hydrogen_value()->representation().IsSmi()) {
2305 __ cmp(ToOperand(left), Immediate(Smi::FromInt(const_value))); 2290 __ cmp(ToOperand(left), Immediate(Smi::FromInt(const_value)));
2306 } else { 2291 } else {
2307 __ cmp(ToOperand(left), Immediate(const_value)); 2292 __ cmp(ToOperand(left), Immediate(const_value));
2308 } 2293 }
2309 } else if (left->IsConstantOperand()) { 2294 } else if (left->IsConstantOperand()) {
2310 int32_t const_value = ToInteger32(LConstantOperand::cast(left)); 2295 int32_t const_value = ToInteger32(LConstantOperand::cast(left));
2311 if (instr->hydrogen_value()->representation().IsSmi()) { 2296 if (instr->hydrogen_value()->representation().IsSmi()) {
2312 __ cmp(ToOperand(right), Immediate(Smi::FromInt(const_value))); 2297 __ cmp(ToOperand(right), Immediate(Smi::FromInt(const_value)));
2313 } else { 2298 } else {
2314 __ cmp(ToOperand(right), Immediate(const_value)); 2299 __ cmp(ToOperand(right), Immediate(const_value));
2315 } 2300 }
2316 // We transposed the operands. Reverse the condition. 2301 // We transposed the operands. Reverse the condition.
2317 cc = ReverseCondition(cc); 2302 cc = ReverseCondition(cc);
2318 } else { 2303 } else {
2319 __ cmp(ToRegister(left), ToOperand(right)); 2304 __ cmp(ToRegister(left), ToOperand(right));
2320 } 2305 }
2321 } 2306 }
2322 EmitBranch(true_block, false_block, cc); 2307 EmitBranch(instr, cc);
2323 } 2308 }
2324 } 2309 }
2325 2310
2326 2311
2327 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { 2312 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
2328 Register left = ToRegister(instr->left()); 2313 Register left = ToRegister(instr->left());
2329 int false_block = chunk_->LookupDestination(instr->false_block_id());
2330 int true_block = chunk_->LookupDestination(instr->true_block_id());
2331 2314
2332 if (instr->right()->IsConstantOperand()) { 2315 if (instr->right()->IsConstantOperand()) {
2333 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); 2316 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right()));
2334 __ CmpObject(left, right); 2317 __ CmpObject(left, right);
2335 } else { 2318 } else {
2336 Operand right = ToOperand(instr->right()); 2319 Operand right = ToOperand(instr->right());
2337 __ cmp(left, right); 2320 __ cmp(left, right);
2338 } 2321 }
2339 EmitBranch(true_block, false_block, equal); 2322 EmitBranch(instr, equal);
2340 } 2323 }
2341 2324
2342 2325
2343 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { 2326 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) {
2344 Register left = ToRegister(instr->left()); 2327 Register left = ToRegister(instr->left());
2345 int true_block = chunk_->LookupDestination(instr->true_block_id());
2346 int false_block = chunk_->LookupDestination(instr->false_block_id());
2347 2328
2348 __ cmp(left, instr->hydrogen()->right()); 2329 __ cmp(left, instr->hydrogen()->right());
2349 EmitBranch(true_block, false_block, equal); 2330 EmitBranch(instr, equal);
2350 } 2331 }
2351 2332
2352 2333
2353 Condition LCodeGen::EmitIsObject(Register input, 2334 Condition LCodeGen::EmitIsObject(Register input,
2354 Register temp1, 2335 Register temp1,
2355 Label* is_not_object, 2336 Label* is_not_object,
2356 Label* is_object) { 2337 Label* is_object) {
2357 __ JumpIfSmi(input, is_not_object); 2338 __ JumpIfSmi(input, is_not_object);
2358 2339
2359 __ cmp(input, isolate()->factory()->null_value()); 2340 __ cmp(input, isolate()->factory()->null_value());
(...skipping 10 matching lines...) Expand all
2370 __ j(below, is_not_object); 2351 __ j(below, is_not_object);
2371 __ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 2352 __ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
2372 return below_equal; 2353 return below_equal;
2373 } 2354 }
2374 2355
2375 2356
2376 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { 2357 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
2377 Register reg = ToRegister(instr->value()); 2358 Register reg = ToRegister(instr->value());
2378 Register temp = ToRegister(instr->temp()); 2359 Register temp = ToRegister(instr->temp());
2379 2360
2380 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2361 Condition true_cond = EmitIsObject(
2381 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2362 reg, temp, instr->FalseLabel(chunk_), instr->TrueLabel(chunk_));
2382 Label* true_label = chunk_->GetAssemblyLabel(true_block);
2383 Label* false_label = chunk_->GetAssemblyLabel(false_block);
2384 2363
2385 Condition true_cond = EmitIsObject(reg, temp, false_label, true_label); 2364 EmitBranch(instr, true_cond);
2386
2387 EmitBranch(true_block, false_block, true_cond);
2388 } 2365 }
2389 2366
2390 2367
2391 Condition LCodeGen::EmitIsString(Register input, 2368 Condition LCodeGen::EmitIsString(Register input,
2392 Register temp1, 2369 Register temp1,
2393 Label* is_not_string) { 2370 Label* is_not_string,
2394 __ JumpIfSmi(input, is_not_string); 2371 SmiCheck check_needed = INLINE_SMI_CHECK) {
2372 if (check_needed == INLINE_SMI_CHECK) {
2373 __ JumpIfSmi(input, is_not_string);
2374 }
2395 2375
2396 Condition cond = masm_->IsObjectStringType(input, temp1, temp1); 2376 Condition cond = masm_->IsObjectStringType(input, temp1, temp1);
2397 2377
2398 return cond; 2378 return cond;
2399 } 2379 }
2400 2380
2401 2381
2402 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { 2382 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) {
2403 Register reg = ToRegister(instr->value()); 2383 Register reg = ToRegister(instr->value());
2404 Register temp = ToRegister(instr->temp()); 2384 Register temp = ToRegister(instr->temp());
2405 2385
2406 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2386 SmiCheck check_needed =
2407 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2387 instr->hydrogen()->value()->IsHeapObject()
2408 Label* false_label = chunk_->GetAssemblyLabel(false_block); 2388 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2409 2389
2410 Condition true_cond = EmitIsString(reg, temp, false_label); 2390 Condition true_cond = EmitIsString(
2391 reg, temp, instr->FalseLabel(chunk_), check_needed);
2411 2392
2412 EmitBranch(true_block, false_block, true_cond); 2393 EmitBranch(instr, true_cond);
2413 } 2394 }
2414 2395
2415 2396
2416 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { 2397 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
2417 Operand input = ToOperand(instr->value()); 2398 Operand input = ToOperand(instr->value());
2418 2399
2419 int true_block = chunk_->LookupDestination(instr->true_block_id());
2420 int false_block = chunk_->LookupDestination(instr->false_block_id());
2421
2422 __ test(input, Immediate(kSmiTagMask)); 2400 __ test(input, Immediate(kSmiTagMask));
2423 EmitBranch(true_block, false_block, zero); 2401 EmitBranch(instr, zero);
2424 } 2402 }
2425 2403
2426 2404
2427 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { 2405 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
2428 Register input = ToRegister(instr->value()); 2406 Register input = ToRegister(instr->value());
2429 Register temp = ToRegister(instr->temp()); 2407 Register temp = ToRegister(instr->temp());
2430 2408
2431 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2409 if (!instr->hydrogen()->value()->IsHeapObject()) {
2432 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2410 STATIC_ASSERT(kSmiTag == 0);
2433 2411 __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2434 STATIC_ASSERT(kSmiTag == 0); 2412 }
2435 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block));
2436 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); 2413 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
2437 __ test_b(FieldOperand(temp, Map::kBitFieldOffset), 2414 __ test_b(FieldOperand(temp, Map::kBitFieldOffset),
2438 1 << Map::kIsUndetectable); 2415 1 << Map::kIsUndetectable);
2439 EmitBranch(true_block, false_block, not_zero); 2416 EmitBranch(instr, not_zero);
2440 } 2417 }
2441 2418
2442 2419
2443 static Condition ComputeCompareCondition(Token::Value op) { 2420 static Condition ComputeCompareCondition(Token::Value op) {
2444 switch (op) { 2421 switch (op) {
2445 case Token::EQ_STRICT: 2422 case Token::EQ_STRICT:
2446 case Token::EQ: 2423 case Token::EQ:
2447 return equal; 2424 return equal;
2448 case Token::LT: 2425 case Token::LT:
2449 return less; 2426 return less;
2450 case Token::GT: 2427 case Token::GT:
2451 return greater; 2428 return greater;
2452 case Token::LTE: 2429 case Token::LTE:
2453 return less_equal; 2430 return less_equal;
2454 case Token::GTE: 2431 case Token::GTE:
2455 return greater_equal; 2432 return greater_equal;
2456 default: 2433 default:
2457 UNREACHABLE(); 2434 UNREACHABLE();
2458 return no_condition; 2435 return no_condition;
2459 } 2436 }
2460 } 2437 }
2461 2438
2462 2439
2463 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { 2440 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
2464 Token::Value op = instr->op(); 2441 Token::Value op = instr->op();
2465 int true_block = chunk_->LookupDestination(instr->true_block_id());
2466 int false_block = chunk_->LookupDestination(instr->false_block_id());
2467 2442
2468 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); 2443 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
2469 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2444 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2470 2445
2471 Condition condition = ComputeCompareCondition(op); 2446 Condition condition = ComputeCompareCondition(op);
2472 __ test(eax, Operand(eax)); 2447 __ test(eax, Operand(eax));
2473 2448
2474 EmitBranch(true_block, false_block, condition); 2449 EmitBranch(instr, condition);
2475 } 2450 }
2476 2451
2477 2452
2478 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { 2453 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
2479 InstanceType from = instr->from(); 2454 InstanceType from = instr->from();
2480 InstanceType to = instr->to(); 2455 InstanceType to = instr->to();
2481 if (from == FIRST_TYPE) return to; 2456 if (from == FIRST_TYPE) return to;
2482 ASSERT(from == to || to == LAST_TYPE); 2457 ASSERT(from == to || to == LAST_TYPE);
2483 return from; 2458 return from;
2484 } 2459 }
2485 2460
2486 2461
2487 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { 2462 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
2488 InstanceType from = instr->from(); 2463 InstanceType from = instr->from();
2489 InstanceType to = instr->to(); 2464 InstanceType to = instr->to();
2490 if (from == to) return equal; 2465 if (from == to) return equal;
2491 if (to == LAST_TYPE) return above_equal; 2466 if (to == LAST_TYPE) return above_equal;
2492 if (from == FIRST_TYPE) return below_equal; 2467 if (from == FIRST_TYPE) return below_equal;
2493 UNREACHABLE(); 2468 UNREACHABLE();
2494 return equal; 2469 return equal;
2495 } 2470 }
2496 2471
2497 2472
2498 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { 2473 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
2499 Register input = ToRegister(instr->value()); 2474 Register input = ToRegister(instr->value());
2500 Register temp = ToRegister(instr->temp()); 2475 Register temp = ToRegister(instr->temp());
2501 2476
2502 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2477 if (!instr->hydrogen()->value()->IsHeapObject()) {
2503 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2478 __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2504 2479 }
2505 Label* false_label = chunk_->GetAssemblyLabel(false_block);
2506
2507 __ JumpIfSmi(input, false_label);
2508 2480
2509 __ CmpObjectType(input, TestType(instr->hydrogen()), temp); 2481 __ CmpObjectType(input, TestType(instr->hydrogen()), temp);
2510 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); 2482 EmitBranch(instr, BranchCondition(instr->hydrogen()));
2511 } 2483 }
2512 2484
2513 2485
2514 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { 2486 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
2515 Register input = ToRegister(instr->value()); 2487 Register input = ToRegister(instr->value());
2516 Register result = ToRegister(instr->result()); 2488 Register result = ToRegister(instr->result());
2517 2489
2518 __ AssertString(input); 2490 __ AssertString(input);
2519 2491
2520 __ mov(result, FieldOperand(input, String::kHashFieldOffset)); 2492 __ mov(result, FieldOperand(input, String::kHashFieldOffset));
2521 __ IndexFromHash(result, result); 2493 __ IndexFromHash(result, result);
2522 } 2494 }
2523 2495
2524 2496
2525 void LCodeGen::DoHasCachedArrayIndexAndBranch( 2497 void LCodeGen::DoHasCachedArrayIndexAndBranch(
2526 LHasCachedArrayIndexAndBranch* instr) { 2498 LHasCachedArrayIndexAndBranch* instr) {
2527 Register input = ToRegister(instr->value()); 2499 Register input = ToRegister(instr->value());
2528 2500
2529 int true_block = chunk_->LookupDestination(instr->true_block_id());
2530 int false_block = chunk_->LookupDestination(instr->false_block_id());
2531
2532 __ test(FieldOperand(input, String::kHashFieldOffset), 2501 __ test(FieldOperand(input, String::kHashFieldOffset),
2533 Immediate(String::kContainsCachedArrayIndexMask)); 2502 Immediate(String::kContainsCachedArrayIndexMask));
2534 EmitBranch(true_block, false_block, equal); 2503 EmitBranch(instr, equal);
2535 } 2504 }
2536 2505
2537 2506
2538 // Branches to a label or falls through with the answer in the z flag. Trashes 2507 // Branches to a label or falls through with the answer in the z flag. Trashes
2539 // the temp registers, but not the input. 2508 // the temp registers, but not the input.
2540 void LCodeGen::EmitClassOfTest(Label* is_true, 2509 void LCodeGen::EmitClassOfTest(Label* is_true,
2541 Label* is_false, 2510 Label* is_false,
2542 Handle<String>class_name, 2511 Handle<String>class_name,
2543 Register input, 2512 Register input,
2544 Register temp, 2513 Register temp,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2600 } 2569 }
2601 2570
2602 2571
2603 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { 2572 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
2604 Register input = ToRegister(instr->value()); 2573 Register input = ToRegister(instr->value());
2605 Register temp = ToRegister(instr->temp()); 2574 Register temp = ToRegister(instr->temp());
2606 Register temp2 = ToRegister(instr->temp2()); 2575 Register temp2 = ToRegister(instr->temp2());
2607 2576
2608 Handle<String> class_name = instr->hydrogen()->class_name(); 2577 Handle<String> class_name = instr->hydrogen()->class_name();
2609 2578
2610 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2579 EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
2611 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2580 class_name, input, temp, temp2);
2612 2581
2613 Label* true_label = chunk_->GetAssemblyLabel(true_block); 2582 EmitBranch(instr, equal);
2614 Label* false_label = chunk_->GetAssemblyLabel(false_block);
2615
2616 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2);
2617
2618 EmitBranch(true_block, false_block, equal);
2619 } 2583 }
2620 2584
2621 2585
2622 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { 2586 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
2623 Register reg = ToRegister(instr->value()); 2587 Register reg = ToRegister(instr->value());
2624 int true_block = instr->true_block_id();
2625 int false_block = instr->false_block_id();
2626
2627 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); 2588 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map());
2628 EmitBranch(true_block, false_block, equal); 2589 EmitBranch(instr, equal);
2629 } 2590 }
2630 2591
2631 2592
2632 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { 2593 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
2633 // Object and function are in fixed registers defined by the stub. 2594 // Object and function are in fixed registers defined by the stub.
2634 ASSERT(ToRegister(instr->context()).is(esi)); 2595 ASSERT(ToRegister(instr->context()).is(esi));
2635 InstanceofStub stub(InstanceofStub::kArgsInRegisters); 2596 InstanceofStub stub(InstanceofStub::kArgsInRegisters);
2636 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 2597 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
2637 2598
2638 Label true_value, done; 2599 Label true_value, done;
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
2945 __ cmp(target, factory()->the_hole_value()); 2906 __ cmp(target, factory()->the_hole_value());
2946 if (instr->hydrogen()->DeoptimizesOnHole()) { 2907 if (instr->hydrogen()->DeoptimizesOnHole()) {
2947 DeoptimizeIf(equal, instr->environment()); 2908 DeoptimizeIf(equal, instr->environment());
2948 } else { 2909 } else {
2949 __ j(not_equal, &skip_assignment, Label::kNear); 2910 __ j(not_equal, &skip_assignment, Label::kNear);
2950 } 2911 }
2951 } 2912 }
2952 2913
2953 __ mov(target, value); 2914 __ mov(target, value);
2954 if (instr->hydrogen()->NeedsWriteBarrier()) { 2915 if (instr->hydrogen()->NeedsWriteBarrier()) {
2955 HType type = instr->hydrogen()->value()->type();
2956 SmiCheck check_needed = 2916 SmiCheck check_needed =
2957 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 2917 instr->hydrogen()->value()->IsHeapObject()
2918 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2958 Register temp = ToRegister(instr->temp()); 2919 Register temp = ToRegister(instr->temp());
2959 int offset = Context::SlotOffset(instr->slot_index()); 2920 int offset = Context::SlotOffset(instr->slot_index());
2960 __ RecordWriteContextSlot(context, 2921 __ RecordWriteContextSlot(context,
2961 offset, 2922 offset,
2962 value, 2923 value,
2963 temp, 2924 temp,
2964 GetSaveFPRegsMode(), 2925 GetSaveFPRegsMode(),
2965 EMIT_REMEMBERED_SET, 2926 EMIT_REMEMBERED_SET,
2966 check_needed); 2927 check_needed);
2967 } 2928 }
(...skipping 1222 matching lines...) Expand 10 before | Expand all | Expand 10 after
4190 CALL_AS_FUNCTION, 4151 CALL_AS_FUNCTION,
4191 EDI_UNINITIALIZED); 4152 EDI_UNINITIALIZED);
4192 } 4153 }
4193 4154
4194 4155
4195 void LCodeGen::DoCallNew(LCallNew* instr) { 4156 void LCodeGen::DoCallNew(LCallNew* instr) {
4196 ASSERT(ToRegister(instr->context()).is(esi)); 4157 ASSERT(ToRegister(instr->context()).is(esi));
4197 ASSERT(ToRegister(instr->constructor()).is(edi)); 4158 ASSERT(ToRegister(instr->constructor()).is(edi));
4198 ASSERT(ToRegister(instr->result()).is(eax)); 4159 ASSERT(ToRegister(instr->result()).is(eax));
4199 4160
4200 if (FLAG_optimize_constructed_arrays) { 4161 // No cell in ebx for construct type feedback in optimized code
4201 // No cell in ebx for construct type feedback in optimized code 4162 Handle<Object> undefined_value(isolate()->factory()->undefined_value());
4202 Handle<Object> undefined_value(isolate()->heap()->undefined_value(), 4163 __ mov(ebx, Immediate(undefined_value));
4203 isolate());
4204 __ mov(ebx, Immediate(undefined_value));
4205 }
4206 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); 4164 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
4207 __ Set(eax, Immediate(instr->arity())); 4165 __ Set(eax, Immediate(instr->arity()));
4208 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 4166 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
4209 } 4167 }
4210 4168
4211 4169
4212 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { 4170 void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
4213 ASSERT(ToRegister(instr->context()).is(esi)); 4171 ASSERT(ToRegister(instr->context()).is(esi));
4214 ASSERT(ToRegister(instr->constructor()).is(edi)); 4172 ASSERT(ToRegister(instr->constructor()).is(edi));
4215 ASSERT(ToRegister(instr->result()).is(eax)); 4173 ASSERT(ToRegister(instr->result()).is(eax));
4216 ASSERT(FLAG_optimize_constructed_arrays);
4217 4174
4218 __ Set(eax, Immediate(instr->arity())); 4175 __ Set(eax, Immediate(instr->arity()));
4219 __ mov(ebx, instr->hydrogen()->property_cell()); 4176 __ mov(ebx, instr->hydrogen()->property_cell());
4220 ElementsKind kind = instr->hydrogen()->elements_kind(); 4177 ElementsKind kind = instr->hydrogen()->elements_kind();
4221 bool disable_allocation_sites = 4178 bool disable_allocation_sites =
4222 (AllocationSiteInfo::GetMode(kind) == TRACK_ALLOCATION_SITE); 4179 (AllocationSiteInfo::GetMode(kind) == TRACK_ALLOCATION_SITE);
4223 4180
4224 if (instr->arity() == 0) { 4181 if (instr->arity() == 0) {
4225 ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites); 4182 ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites);
4226 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 4183 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
4320 HeapObject::kMapOffset, 4277 HeapObject::kMapOffset,
4321 temp_map, 4278 temp_map,
4322 temp, 4279 temp,
4323 GetSaveFPRegsMode(), 4280 GetSaveFPRegsMode(),
4324 OMIT_REMEMBERED_SET, 4281 OMIT_REMEMBERED_SET,
4325 OMIT_SMI_CHECK); 4282 OMIT_SMI_CHECK);
4326 } 4283 }
4327 } 4284 }
4328 4285
4329 // Do the store. 4286 // Do the store.
4330 HType type = instr->hydrogen()->value()->type();
4331 SmiCheck check_needed = 4287 SmiCheck check_needed =
4332 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 4288 instr->hydrogen()->value()->IsHeapObject()
4289 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
4333 4290
4334 Register write_register = object; 4291 Register write_register = object;
4335 if (!access.IsInobject()) { 4292 if (!access.IsInobject()) {
4336 write_register = ToRegister(instr->temp()); 4293 write_register = ToRegister(instr->temp());
4337 __ mov(write_register, 4294 __ mov(write_register,
4338 FieldOperand(object, JSObject::kPropertiesOffset)); 4295 FieldOperand(object, JSObject::kPropertiesOffset));
4339 } 4296 }
4340 4297
4341 if (instr->value()->IsConstantOperand()) { 4298 if (instr->value()->IsConstantOperand()) {
4342 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); 4299 LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
4559 } else { 4516 } else {
4560 Handle<Object> handle_value = ToHandle(operand_value); 4517 Handle<Object> handle_value = ToHandle(operand_value);
4561 __ mov(operand, handle_value); 4518 __ mov(operand, handle_value);
4562 } 4519 }
4563 } 4520 }
4564 4521
4565 if (instr->hydrogen()->NeedsWriteBarrier()) { 4522 if (instr->hydrogen()->NeedsWriteBarrier()) {
4566 ASSERT(instr->value()->IsRegister()); 4523 ASSERT(instr->value()->IsRegister());
4567 Register value = ToRegister(instr->value()); 4524 Register value = ToRegister(instr->value());
4568 ASSERT(!instr->key()->IsConstantOperand()); 4525 ASSERT(!instr->key()->IsConstantOperand());
4569 HType type = instr->hydrogen()->value()->type();
4570 SmiCheck check_needed = 4526 SmiCheck check_needed =
4571 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 4527 instr->hydrogen()->value()->IsHeapObject()
4528 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
4572 // Compute address of modified element and store it into key register. 4529 // Compute address of modified element and store it into key register.
4573 __ lea(key, operand); 4530 __ lea(key, operand);
4574 __ RecordWrite(elements, 4531 __ RecordWrite(elements,
4575 key, 4532 key,
4576 value, 4533 value,
4577 GetSaveFPRegsMode(), 4534 GetSaveFPRegsMode(),
4578 EMIT_REMEMBERED_SET, 4535 EMIT_REMEMBERED_SET,
4579 check_needed); 4536 check_needed);
4580 } 4537 }
4581 } 4538 }
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
4904 CpuFeatureScope feature_scope(masm(), SSE2); 4861 CpuFeatureScope feature_scope(masm(), SSE2);
4905 __ cvtsi2sd(xmm0, Operand(reg)); 4862 __ cvtsi2sd(xmm0, Operand(reg));
4906 } else { 4863 } else {
4907 __ push(reg); 4864 __ push(reg);
4908 __ fild_s(Operand(esp, 0)); 4865 __ fild_s(Operand(esp, 0));
4909 __ pop(reg); 4866 __ pop(reg);
4910 } 4867 }
4911 } else { 4868 } else {
4912 if (CpuFeatures::IsSupported(SSE2)) { 4869 if (CpuFeatures::IsSupported(SSE2)) {
4913 CpuFeatureScope feature_scope(masm(), SSE2); 4870 CpuFeatureScope feature_scope(masm(), SSE2);
4914 __ LoadUint32(xmm0, reg, xmm1); 4871 __ LoadUint32(xmm0, reg,
4872 ToDoubleRegister(LNumberTagU::cast(instr)->temp()));
4915 } else { 4873 } else {
4916 // There's no fild variant for unsigned values, so zero-extend to a 64-bit 4874 // There's no fild variant for unsigned values, so zero-extend to a 64-bit
4917 // int manually. 4875 // int manually.
4918 __ push(Immediate(0)); 4876 __ push(Immediate(0));
4919 __ push(reg); 4877 __ push(reg);
4920 __ fild_d(Operand(esp, 0)); 4878 __ fild_d(Operand(esp, 0));
4921 __ pop(reg); 4879 __ pop(reg);
4922 __ pop(reg); 4880 __ pop(reg);
4923 } 4881 }
4924 } 4882 }
(...skipping 777 matching lines...) Expand 10 before | Expand all | Expand 10 after
5702 5660
5703 5661
5704 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 5662 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
5705 LOperand* input = instr->value(); 5663 LOperand* input = instr->value();
5706 __ test(ToOperand(input), Immediate(kSmiTagMask)); 5664 __ test(ToOperand(input), Immediate(kSmiTagMask));
5707 DeoptimizeIf(not_zero, instr->environment()); 5665 DeoptimizeIf(not_zero, instr->environment());
5708 } 5666 }
5709 5667
5710 5668
5711 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 5669 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
5712 LOperand* input = instr->value(); 5670 if (!instr->hydrogen()->value()->IsHeapObject()) {
5713 __ test(ToOperand(input), Immediate(kSmiTagMask)); 5671 LOperand* input = instr->value();
5714 DeoptimizeIf(zero, instr->environment()); 5672 __ test(ToOperand(input), Immediate(kSmiTagMask));
5673 DeoptimizeIf(zero, instr->environment());
5674 }
5715 } 5675 }
5716 5676
5717 5677
5718 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 5678 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
5719 Register input = ToRegister(instr->value()); 5679 Register input = ToRegister(instr->value());
5720 Register temp = ToRegister(instr->temp()); 5680 Register temp = ToRegister(instr->temp());
5721 5681
5722 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); 5682 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
5723 5683
5724 if (instr->hydrogen()->is_interval_check()) { 5684 if (instr->hydrogen()->is_interval_check()) {
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
5984 5944
5985 if (!instr->hydrogen()->CanOmitPrototypeChecks()) { 5945 if (!instr->hydrogen()->CanOmitPrototypeChecks()) {
5986 for (int i = 0; i < prototypes->length(); i++) { 5946 for (int i = 0; i < prototypes->length(); i++) {
5987 __ LoadHeapObject(reg, prototypes->at(i)); 5947 __ LoadHeapObject(reg, prototypes->at(i));
5988 DoCheckMapCommon(reg, maps->at(i), instr); 5948 DoCheckMapCommon(reg, maps->at(i), instr);
5989 } 5949 }
5990 } 5950 }
5991 } 5951 }
5992 5952
5993 5953
5954 void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
5955 class DeferredAllocateObject: public LDeferredCode {
5956 public:
5957 DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr)
5958 : LDeferredCode(codegen), instr_(instr) { }
5959 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); }
5960 virtual LInstruction* instr() { return instr_; }
5961 private:
5962 LAllocateObject* instr_;
5963 };
5964
5965 DeferredAllocateObject* deferred =
5966 new(zone()) DeferredAllocateObject(this, instr);
5967
5968 Register result = ToRegister(instr->result());
5969 Register scratch = ToRegister(instr->temp());
5970 Handle<JSFunction> constructor = instr->hydrogen()->constructor();
5971 Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
5972 int instance_size = initial_map->instance_size();
5973 ASSERT(initial_map->pre_allocated_property_fields() +
5974 initial_map->unused_property_fields() -
5975 initial_map->inobject_properties() == 0);
5976
5977 __ Allocate(instance_size, result, no_reg, scratch, deferred->entry(),
5978 TAG_OBJECT);
5979
5980 __ bind(deferred->exit());
5981 if (FLAG_debug_code) {
5982 Label is_in_new_space;
5983 __ JumpIfInNewSpace(result, scratch, &is_in_new_space);
5984 __ Abort("Allocated object is not in new-space");
5985 __ bind(&is_in_new_space);
5986 }
5987
5988 // Load the initial map.
5989 Register map = scratch;
5990 __ LoadHeapObject(scratch, constructor);
5991 __ mov(map, FieldOperand(scratch, JSFunction::kPrototypeOrInitialMapOffset));
5992
5993 if (FLAG_debug_code) {
5994 __ AssertNotSmi(map);
5995 __ cmpb(FieldOperand(map, Map::kInstanceSizeOffset),
5996 instance_size >> kPointerSizeLog2);
5997 __ Assert(equal, "Unexpected instance size");
5998 __ cmpb(FieldOperand(map, Map::kPreAllocatedPropertyFieldsOffset),
5999 initial_map->pre_allocated_property_fields());
6000 __ Assert(equal, "Unexpected pre-allocated property fields count");
6001 __ cmpb(FieldOperand(map, Map::kUnusedPropertyFieldsOffset),
6002 initial_map->unused_property_fields());
6003 __ Assert(equal, "Unexpected unused property fields count");
6004 __ cmpb(FieldOperand(map, Map::kInObjectPropertiesOffset),
6005 initial_map->inobject_properties());
6006 __ Assert(equal, "Unexpected in-object property fields count");
6007 }
6008
6009 // Initialize map and fields of the newly allocated object.
6010 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
6011 __ mov(FieldOperand(result, JSObject::kMapOffset), map);
6012 __ mov(scratch, factory()->empty_fixed_array());
6013 __ mov(FieldOperand(result, JSObject::kElementsOffset), scratch);
6014 __ mov(FieldOperand(result, JSObject::kPropertiesOffset), scratch);
6015 if (initial_map->inobject_properties() != 0) {
6016 __ mov(scratch, factory()->undefined_value());
6017 for (int i = 0; i < initial_map->inobject_properties(); i++) {
6018 int property_offset = JSObject::kHeaderSize + i * kPointerSize;
6019 __ mov(FieldOperand(result, property_offset), scratch);
6020 }
6021 }
6022 }
6023
6024
6025 void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
6026 Register result = ToRegister(instr->result());
6027 Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
6028 int instance_size = initial_map->instance_size();
6029
6030 // TODO(3095996): Get rid of this. For now, we need to make the
6031 // result register contain a valid pointer because it is already
6032 // contained in the register pointer map.
6033 __ Set(result, Immediate(0));
6034
6035 PushSafepointRegistersScope scope(this);
6036 __ push(Immediate(Smi::FromInt(instance_size)));
6037 CallRuntimeFromDeferred(
6038 Runtime::kAllocateInNewSpace, 1, instr, instr->context());
6039 __ StoreToSafepointRegisterSlot(result, eax);
6040 }
6041
6042
5994 void LCodeGen::DoAllocate(LAllocate* instr) { 6043 void LCodeGen::DoAllocate(LAllocate* instr) {
5995 class DeferredAllocate: public LDeferredCode { 6044 class DeferredAllocate: public LDeferredCode {
5996 public: 6045 public:
5997 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) 6046 DeferredAllocate(LCodeGen* codegen, LAllocate* instr)
5998 : LDeferredCode(codegen), instr_(instr) { } 6047 : LDeferredCode(codegen), instr_(instr) { }
5999 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } 6048 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); }
6000 virtual LInstruction* instr() { return instr_; } 6049 virtual LInstruction* instr() { return instr_; }
6001 private: 6050 private:
6002 LAllocate* instr_; 6051 LAllocate* instr_;
6003 }; 6052 };
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
6147 6196
6148 void LCodeGen::DoTypeof(LTypeof* instr) { 6197 void LCodeGen::DoTypeof(LTypeof* instr) {
6149 LOperand* input = instr->value(); 6198 LOperand* input = instr->value();
6150 EmitPushTaggedOperand(input); 6199 EmitPushTaggedOperand(input);
6151 CallRuntime(Runtime::kTypeof, 1, instr); 6200 CallRuntime(Runtime::kTypeof, 1, instr);
6152 } 6201 }
6153 6202
6154 6203
6155 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 6204 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
6156 Register input = ToRegister(instr->value()); 6205 Register input = ToRegister(instr->value());
6157 int true_block = chunk_->LookupDestination(instr->true_block_id());
6158 int false_block = chunk_->LookupDestination(instr->false_block_id());
6159 Label* true_label = chunk_->GetAssemblyLabel(true_block);
6160 Label* false_label = chunk_->GetAssemblyLabel(false_block);
6161 6206
6162 Condition final_branch_condition = 6207 Condition final_branch_condition =
6163 EmitTypeofIs(true_label, false_label, input, instr->type_literal()); 6208 EmitTypeofIs(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
6209 input, instr->type_literal());
6164 if (final_branch_condition != no_condition) { 6210 if (final_branch_condition != no_condition) {
6165 EmitBranch(true_block, false_block, final_branch_condition); 6211 EmitBranch(instr, final_branch_condition);
6166 } 6212 }
6167 } 6213 }
6168 6214
6169 6215
6170 Condition LCodeGen::EmitTypeofIs(Label* true_label, 6216 Condition LCodeGen::EmitTypeofIs(Label* true_label,
6171 Label* false_label, 6217 Label* false_label,
6172 Register input, 6218 Register input,
6173 Handle<String> type_name) { 6219 Handle<String> type_name) {
6174 Condition final_branch_condition = no_condition; 6220 Condition final_branch_condition = no_condition;
6175 if (type_name->Equals(heap()->number_string())) { 6221 if (type_name->Equals(heap()->number_string())) {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
6236 6282
6237 } else { 6283 } else {
6238 __ jmp(false_label); 6284 __ jmp(false_label);
6239 } 6285 }
6240 return final_branch_condition; 6286 return final_branch_condition;
6241 } 6287 }
6242 6288
6243 6289
6244 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 6290 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
6245 Register temp = ToRegister(instr->temp()); 6291 Register temp = ToRegister(instr->temp());
6246 int true_block = chunk_->LookupDestination(instr->true_block_id());
6247 int false_block = chunk_->LookupDestination(instr->false_block_id());
6248 6292
6249 EmitIsConstructCall(temp); 6293 EmitIsConstructCall(temp);
6250 EmitBranch(true_block, false_block, equal); 6294 EmitBranch(instr, equal);
6251 } 6295 }
6252 6296
6253 6297
6254 void LCodeGen::EmitIsConstructCall(Register temp) { 6298 void LCodeGen::EmitIsConstructCall(Register temp) {
6255 // Get the frame pointer for the calling frame. 6299 // Get the frame pointer for the calling frame.
6256 __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 6300 __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
6257 6301
6258 // Skip the arguments adaptor frame if it exists. 6302 // Skip the arguments adaptor frame if it exists.
6259 Label check_frame_marker; 6303 Label check_frame_marker;
6260 __ cmp(Operand(temp, StandardFrameConstants::kContextOffset), 6304 __ cmp(Operand(temp, StandardFrameConstants::kContextOffset),
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
6386 // the deferred code. 6430 // the deferred code.
6387 } 6431 }
6388 } 6432 }
6389 6433
6390 6434
6391 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { 6435 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
6392 // This is a pseudo-instruction that ensures that the environment here is 6436 // This is a pseudo-instruction that ensures that the environment here is
6393 // properly registered for deoptimization and records the assembler's PC 6437 // properly registered for deoptimization and records the assembler's PC
6394 // offset. 6438 // offset.
6395 LEnvironment* environment = instr->environment(); 6439 LEnvironment* environment = instr->environment();
6396 environment->SetSpilledRegisters(instr->SpilledRegisterArray(),
6397 instr->SpilledDoubleRegisterArray());
6398 6440
6399 // If the environment were already registered, we would have no way of 6441 // If the environment were already registered, we would have no way of
6400 // backpatching it with the spill slot operands. 6442 // backpatching it with the spill slot operands.
6401 ASSERT(!environment->HasBeenRegistered()); 6443 ASSERT(!environment->HasBeenRegistered());
6402 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 6444 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
6403 ASSERT(osr_pc_offset_ == -1); 6445
6404 osr_pc_offset_ = masm()->pc_offset(); 6446 // Normally we record the first unknown OSR value as the entrypoint to the OSR
6447 // code, but if there were none, record the entrypoint here.
6448 if (osr_pc_offset_ == -1) osr_pc_offset_ = masm()->pc_offset();
6405 } 6449 }
6406 6450
6407 6451
6408 void LCodeGen::DoIn(LIn* instr) { 6452 void LCodeGen::DoIn(LIn* instr) {
6409 LOperand* obj = instr->object(); 6453 LOperand* obj = instr->object();
6410 LOperand* key = instr->key(); 6454 LOperand* key = instr->key();
6411 EmitPushTaggedOperand(key); 6455 EmitPushTaggedOperand(key);
6412 EmitPushTaggedOperand(obj); 6456 EmitPushTaggedOperand(obj);
6413 ASSERT(instr->HasPointerMap()); 6457 ASSERT(instr->HasPointerMap());
6414 LPointerMap* pointers = instr->pointer_map(); 6458 LPointerMap* pointers = instr->pointer_map();
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
6504 FixedArray::kHeaderSize - kPointerSize)); 6548 FixedArray::kHeaderSize - kPointerSize));
6505 __ bind(&done); 6549 __ bind(&done);
6506 } 6550 }
6507 6551
6508 6552
6509 #undef __ 6553 #undef __
6510 6554
6511 } } // namespace v8::internal 6555 } } // namespace v8::internal
6512 6556
6513 #endif // V8_TARGET_ARCH_IA32 6557 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698