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

Side by Side Diff: src/arm/lithium-codegen-arm.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/arm/lithium-codegen-arm.h ('k') | src/arm/macro-assembler-arm.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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 private: 55 private:
56 LCodeGen* codegen_; 56 LCodeGen* codegen_;
57 LPointerMap* pointers_; 57 LPointerMap* pointers_;
58 Safepoint::DeoptMode deopt_mode_; 58 Safepoint::DeoptMode deopt_mode_;
59 }; 59 };
60 60
61 61
62 #define __ masm()-> 62 #define __ masm()->
63 63
64 bool LCodeGen::GenerateCode() { 64 bool LCodeGen::GenerateCode() {
65 HPhase phase("Z_Code generation", chunk()); 65 LPhase phase("Z_Code generation", chunk());
66 ASSERT(is_unused()); 66 ASSERT(is_unused());
67 status_ = GENERATING; 67 status_ = GENERATING;
68 68
69 // Open a frame scope to indicate that there is a frame on the stack. The 69 // Open a frame scope to indicate that there is a frame on the stack. The
70 // NONE indicates that the scope shouldn't actually generate code to set up 70 // NONE indicates that the scope shouldn't actually generate code to set up
71 // the frame (that is done in GeneratePrologue). 71 // the frame (that is done in GeneratePrologue).
72 FrameScope frame_scope(masm_, StackFrame::NONE); 72 FrameScope frame_scope(masm_, StackFrame::NONE);
73 73
74 return GeneratePrologue() && 74 return GeneratePrologue() &&
75 GenerateBody() && 75 GenerateBody() &&
76 GenerateDeferredCode() && 76 GenerateDeferredCode() &&
77 GenerateDeoptJumpTable() && 77 GenerateDeoptJumpTable() &&
78 GenerateSafepointTable(); 78 GenerateSafepointTable();
79 } 79 }
80 80
81 81
82 void LCodeGen::FinishCode(Handle<Code> code) { 82 void LCodeGen::FinishCode(Handle<Code> code) {
83 ASSERT(is_done()); 83 ASSERT(is_done());
84 code->set_stack_slots(GetStackSlotCount()); 84 code->set_stack_slots(GetStackSlotCount());
85 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); 85 code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
86 if (FLAG_weak_embedded_maps_in_optimized_code) { 86 if (FLAG_weak_embedded_maps_in_optimized_code) {
87 RegisterDependentCodeForEmbeddedMaps(code); 87 RegisterDependentCodeForEmbeddedMaps(code);
88 } 88 }
89 PopulateDeoptimizationData(code); 89 PopulateDeoptimizationData(code);
90 info()->CommitDependentMaps(code); 90 info()->CommitDependencies(code);
91 } 91 }
92 92
93 93
94 void LCodeGen::Abort(const char* reason) { 94 void LCodeGen::Abort(const char* reason) {
95 info()->set_bailout_reason(reason); 95 info()->set_bailout_reason(reason);
96 status_ = ABORTED; 96 status_ = ABORTED;
97 } 97 }
98 98
99 99
100 void LCodeGen::Comment(const char* format, ...) { 100 void LCodeGen::Comment(const char* format, ...) {
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 case STUB: 615 case STUB:
616 translation->BeginCompiledStubFrame(); 616 translation->BeginCompiledStubFrame();
617 break; 617 break;
618 case ARGUMENTS_ADAPTOR: 618 case ARGUMENTS_ADAPTOR:
619 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); 619 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size);
620 break; 620 break;
621 } 621 }
622 622
623 for (int i = 0; i < translation_size; ++i) { 623 for (int i = 0; i < translation_size; ++i) {
624 LOperand* value = environment->values()->at(i); 624 LOperand* value = environment->values()->at(i);
625 // spilled_registers_ and spilled_double_registers_ are either
626 // both NULL or both set.
627 if (environment->spilled_registers() != NULL && value != NULL) {
628 if (value->IsRegister() &&
629 environment->spilled_registers()[value->index()] != NULL) {
630 translation->MarkDuplicate();
631 AddToTranslation(translation,
632 environment->spilled_registers()[value->index()],
633 environment->HasTaggedValueAt(i),
634 environment->HasUint32ValueAt(i));
635 } else if (
636 value->IsDoubleRegister() &&
637 environment->spilled_double_registers()[value->index()] != NULL) {
638 translation->MarkDuplicate();
639 AddToTranslation(
640 translation,
641 environment->spilled_double_registers()[value->index()],
642 false,
643 false);
644 }
645 }
646 625
647 // TODO(mstarzinger): Introduce marker operands to indicate that this value 626 // TODO(mstarzinger): Introduce marker operands to indicate that this value
648 // is not present and must be reconstructed from the deoptimizer. Currently 627 // is not present and must be reconstructed from the deoptimizer. Currently
649 // this is only used for the arguments object. 628 // this is only used for the arguments object.
650 if (value == NULL) { 629 if (value == NULL) {
651 int arguments_count = environment->values()->length() - translation_size; 630 int arguments_count = environment->values()->length() - translation_size;
652 translation->BeginArgumentsObject(arguments_count); 631 translation->BeginArgumentsObject(arguments_count);
653 for (int i = 0; i < arguments_count; ++i) { 632 for (int i = 0; i < arguments_count; ++i) {
654 LOperand* value = environment->values()->at(translation_size + i); 633 LOperand* value = environment->values()->at(translation_size + i);
655 ASSERT(environment->spilled_registers() == NULL ||
656 !value->IsRegister() ||
657 environment->spilled_registers()[value->index()] == NULL);
658 ASSERT(environment->spilled_registers() == NULL ||
659 !value->IsDoubleRegister() ||
660 environment->spilled_double_registers()[value->index()] == NULL);
661 AddToTranslation(translation, 634 AddToTranslation(translation,
662 value, 635 value,
663 environment->HasTaggedValueAt(translation_size + i), 636 environment->HasTaggedValueAt(translation_size + i),
664 environment->HasUint32ValueAt(translation_size + i)); 637 environment->HasUint32ValueAt(translation_size + i));
665 } 638 }
666 continue; 639 continue;
667 } 640 }
668 641
669 AddToTranslation(translation, 642 AddToTranslation(translation,
670 value, 643 value,
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after
1113 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 1086 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
1114 break; 1087 break;
1115 } 1088 }
1116 default: 1089 default:
1117 UNREACHABLE(); 1090 UNREACHABLE();
1118 } 1091 }
1119 } 1092 }
1120 1093
1121 1094
1122 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 1095 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
1123 // Nothing to do. 1096 // Record the address of the first unknown OSR value as the place to enter.
1097 if (osr_pc_offset_ == -1) osr_pc_offset_ = masm()->pc_offset();
1124 } 1098 }
1125 1099
1126 1100
1127 void LCodeGen::DoModI(LModI* instr) { 1101 void LCodeGen::DoModI(LModI* instr) {
1128 HMod* hmod = instr->hydrogen(); 1102 HMod* hmod = instr->hydrogen();
1129 HValue* left = hmod->left(); 1103 HValue* left = hmod->left();
1130 HValue* right = hmod->right(); 1104 HValue* right = hmod->right();
1131 if (hmod->HasPowerOf2Divisor()) { 1105 if (hmod->HasPowerOf2Divisor()) {
1132 // TODO(svenpanne) We should really do the strength reduction on the 1106 // TODO(svenpanne) We should really do the strength reduction on the
1133 // Hydrogen level. 1107 // Hydrogen level.
(...skipping 13 matching lines...) Expand all
1147 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1121 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1148 DeoptimizeIf(eq, instr->environment()); 1122 DeoptimizeIf(eq, instr->environment());
1149 } 1123 }
1150 __ b(&done); 1124 __ b(&done);
1151 } 1125 }
1152 1126
1153 __ bind(&left_is_not_negative); 1127 __ bind(&left_is_not_negative);
1154 __ and_(result_reg, left_reg, Operand(divisor - 1)); 1128 __ and_(result_reg, left_reg, Operand(divisor - 1));
1155 __ bind(&done); 1129 __ bind(&done);
1156 1130
1157 } else if (hmod->has_fixed_right_arg()) { 1131 } else if (hmod->fixed_right_arg().has_value) {
1158 Register left_reg = ToRegister(instr->left()); 1132 Register left_reg = ToRegister(instr->left());
1159 Register right_reg = ToRegister(instr->right()); 1133 Register right_reg = ToRegister(instr->right());
1160 Register result_reg = ToRegister(instr->result()); 1134 Register result_reg = ToRegister(instr->result());
1161 1135
1162 int32_t divisor = hmod->fixed_right_arg_value(); 1136 int32_t divisor = hmod->fixed_right_arg().value;
1163 ASSERT(IsPowerOf2(divisor)); 1137 ASSERT(IsPowerOf2(divisor));
1164 1138
1165 // Check if our assumption of a fixed right operand still holds. 1139 // Check if our assumption of a fixed right operand still holds.
1166 __ cmp(right_reg, Operand(divisor)); 1140 __ cmp(right_reg, Operand(divisor));
1167 DeoptimizeIf(ne, instr->environment()); 1141 DeoptimizeIf(ne, instr->environment());
1168 1142
1169 Label left_is_not_negative, done; 1143 Label left_is_not_negative, done;
1170 if (left->CanBeNegative()) { 1144 if (left->CanBeNegative()) {
1171 __ cmp(left_reg, Operand::Zero()); 1145 __ cmp(left_reg, Operand::Zero());
1172 __ b(pl, &left_is_not_negative); 1146 __ b(pl, &left_is_not_negative);
(...skipping 726 matching lines...) Expand 10 before | Expand all | Expand 10 after
1899 __ ubfx(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount); 1873 __ ubfx(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount);
1900 } 1874 }
1901 1875
1902 1876
1903 void LCodeGen::DoValueOf(LValueOf* instr) { 1877 void LCodeGen::DoValueOf(LValueOf* instr) {
1904 Register input = ToRegister(instr->value()); 1878 Register input = ToRegister(instr->value());
1905 Register result = ToRegister(instr->result()); 1879 Register result = ToRegister(instr->result());
1906 Register map = ToRegister(instr->temp()); 1880 Register map = ToRegister(instr->temp());
1907 Label done; 1881 Label done;
1908 1882
1909 // If the object is a smi return the object. 1883 if (!instr->hydrogen()->value()->IsHeapObject()) {
1910 __ SmiTst(input); 1884 // If the object is a smi return the object.
1911 __ Move(result, input, eq); 1885 __ SmiTst(input);
1912 __ b(eq, &done); 1886 __ Move(result, input, eq);
1887 __ b(eq, &done);
1888 }
1913 1889
1914 // If the object is not a value type, return the object. 1890 // If the object is not a value type, return the object.
1915 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); 1891 __ CompareObjectType(input, map, map, JS_VALUE_TYPE);
1916 __ Move(result, input, ne); 1892 __ Move(result, input, ne);
1917 __ b(ne, &done); 1893 __ b(ne, &done);
1918 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); 1894 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset));
1919 1895
1920 __ bind(&done); 1896 __ bind(&done);
1921 } 1897 }
1922 1898
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
2152 } 2128 }
2153 2129
2154 2130
2155 int LCodeGen::GetNextEmittedBlock() const { 2131 int LCodeGen::GetNextEmittedBlock() const {
2156 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { 2132 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) {
2157 if (!chunk_->GetLabel(i)->HasReplacement()) return i; 2133 if (!chunk_->GetLabel(i)->HasReplacement()) return i;
2158 } 2134 }
2159 return -1; 2135 return -1;
2160 } 2136 }
2161 2137
2138 template<class InstrType>
2139 void LCodeGen::EmitBranch(InstrType instr, Condition cc) {
2140 int right_block = instr->FalseDestination(chunk_);
2141 int left_block = instr->TrueDestination(chunk_);
2162 2142
2163 void LCodeGen::EmitBranch(int left_block, int right_block, Condition cc) {
2164 int next_block = GetNextEmittedBlock(); 2143 int next_block = GetNextEmittedBlock();
2165 right_block = chunk_->LookupDestination(right_block);
2166 left_block = chunk_->LookupDestination(left_block);
2167 2144
2168 if (right_block == left_block) { 2145 if (right_block == left_block) {
2169 EmitGoto(left_block); 2146 EmitGoto(left_block);
2170 } else if (left_block == next_block) { 2147 } else if (left_block == next_block) {
2171 __ b(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); 2148 __ b(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block));
2172 } else if (right_block == next_block) { 2149 } else if (right_block == next_block) {
2173 __ b(cc, chunk_->GetAssemblyLabel(left_block)); 2150 __ b(cc, chunk_->GetAssemblyLabel(left_block));
2174 } else { 2151 } else {
2175 __ b(cc, chunk_->GetAssemblyLabel(left_block)); 2152 __ b(cc, chunk_->GetAssemblyLabel(left_block));
2176 __ b(chunk_->GetAssemblyLabel(right_block)); 2153 __ b(chunk_->GetAssemblyLabel(right_block));
2177 } 2154 }
2178 } 2155 }
2179 2156
2180 2157
2181 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { 2158 void LCodeGen::DoDebugBreak(LDebugBreak* instr) {
2182 __ stop("LBreak"); 2159 __ stop("LBreak");
2183 } 2160 }
2184 2161
2185 2162
2186 void LCodeGen::DoBranch(LBranch* instr) { 2163 void LCodeGen::DoBranch(LBranch* instr) {
2187 int true_block = chunk_->LookupDestination(instr->true_block_id());
2188 int false_block = chunk_->LookupDestination(instr->false_block_id());
2189
2190 Representation r = instr->hydrogen()->value()->representation(); 2164 Representation r = instr->hydrogen()->value()->representation();
2191 if (r.IsInteger32() || r.IsSmi()) { 2165 if (r.IsInteger32() || r.IsSmi()) {
2192 ASSERT(!info()->IsStub()); 2166 ASSERT(!info()->IsStub());
2193 Register reg = ToRegister(instr->value()); 2167 Register reg = ToRegister(instr->value());
2194 __ cmp(reg, Operand::Zero()); 2168 __ cmp(reg, Operand::Zero());
2195 EmitBranch(true_block, false_block, ne); 2169 EmitBranch(instr, ne);
2196 } else if (r.IsDouble()) { 2170 } else if (r.IsDouble()) {
2197 ASSERT(!info()->IsStub()); 2171 ASSERT(!info()->IsStub());
2198 DwVfpRegister reg = ToDoubleRegister(instr->value()); 2172 DwVfpRegister reg = ToDoubleRegister(instr->value());
2199 // Test the double value. Zero and NaN are false. 2173 // Test the double value. Zero and NaN are false.
2200 __ VFPCompareAndSetFlags(reg, 0.0); 2174 __ VFPCompareAndSetFlags(reg, 0.0);
2201 __ cmp(r0, r0, vs); // If NaN, set the Z flag. 2175 __ cmp(r0, r0, vs); // If NaN, set the Z flag. (NaN -> false)
2202 EmitBranch(true_block, false_block, ne); 2176 EmitBranch(instr, ne);
2203 } else { 2177 } else {
2204 ASSERT(r.IsTagged()); 2178 ASSERT(r.IsTagged());
2205 Register reg = ToRegister(instr->value()); 2179 Register reg = ToRegister(instr->value());
2206 HType type = instr->hydrogen()->value()->type(); 2180 HType type = instr->hydrogen()->value()->type();
2207 if (type.IsBoolean()) { 2181 if (type.IsBoolean()) {
2208 ASSERT(!info()->IsStub()); 2182 ASSERT(!info()->IsStub());
2209 __ CompareRoot(reg, Heap::kTrueValueRootIndex); 2183 __ CompareRoot(reg, Heap::kTrueValueRootIndex);
2210 EmitBranch(true_block, false_block, eq); 2184 EmitBranch(instr, eq);
2211 } else if (type.IsSmi()) { 2185 } else if (type.IsSmi()) {
2212 ASSERT(!info()->IsStub()); 2186 ASSERT(!info()->IsStub());
2213 __ cmp(reg, Operand::Zero()); 2187 __ cmp(reg, Operand::Zero());
2214 EmitBranch(true_block, false_block, ne); 2188 EmitBranch(instr, ne);
2189 } else if (type.IsJSArray()) {
2190 ASSERT(!info()->IsStub());
2191 EmitBranch(instr, al);
2192 } else if (type.IsHeapNumber()) {
2193 ASSERT(!info()->IsStub());
2194 DwVfpRegister dbl_scratch = double_scratch0();
2195 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset));
2196 // Test the double value. Zero and NaN are false.
2197 __ VFPCompareAndSetFlags(dbl_scratch, 0.0);
2198 __ cmp(r0, r0, vs); // If NaN, set the Z flag. (NaN)
2199 EmitBranch(instr, ne);
2200 } else if (type.IsString()) {
2201 ASSERT(!info()->IsStub());
2202 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset));
2203 __ cmp(ip, Operand::Zero());
2204 EmitBranch(instr, ne);
2215 } else { 2205 } else {
2216 Label* true_label = chunk_->GetAssemblyLabel(true_block);
2217 Label* false_label = chunk_->GetAssemblyLabel(false_block);
2218
2219 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); 2206 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
2220 // Avoid deopts in the case where we've never executed this path before. 2207 // Avoid deopts in the case where we've never executed this path before.
2221 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); 2208 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();
2222 2209
2223 if (expected.Contains(ToBooleanStub::UNDEFINED)) { 2210 if (expected.Contains(ToBooleanStub::UNDEFINED)) {
2224 // undefined -> false. 2211 // undefined -> false.
2225 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); 2212 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex);
2226 __ b(eq, false_label); 2213 __ b(eq, instr->FalseLabel(chunk_));
2227 } 2214 }
2228 if (expected.Contains(ToBooleanStub::BOOLEAN)) { 2215 if (expected.Contains(ToBooleanStub::BOOLEAN)) {
2229 // Boolean -> its value. 2216 // Boolean -> its value.
2230 __ CompareRoot(reg, Heap::kTrueValueRootIndex); 2217 __ CompareRoot(reg, Heap::kTrueValueRootIndex);
2231 __ b(eq, true_label); 2218 __ b(eq, instr->TrueLabel(chunk_));
2232 __ CompareRoot(reg, Heap::kFalseValueRootIndex); 2219 __ CompareRoot(reg, Heap::kFalseValueRootIndex);
2233 __ b(eq, false_label); 2220 __ b(eq, instr->FalseLabel(chunk_));
2234 } 2221 }
2235 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { 2222 if (expected.Contains(ToBooleanStub::NULL_TYPE)) {
2236 // 'null' -> false. 2223 // 'null' -> false.
2237 __ CompareRoot(reg, Heap::kNullValueRootIndex); 2224 __ CompareRoot(reg, Heap::kNullValueRootIndex);
2238 __ b(eq, false_label); 2225 __ b(eq, instr->FalseLabel(chunk_));
2239 } 2226 }
2240 2227
2241 if (expected.Contains(ToBooleanStub::SMI)) { 2228 if (expected.Contains(ToBooleanStub::SMI)) {
2242 // Smis: 0 -> false, all other -> true. 2229 // Smis: 0 -> false, all other -> true.
2243 __ cmp(reg, Operand::Zero()); 2230 __ cmp(reg, Operand::Zero());
2244 __ b(eq, false_label); 2231 __ b(eq, instr->FalseLabel(chunk_));
2245 __ JumpIfSmi(reg, true_label); 2232 __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2246 } else if (expected.NeedsMap()) { 2233 } else if (expected.NeedsMap()) {
2247 // If we need a map later and have a Smi -> deopt. 2234 // If we need a map later and have a Smi -> deopt.
2248 __ SmiTst(reg); 2235 __ SmiTst(reg);
2249 DeoptimizeIf(eq, instr->environment()); 2236 DeoptimizeIf(eq, instr->environment());
2250 } 2237 }
2251 2238
2252 const Register map = scratch0(); 2239 const Register map = scratch0();
2253 if (expected.NeedsMap()) { 2240 if (expected.NeedsMap()) {
2254 __ ldr(map, FieldMemOperand(reg, HeapObject::kMapOffset)); 2241 __ ldr(map, FieldMemOperand(reg, HeapObject::kMapOffset));
2255 2242
2256 if (expected.CanBeUndetectable()) { 2243 if (expected.CanBeUndetectable()) {
2257 // Undetectable -> false. 2244 // Undetectable -> false.
2258 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); 2245 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset));
2259 __ tst(ip, Operand(1 << Map::kIsUndetectable)); 2246 __ tst(ip, Operand(1 << Map::kIsUndetectable));
2260 __ b(ne, false_label); 2247 __ b(ne, instr->FalseLabel(chunk_));
2261 } 2248 }
2262 } 2249 }
2263 2250
2264 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { 2251 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) {
2265 // spec object -> true. 2252 // spec object -> true.
2266 __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE); 2253 __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE);
2267 __ b(ge, true_label); 2254 __ b(ge, instr->TrueLabel(chunk_));
2268 } 2255 }
2269 2256
2270 if (expected.Contains(ToBooleanStub::STRING)) { 2257 if (expected.Contains(ToBooleanStub::STRING)) {
2271 // String value -> false iff empty. 2258 // String value -> false iff empty.
2272 Label not_string; 2259 Label not_string;
2273 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); 2260 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE);
2274 __ b(ge, &not_string); 2261 __ b(ge, &not_string);
2275 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset)); 2262 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset));
2276 __ cmp(ip, Operand::Zero()); 2263 __ cmp(ip, Operand::Zero());
2277 __ b(ne, true_label); 2264 __ b(ne, instr->TrueLabel(chunk_));
2278 __ b(false_label); 2265 __ b(instr->FalseLabel(chunk_));
2279 __ bind(&not_string); 2266 __ bind(&not_string);
2280 } 2267 }
2281 2268
2282 if (expected.Contains(ToBooleanStub::SYMBOL)) { 2269 if (expected.Contains(ToBooleanStub::SYMBOL)) {
2283 // Symbol value -> true. 2270 // Symbol value -> true.
2284 __ CompareInstanceType(map, ip, SYMBOL_TYPE); 2271 __ CompareInstanceType(map, ip, SYMBOL_TYPE);
2285 __ b(eq, true_label); 2272 __ b(eq, instr->TrueLabel(chunk_));
2286 } 2273 }
2287 2274
2288 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { 2275 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
2289 // heap number -> false iff +0, -0, or NaN. 2276 // heap number -> false iff +0, -0, or NaN.
2290 DwVfpRegister dbl_scratch = double_scratch0(); 2277 DwVfpRegister dbl_scratch = double_scratch0();
2291 Label not_heap_number; 2278 Label not_heap_number;
2292 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); 2279 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
2293 __ b(ne, &not_heap_number); 2280 __ b(ne, &not_heap_number);
2294 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); 2281 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset));
2295 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); 2282 __ VFPCompareAndSetFlags(dbl_scratch, 0.0);
2296 __ cmp(r0, r0, vs); // NaN -> false. 2283 __ cmp(r0, r0, vs); // NaN -> false.
2297 __ b(eq, false_label); // +0, -0 -> false. 2284 __ b(eq, instr->FalseLabel(chunk_)); // +0, -0 -> false.
2298 __ b(true_label); 2285 __ b(instr->TrueLabel(chunk_));
2299 __ bind(&not_heap_number); 2286 __ bind(&not_heap_number);
2300 } 2287 }
2301 2288
2302 // We've seen something for the first time -> deopt. 2289 if (!expected.IsGeneric()) {
2303 DeoptimizeIf(al, instr->environment()); 2290 // We've seen something for the first time -> deopt.
2291 // This can only happen if we are not generic already.
2292 DeoptimizeIf(al, instr->environment());
2293 }
2304 } 2294 }
2305 } 2295 }
2306 } 2296 }
2307 2297
2308 2298
2309 void LCodeGen::EmitGoto(int block) { 2299 void LCodeGen::EmitGoto(int block) {
2310 if (!IsNextEmittedBlock(block)) { 2300 if (!IsNextEmittedBlock(block)) {
2311 __ jmp(chunk_->GetAssemblyLabel(chunk_->LookupDestination(block))); 2301 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block)));
2312 } 2302 }
2313 } 2303 }
2314 2304
2315 2305
2316 void LCodeGen::DoGoto(LGoto* instr) { 2306 void LCodeGen::DoGoto(LGoto* instr) {
2317 EmitGoto(instr->block_id()); 2307 EmitGoto(instr->block_id());
2318 } 2308 }
2319 2309
2320 2310
2321 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { 2311 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) {
(...skipping 20 matching lines...) Expand all
2342 default: 2332 default:
2343 UNREACHABLE(); 2333 UNREACHABLE();
2344 } 2334 }
2345 return cond; 2335 return cond;
2346 } 2336 }
2347 2337
2348 2338
2349 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { 2339 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
2350 LOperand* left = instr->left(); 2340 LOperand* left = instr->left();
2351 LOperand* right = instr->right(); 2341 LOperand* right = instr->right();
2352 int false_block = chunk_->LookupDestination(instr->false_block_id());
2353 int true_block = chunk_->LookupDestination(instr->true_block_id());
2354 Condition cond = TokenToCondition(instr->op(), false); 2342 Condition cond = TokenToCondition(instr->op(), false);
2355 2343
2356 if (left->IsConstantOperand() && right->IsConstantOperand()) { 2344 if (left->IsConstantOperand() && right->IsConstantOperand()) {
2357 // We can statically evaluate the comparison. 2345 // We can statically evaluate the comparison.
2358 double left_val = ToDouble(LConstantOperand::cast(left)); 2346 double left_val = ToDouble(LConstantOperand::cast(left));
2359 double right_val = ToDouble(LConstantOperand::cast(right)); 2347 double right_val = ToDouble(LConstantOperand::cast(right));
2360 int next_block = 2348 int next_block = EvalComparison(instr->op(), left_val, right_val) ?
2361 EvalComparison(instr->op(), left_val, right_val) ? true_block 2349 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_);
2362 : false_block;
2363 EmitGoto(next_block); 2350 EmitGoto(next_block);
2364 } else { 2351 } else {
2365 if (instr->is_double()) { 2352 if (instr->is_double()) {
2366 // Compare left and right operands as doubles and load the 2353 // Compare left and right operands as doubles and load the
2367 // resulting flags into the normal status register. 2354 // resulting flags into the normal status register.
2368 __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right)); 2355 __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right));
2369 // If a NaN is involved, i.e. the result is unordered (V set), 2356 // If a NaN is involved, i.e. the result is unordered (V set),
2370 // jump to false block label. 2357 // jump to false block label.
2371 __ b(vs, chunk_->GetAssemblyLabel(false_block)); 2358 __ b(vs, instr->FalseLabel(chunk_));
2372 } else { 2359 } else {
2373 if (right->IsConstantOperand()) { 2360 if (right->IsConstantOperand()) {
2374 int32_t value = ToInteger32(LConstantOperand::cast(right)); 2361 int32_t value = ToInteger32(LConstantOperand::cast(right));
2375 if (instr->hydrogen_value()->representation().IsSmi()) { 2362 if (instr->hydrogen_value()->representation().IsSmi()) {
2376 __ cmp(ToRegister(left), Operand(Smi::FromInt(value))); 2363 __ cmp(ToRegister(left), Operand(Smi::FromInt(value)));
2377 } else { 2364 } else {
2378 __ cmp(ToRegister(left), Operand(value)); 2365 __ cmp(ToRegister(left), Operand(value));
2379 } 2366 }
2380 } else if (left->IsConstantOperand()) { 2367 } else if (left->IsConstantOperand()) {
2381 int32_t value = ToInteger32(LConstantOperand::cast(left)); 2368 int32_t value = ToInteger32(LConstantOperand::cast(left));
2382 if (instr->hydrogen_value()->representation().IsSmi()) { 2369 if (instr->hydrogen_value()->representation().IsSmi()) {
2383 __ cmp(ToRegister(right), Operand(Smi::FromInt(value))); 2370 __ cmp(ToRegister(right), Operand(Smi::FromInt(value)));
2384 } else { 2371 } else {
2385 __ cmp(ToRegister(right), Operand(value)); 2372 __ cmp(ToRegister(right), Operand(value));
2386 } 2373 }
2387 // We transposed the operands. Reverse the condition. 2374 // We transposed the operands. Reverse the condition.
2388 cond = ReverseCondition(cond); 2375 cond = ReverseCondition(cond);
2389 } else { 2376 } else {
2390 __ cmp(ToRegister(left), ToRegister(right)); 2377 __ cmp(ToRegister(left), ToRegister(right));
2391 } 2378 }
2392 } 2379 }
2393 EmitBranch(true_block, false_block, cond); 2380 EmitBranch(instr, cond);
2394 } 2381 }
2395 } 2382 }
2396 2383
2397 2384
2398 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { 2385 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
2399 Register left = ToRegister(instr->left()); 2386 Register left = ToRegister(instr->left());
2400 Register right = ToRegister(instr->right()); 2387 Register right = ToRegister(instr->right());
2401 int false_block = chunk_->LookupDestination(instr->false_block_id());
2402 int true_block = chunk_->LookupDestination(instr->true_block_id());
2403 2388
2404 __ cmp(left, Operand(right)); 2389 __ cmp(left, Operand(right));
2405 EmitBranch(true_block, false_block, eq); 2390 EmitBranch(instr, eq);
2406 } 2391 }
2407 2392
2408 2393
2409 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { 2394 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) {
2410 Register left = ToRegister(instr->left()); 2395 Register left = ToRegister(instr->left());
2411 int true_block = chunk_->LookupDestination(instr->true_block_id());
2412 int false_block = chunk_->LookupDestination(instr->false_block_id());
2413 2396
2414 __ cmp(left, Operand(instr->hydrogen()->right())); 2397 __ cmp(left, Operand(instr->hydrogen()->right()));
2415 EmitBranch(true_block, false_block, eq); 2398 EmitBranch(instr, eq);
2416 } 2399 }
2417 2400
2418 2401
2419 Condition LCodeGen::EmitIsObject(Register input, 2402 Condition LCodeGen::EmitIsObject(Register input,
2420 Register temp1, 2403 Register temp1,
2421 Label* is_not_object, 2404 Label* is_not_object,
2422 Label* is_object) { 2405 Label* is_object) {
2423 Register temp2 = scratch0(); 2406 Register temp2 = scratch0();
2424 __ JumpIfSmi(input, is_not_object); 2407 __ JumpIfSmi(input, is_not_object);
2425 2408
(...skipping 14 matching lines...) Expand all
2440 __ b(lt, is_not_object); 2423 __ b(lt, is_not_object);
2441 __ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2424 __ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
2442 return le; 2425 return le;
2443 } 2426 }
2444 2427
2445 2428
2446 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { 2429 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
2447 Register reg = ToRegister(instr->value()); 2430 Register reg = ToRegister(instr->value());
2448 Register temp1 = ToRegister(instr->temp()); 2431 Register temp1 = ToRegister(instr->temp());
2449 2432
2450 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2433 Condition true_cond =
2451 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2434 EmitIsObject(reg, temp1,
2452 Label* true_label = chunk_->GetAssemblyLabel(true_block); 2435 instr->FalseLabel(chunk_), instr->TrueLabel(chunk_));
2453 Label* false_label = chunk_->GetAssemblyLabel(false_block);
2454 2436
2455 Condition true_cond = 2437 EmitBranch(instr, true_cond);
2456 EmitIsObject(reg, temp1, false_label, true_label);
2457
2458 EmitBranch(true_block, false_block, true_cond);
2459 } 2438 }
2460 2439
2461 2440
2462 Condition LCodeGen::EmitIsString(Register input, 2441 Condition LCodeGen::EmitIsString(Register input,
2463 Register temp1, 2442 Register temp1,
2464 Label* is_not_string) { 2443 Label* is_not_string,
2465 __ JumpIfSmi(input, is_not_string); 2444 SmiCheck check_needed = INLINE_SMI_CHECK) {
2445 if (check_needed == INLINE_SMI_CHECK) {
2446 __ JumpIfSmi(input, is_not_string);
2447 }
2466 __ CompareObjectType(input, temp1, temp1, FIRST_NONSTRING_TYPE); 2448 __ CompareObjectType(input, temp1, temp1, FIRST_NONSTRING_TYPE);
2467 2449
2468 return lt; 2450 return lt;
2469 } 2451 }
2470 2452
2471 2453
2472 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { 2454 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) {
2473 Register reg = ToRegister(instr->value()); 2455 Register reg = ToRegister(instr->value());
2474 Register temp1 = ToRegister(instr->temp()); 2456 Register temp1 = ToRegister(instr->temp());
2475 2457
2476 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2458 SmiCheck check_needed =
2477 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2459 instr->hydrogen()->value()->IsHeapObject()
2478 Label* false_label = chunk_->GetAssemblyLabel(false_block); 2460 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2461 Condition true_cond =
2462 EmitIsString(reg, temp1, instr->FalseLabel(chunk_), check_needed);
2479 2463
2480 Condition true_cond = 2464 EmitBranch(instr, true_cond);
2481 EmitIsString(reg, temp1, false_label);
2482
2483 EmitBranch(true_block, false_block, true_cond);
2484 } 2465 }
2485 2466
2486 2467
2487 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { 2468 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
2488 int true_block = chunk_->LookupDestination(instr->true_block_id());
2489 int false_block = chunk_->LookupDestination(instr->false_block_id());
2490
2491 Register input_reg = EmitLoadRegister(instr->value(), ip); 2469 Register input_reg = EmitLoadRegister(instr->value(), ip);
2492 __ SmiTst(input_reg); 2470 __ SmiTst(input_reg);
2493 EmitBranch(true_block, false_block, eq); 2471 EmitBranch(instr, eq);
2494 } 2472 }
2495 2473
2496 2474
2497 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { 2475 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
2498 Register input = ToRegister(instr->value()); 2476 Register input = ToRegister(instr->value());
2499 Register temp = ToRegister(instr->temp()); 2477 Register temp = ToRegister(instr->temp());
2500 2478
2501 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2479 if (!instr->hydrogen()->value()->IsHeapObject()) {
2502 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2480 __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2503 2481 }
2504 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block));
2505 __ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset)); 2482 __ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset));
2506 __ ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); 2483 __ ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset));
2507 __ tst(temp, Operand(1 << Map::kIsUndetectable)); 2484 __ tst(temp, Operand(1 << Map::kIsUndetectable));
2508 EmitBranch(true_block, false_block, ne); 2485 EmitBranch(instr, ne);
2509 } 2486 }
2510 2487
2511 2488
2512 static Condition ComputeCompareCondition(Token::Value op) { 2489 static Condition ComputeCompareCondition(Token::Value op) {
2513 switch (op) { 2490 switch (op) {
2514 case Token::EQ_STRICT: 2491 case Token::EQ_STRICT:
2515 case Token::EQ: 2492 case Token::EQ:
2516 return eq; 2493 return eq;
2517 case Token::LT: 2494 case Token::LT:
2518 return lt; 2495 return lt;
2519 case Token::GT: 2496 case Token::GT:
2520 return gt; 2497 return gt;
2521 case Token::LTE: 2498 case Token::LTE:
2522 return le; 2499 return le;
2523 case Token::GTE: 2500 case Token::GTE:
2524 return ge; 2501 return ge;
2525 default: 2502 default:
2526 UNREACHABLE(); 2503 UNREACHABLE();
2527 return kNoCondition; 2504 return kNoCondition;
2528 } 2505 }
2529 } 2506 }
2530 2507
2531 2508
2532 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { 2509 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
2533 Token::Value op = instr->op(); 2510 Token::Value op = instr->op();
2534 int true_block = chunk_->LookupDestination(instr->true_block_id());
2535 int false_block = chunk_->LookupDestination(instr->false_block_id());
2536 2511
2537 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); 2512 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
2538 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2513 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2539 // This instruction also signals no smi code inlined. 2514 // This instruction also signals no smi code inlined.
2540 __ cmp(r0, Operand::Zero()); 2515 __ cmp(r0, Operand::Zero());
2541 2516
2542 Condition condition = ComputeCompareCondition(op); 2517 Condition condition = ComputeCompareCondition(op);
2543 2518
2544 EmitBranch(true_block, false_block, condition); 2519 EmitBranch(instr, condition);
2545 } 2520 }
2546 2521
2547 2522
2548 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { 2523 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
2549 InstanceType from = instr->from(); 2524 InstanceType from = instr->from();
2550 InstanceType to = instr->to(); 2525 InstanceType to = instr->to();
2551 if (from == FIRST_TYPE) return to; 2526 if (from == FIRST_TYPE) return to;
2552 ASSERT(from == to || to == LAST_TYPE); 2527 ASSERT(from == to || to == LAST_TYPE);
2553 return from; 2528 return from;
2554 } 2529 }
2555 2530
2556 2531
2557 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { 2532 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
2558 InstanceType from = instr->from(); 2533 InstanceType from = instr->from();
2559 InstanceType to = instr->to(); 2534 InstanceType to = instr->to();
2560 if (from == to) return eq; 2535 if (from == to) return eq;
2561 if (to == LAST_TYPE) return hs; 2536 if (to == LAST_TYPE) return hs;
2562 if (from == FIRST_TYPE) return ls; 2537 if (from == FIRST_TYPE) return ls;
2563 UNREACHABLE(); 2538 UNREACHABLE();
2564 return eq; 2539 return eq;
2565 } 2540 }
2566 2541
2567 2542
2568 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { 2543 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
2569 Register scratch = scratch0(); 2544 Register scratch = scratch0();
2570 Register input = ToRegister(instr->value()); 2545 Register input = ToRegister(instr->value());
2571 2546
2572 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2547 if (!instr->hydrogen()->value()->IsHeapObject()) {
2573 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2548 __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2574 2549 }
2575 Label* false_label = chunk_->GetAssemblyLabel(false_block);
2576
2577 __ JumpIfSmi(input, false_label);
2578 2550
2579 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen())); 2551 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen()));
2580 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); 2552 EmitBranch(instr, BranchCondition(instr->hydrogen()));
2581 } 2553 }
2582 2554
2583 2555
2584 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { 2556 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
2585 Register input = ToRegister(instr->value()); 2557 Register input = ToRegister(instr->value());
2586 Register result = ToRegister(instr->result()); 2558 Register result = ToRegister(instr->result());
2587 2559
2588 __ AssertString(input); 2560 __ AssertString(input);
2589 2561
2590 __ ldr(result, FieldMemOperand(input, String::kHashFieldOffset)); 2562 __ ldr(result, FieldMemOperand(input, String::kHashFieldOffset));
2591 __ IndexFromHash(result, result); 2563 __ IndexFromHash(result, result);
2592 } 2564 }
2593 2565
2594 2566
2595 void LCodeGen::DoHasCachedArrayIndexAndBranch( 2567 void LCodeGen::DoHasCachedArrayIndexAndBranch(
2596 LHasCachedArrayIndexAndBranch* instr) { 2568 LHasCachedArrayIndexAndBranch* instr) {
2597 Register input = ToRegister(instr->value()); 2569 Register input = ToRegister(instr->value());
2598 Register scratch = scratch0(); 2570 Register scratch = scratch0();
2599 2571
2600 int true_block = chunk_->LookupDestination(instr->true_block_id());
2601 int false_block = chunk_->LookupDestination(instr->false_block_id());
2602
2603 __ ldr(scratch, 2572 __ ldr(scratch,
2604 FieldMemOperand(input, String::kHashFieldOffset)); 2573 FieldMemOperand(input, String::kHashFieldOffset));
2605 __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask)); 2574 __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask));
2606 EmitBranch(true_block, false_block, eq); 2575 EmitBranch(instr, eq);
2607 } 2576 }
2608 2577
2609 2578
2610 // Branches to a label or falls through with the answer in flags. Trashes 2579 // Branches to a label or falls through with the answer in flags. Trashes
2611 // the temp registers, but not the input. 2580 // the temp registers, but not the input.
2612 void LCodeGen::EmitClassOfTest(Label* is_true, 2581 void LCodeGen::EmitClassOfTest(Label* is_true,
2613 Label* is_false, 2582 Label* is_false,
2614 Handle<String>class_name, 2583 Handle<String>class_name,
2615 Register input, 2584 Register input,
2616 Register temp, 2585 Register temp,
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2673 // End with the answer in flags. 2642 // End with the answer in flags.
2674 } 2643 }
2675 2644
2676 2645
2677 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { 2646 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
2678 Register input = ToRegister(instr->value()); 2647 Register input = ToRegister(instr->value());
2679 Register temp = scratch0(); 2648 Register temp = scratch0();
2680 Register temp2 = ToRegister(instr->temp()); 2649 Register temp2 = ToRegister(instr->temp());
2681 Handle<String> class_name = instr->hydrogen()->class_name(); 2650 Handle<String> class_name = instr->hydrogen()->class_name();
2682 2651
2683 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2652 EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
2684 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2653 class_name, input, temp, temp2);
2685 2654
2686 Label* true_label = chunk_->GetAssemblyLabel(true_block); 2655 EmitBranch(instr, eq);
2687 Label* false_label = chunk_->GetAssemblyLabel(false_block);
2688
2689 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2);
2690
2691 EmitBranch(true_block, false_block, eq);
2692 } 2656 }
2693 2657
2694 2658
2695 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { 2659 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
2696 Register reg = ToRegister(instr->value()); 2660 Register reg = ToRegister(instr->value());
2697 Register temp = ToRegister(instr->temp()); 2661 Register temp = ToRegister(instr->temp());
2698 int true_block = instr->true_block_id();
2699 int false_block = instr->false_block_id();
2700 2662
2701 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); 2663 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset));
2702 __ cmp(temp, Operand(instr->map())); 2664 __ cmp(temp, Operand(instr->map()));
2703 EmitBranch(true_block, false_block, eq); 2665 EmitBranch(instr, eq);
2704 } 2666 }
2705 2667
2706 2668
2707 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { 2669 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
2708 ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0. 2670 ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0.
2709 ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1. 2671 ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1.
2710 2672
2711 InstanceofStub stub(InstanceofStub::kArgsInRegisters); 2673 InstanceofStub stub(InstanceofStub::kArgsInRegisters);
2712 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 2674 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
2713 2675
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
3012 __ cmp(scratch, ip); 2974 __ cmp(scratch, ip);
3013 if (instr->hydrogen()->DeoptimizesOnHole()) { 2975 if (instr->hydrogen()->DeoptimizesOnHole()) {
3014 DeoptimizeIf(eq, instr->environment()); 2976 DeoptimizeIf(eq, instr->environment());
3015 } else { 2977 } else {
3016 __ b(ne, &skip_assignment); 2978 __ b(ne, &skip_assignment);
3017 } 2979 }
3018 } 2980 }
3019 2981
3020 __ str(value, target); 2982 __ str(value, target);
3021 if (instr->hydrogen()->NeedsWriteBarrier()) { 2983 if (instr->hydrogen()->NeedsWriteBarrier()) {
3022 HType type = instr->hydrogen()->value()->type();
3023 SmiCheck check_needed = 2984 SmiCheck check_needed =
3024 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 2985 instr->hydrogen()->value()->IsHeapObject()
2986 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
3025 __ RecordWriteContextSlot(context, 2987 __ RecordWriteContextSlot(context,
3026 target.offset(), 2988 target.offset(),
3027 value, 2989 value,
3028 scratch, 2990 scratch,
3029 GetLinkRegisterState(), 2991 GetLinkRegisterState(),
3030 kSaveFPRegs, 2992 kSaveFPRegs,
3031 EMIT_REMEMBERED_SET, 2993 EMIT_REMEMBERED_SET,
3032 check_needed); 2994 check_needed);
3033 } 2995 }
3034 2996
(...skipping 1110 matching lines...) Expand 10 before | Expand all | Expand 10 after
4145 CALL_AS_FUNCTION, 4107 CALL_AS_FUNCTION,
4146 R1_UNINITIALIZED); 4108 R1_UNINITIALIZED);
4147 } 4109 }
4148 4110
4149 4111
4150 void LCodeGen::DoCallNew(LCallNew* instr) { 4112 void LCodeGen::DoCallNew(LCallNew* instr) {
4151 ASSERT(ToRegister(instr->constructor()).is(r1)); 4113 ASSERT(ToRegister(instr->constructor()).is(r1));
4152 ASSERT(ToRegister(instr->result()).is(r0)); 4114 ASSERT(ToRegister(instr->result()).is(r0));
4153 4115
4154 __ mov(r0, Operand(instr->arity())); 4116 __ mov(r0, Operand(instr->arity()));
4155 if (FLAG_optimize_constructed_arrays) { 4117 // No cell in r2 for construct type feedback in optimized code
4156 // No cell in r2 for construct type feedback in optimized code 4118 Handle<Object> undefined_value(isolate()->factory()->undefined_value());
4157 Handle<Object> undefined_value(isolate()->heap()->undefined_value(), 4119 __ mov(r2, Operand(undefined_value));
4158 isolate());
4159 __ mov(r2, Operand(undefined_value));
4160 }
4161 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); 4120 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
4162 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 4121 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
4163 } 4122 }
4164 4123
4165 4124
4166 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { 4125 void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
4167 ASSERT(ToRegister(instr->constructor()).is(r1)); 4126 ASSERT(ToRegister(instr->constructor()).is(r1));
4168 ASSERT(ToRegister(instr->result()).is(r0)); 4127 ASSERT(ToRegister(instr->result()).is(r0));
4169 ASSERT(FLAG_optimize_constructed_arrays);
4170 4128
4171 __ mov(r0, Operand(instr->arity())); 4129 __ mov(r0, Operand(instr->arity()));
4172 __ mov(r2, Operand(instr->hydrogen()->property_cell())); 4130 __ mov(r2, Operand(instr->hydrogen()->property_cell()));
4173 ElementsKind kind = instr->hydrogen()->elements_kind(); 4131 ElementsKind kind = instr->hydrogen()->elements_kind();
4174 bool disable_allocation_sites = 4132 bool disable_allocation_sites =
4175 (AllocationSiteInfo::GetMode(kind) == TRACK_ALLOCATION_SITE); 4133 (AllocationSiteInfo::GetMode(kind) == TRACK_ALLOCATION_SITE);
4176 4134
4177 if (instr->arity() == 0) { 4135 if (instr->arity() == 0) {
4178 ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites); 4136 ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites);
4179 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 4137 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
4256 GetLinkRegisterState(), 4214 GetLinkRegisterState(),
4257 kSaveFPRegs, 4215 kSaveFPRegs,
4258 OMIT_REMEMBERED_SET, 4216 OMIT_REMEMBERED_SET,
4259 OMIT_SMI_CHECK); 4217 OMIT_SMI_CHECK);
4260 } 4218 }
4261 } 4219 }
4262 4220
4263 // Do the store. 4221 // Do the store.
4264 Register value = ToRegister(instr->value()); 4222 Register value = ToRegister(instr->value());
4265 ASSERT(!object.is(value)); 4223 ASSERT(!object.is(value));
4266 HType type = instr->hydrogen()->value()->type();
4267 SmiCheck check_needed = 4224 SmiCheck check_needed =
4268 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 4225 instr->hydrogen()->value()->IsHeapObject()
4226 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
4269 if (access.IsInobject()) { 4227 if (access.IsInobject()) {
4270 __ str(value, FieldMemOperand(object, offset)); 4228 __ str(value, FieldMemOperand(object, offset));
4271 if (instr->hydrogen()->NeedsWriteBarrier()) { 4229 if (instr->hydrogen()->NeedsWriteBarrier()) {
4272 // Update the write barrier for the object for in-object properties. 4230 // Update the write barrier for the object for in-object properties.
4273 __ RecordWriteField(object, 4231 __ RecordWriteField(object,
4274 offset, 4232 offset,
4275 value, 4233 value,
4276 scratch, 4234 scratch,
4277 GetLinkRegisterState(), 4235 GetLinkRegisterState(),
4278 kSaveFPRegs, 4236 kSaveFPRegs,
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
4467 if (instr->hydrogen()->key()->representation().IsSmi()) { 4425 if (instr->hydrogen()->key()->representation().IsSmi()) {
4468 __ add(scratch, elements, Operand::PointerOffsetFromSmiKey(key)); 4426 __ add(scratch, elements, Operand::PointerOffsetFromSmiKey(key));
4469 } else { 4427 } else {
4470 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); 4428 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
4471 } 4429 }
4472 offset = FixedArray::OffsetOfElementAt(instr->additional_index()); 4430 offset = FixedArray::OffsetOfElementAt(instr->additional_index());
4473 } 4431 }
4474 __ str(value, FieldMemOperand(store_base, offset)); 4432 __ str(value, FieldMemOperand(store_base, offset));
4475 4433
4476 if (instr->hydrogen()->NeedsWriteBarrier()) { 4434 if (instr->hydrogen()->NeedsWriteBarrier()) {
4477 HType type = instr->hydrogen()->value()->type();
4478 SmiCheck check_needed = 4435 SmiCheck check_needed =
4479 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 4436 instr->hydrogen()->value()->IsHeapObject()
4437 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
4480 // Compute address of modified element and store it into key register. 4438 // Compute address of modified element and store it into key register.
4481 __ add(key, store_base, Operand(offset - kHeapObjectTag)); 4439 __ add(key, store_base, Operand(offset - kHeapObjectTag));
4482 __ RecordWrite(elements, 4440 __ RecordWrite(elements,
4483 key, 4441 key,
4484 value, 4442 value,
4485 GetLinkRegisterState(), 4443 GetLinkRegisterState(),
4486 kSaveFPRegs, 4444 kSaveFPRegs,
4487 EMIT_REMEMBERED_SET, 4445 EMIT_REMEMBERED_SET,
4488 check_needed); 4446 check_needed);
4489 } 4447 }
(...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after
5191 5149
5192 5150
5193 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 5151 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
5194 LOperand* input = instr->value(); 5152 LOperand* input = instr->value();
5195 __ SmiTst(ToRegister(input)); 5153 __ SmiTst(ToRegister(input));
5196 DeoptimizeIf(ne, instr->environment()); 5154 DeoptimizeIf(ne, instr->environment());
5197 } 5155 }
5198 5156
5199 5157
5200 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 5158 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
5201 LOperand* input = instr->value(); 5159 if (!instr->hydrogen()->value()->IsHeapObject()) {
5202 __ SmiTst(ToRegister(input)); 5160 LOperand* input = instr->value();
5203 DeoptimizeIf(eq, instr->environment()); 5161 __ SmiTst(ToRegister(input));
5162 DeoptimizeIf(eq, instr->environment());
5163 }
5204 } 5164 }
5205 5165
5206 5166
5207 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 5167 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
5208 Register input = ToRegister(instr->value()); 5168 Register input = ToRegister(instr->value());
5209 Register scratch = scratch0(); 5169 Register scratch = scratch0();
5210 5170
5211 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); 5171 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
5212 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); 5172 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
5213 5173
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
5358 if (!instr->hydrogen()->CanOmitPrototypeChecks()) { 5318 if (!instr->hydrogen()->CanOmitPrototypeChecks()) {
5359 for (int i = 0; i < prototypes->length(); i++) { 5319 for (int i = 0; i < prototypes->length(); i++) {
5360 __ LoadHeapObject(prototype_reg, prototypes->at(i)); 5320 __ LoadHeapObject(prototype_reg, prototypes->at(i));
5361 __ ldr(map_reg, FieldMemOperand(prototype_reg, HeapObject::kMapOffset)); 5321 __ ldr(map_reg, FieldMemOperand(prototype_reg, HeapObject::kMapOffset));
5362 DoCheckMapCommon(map_reg, maps->at(i), instr->environment()); 5322 DoCheckMapCommon(map_reg, maps->at(i), instr->environment());
5363 } 5323 }
5364 } 5324 }
5365 } 5325 }
5366 5326
5367 5327
5328 void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
5329 class DeferredAllocateObject: public LDeferredCode {
5330 public:
5331 DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr)
5332 : LDeferredCode(codegen), instr_(instr) { }
5333 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); }
5334 virtual LInstruction* instr() { return instr_; }
5335 private:
5336 LAllocateObject* instr_;
5337 };
5338
5339 DeferredAllocateObject* deferred =
5340 new(zone()) DeferredAllocateObject(this, instr);
5341
5342 Register result = ToRegister(instr->result());
5343 Register scratch = ToRegister(instr->temp());
5344 Register scratch2 = ToRegister(instr->temp2());
5345 Handle<JSFunction> constructor = instr->hydrogen()->constructor();
5346 Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
5347 int instance_size = initial_map->instance_size();
5348 ASSERT(initial_map->pre_allocated_property_fields() +
5349 initial_map->unused_property_fields() -
5350 initial_map->inobject_properties() == 0);
5351
5352 __ Allocate(instance_size, result, scratch, scratch2, deferred->entry(),
5353 TAG_OBJECT);
5354
5355 __ bind(deferred->exit());
5356 if (FLAG_debug_code) {
5357 Label is_in_new_space;
5358 __ JumpIfInNewSpace(result, scratch, &is_in_new_space);
5359 __ Abort("Allocated object is not in new-space");
5360 __ bind(&is_in_new_space);
5361 }
5362
5363 // Load the initial map.
5364 Register map = scratch;
5365 __ LoadHeapObject(map, constructor);
5366 __ ldr(map, FieldMemOperand(map, JSFunction::kPrototypeOrInitialMapOffset));
5367
5368 // Initialize map and fields of the newly allocated object.
5369 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
5370 __ str(map, FieldMemOperand(result, JSObject::kMapOffset));
5371 __ LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex);
5372 __ str(scratch, FieldMemOperand(result, JSObject::kElementsOffset));
5373 __ str(scratch, FieldMemOperand(result, JSObject::kPropertiesOffset));
5374 if (initial_map->inobject_properties() != 0) {
5375 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
5376 for (int i = 0; i < initial_map->inobject_properties(); i++) {
5377 int property_offset = JSObject::kHeaderSize + i * kPointerSize;
5378 __ str(scratch, FieldMemOperand(result, property_offset));
5379 }
5380 }
5381 }
5382
5383
5384 void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
5385 Register result = ToRegister(instr->result());
5386 Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
5387 int instance_size = initial_map->instance_size();
5388
5389 // TODO(3095996): Get rid of this. For now, we need to make the
5390 // result register contain a valid pointer because it is already
5391 // contained in the register pointer map.
5392 __ mov(result, Operand::Zero());
5393
5394 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
5395 __ mov(r0, Operand(Smi::FromInt(instance_size)));
5396 __ push(r0);
5397 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
5398 __ StoreToSafepointRegisterSlot(r0, result);
5399 }
5400
5401
5368 void LCodeGen::DoAllocate(LAllocate* instr) { 5402 void LCodeGen::DoAllocate(LAllocate* instr) {
5369 class DeferredAllocate: public LDeferredCode { 5403 class DeferredAllocate: public LDeferredCode {
5370 public: 5404 public:
5371 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) 5405 DeferredAllocate(LCodeGen* codegen, LAllocate* instr)
5372 : LDeferredCode(codegen), instr_(instr) { } 5406 : LDeferredCode(codegen), instr_(instr) { }
5373 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } 5407 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); }
5374 virtual LInstruction* instr() { return instr_; } 5408 virtual LInstruction* instr() { return instr_; }
5375 private: 5409 private:
5376 LAllocate* instr_; 5410 LAllocate* instr_;
5377 }; 5411 };
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
5516 5550
5517 void LCodeGen::DoTypeof(LTypeof* instr) { 5551 void LCodeGen::DoTypeof(LTypeof* instr) {
5518 Register input = ToRegister(instr->value()); 5552 Register input = ToRegister(instr->value());
5519 __ push(input); 5553 __ push(input);
5520 CallRuntime(Runtime::kTypeof, 1, instr); 5554 CallRuntime(Runtime::kTypeof, 1, instr);
5521 } 5555 }
5522 5556
5523 5557
5524 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 5558 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
5525 Register input = ToRegister(instr->value()); 5559 Register input = ToRegister(instr->value());
5526 int true_block = chunk_->LookupDestination(instr->true_block_id());
5527 int false_block = chunk_->LookupDestination(instr->false_block_id());
5528 Label* true_label = chunk_->GetAssemblyLabel(true_block);
5529 Label* false_label = chunk_->GetAssemblyLabel(false_block);
5530 5560
5531 Condition final_branch_condition = EmitTypeofIs(true_label, 5561 Condition final_branch_condition = EmitTypeofIs(instr->TrueLabel(chunk_),
5532 false_label, 5562 instr->FalseLabel(chunk_),
5533 input, 5563 input,
5534 instr->type_literal()); 5564 instr->type_literal());
5535 if (final_branch_condition != kNoCondition) { 5565 if (final_branch_condition != kNoCondition) {
5536 EmitBranch(true_block, false_block, final_branch_condition); 5566 EmitBranch(instr, final_branch_condition);
5537 } 5567 }
5538 } 5568 }
5539 5569
5540 5570
5541 Condition LCodeGen::EmitTypeofIs(Label* true_label, 5571 Condition LCodeGen::EmitTypeofIs(Label* true_label,
5542 Label* false_label, 5572 Label* false_label,
5543 Register input, 5573 Register input,
5544 Handle<String> type_name) { 5574 Handle<String> type_name) {
5545 Condition final_branch_condition = kNoCondition; 5575 Condition final_branch_condition = kNoCondition;
5546 Register scratch = scratch0(); 5576 Register scratch = scratch0();
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
5611 } else { 5641 } else {
5612 __ b(false_label); 5642 __ b(false_label);
5613 } 5643 }
5614 5644
5615 return final_branch_condition; 5645 return final_branch_condition;
5616 } 5646 }
5617 5647
5618 5648
5619 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 5649 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
5620 Register temp1 = ToRegister(instr->temp()); 5650 Register temp1 = ToRegister(instr->temp());
5621 int true_block = chunk_->LookupDestination(instr->true_block_id());
5622 int false_block = chunk_->LookupDestination(instr->false_block_id());
5623 5651
5624 EmitIsConstructCall(temp1, scratch0()); 5652 EmitIsConstructCall(temp1, scratch0());
5625 EmitBranch(true_block, false_block, eq); 5653 EmitBranch(instr, eq);
5626 } 5654 }
5627 5655
5628 5656
5629 void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) { 5657 void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) {
5630 ASSERT(!temp1.is(temp2)); 5658 ASSERT(!temp1.is(temp2));
5631 // Get the frame pointer for the calling frame. 5659 // Get the frame pointer for the calling frame.
5632 __ ldr(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 5660 __ ldr(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
5633 5661
5634 // Skip the arguments adaptor frame if it exists. 5662 // Skip the arguments adaptor frame if it exists.
5635 Label check_frame_marker; 5663 Label check_frame_marker;
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
5771 // the deferred code. 5799 // the deferred code.
5772 } 5800 }
5773 } 5801 }
5774 5802
5775 5803
5776 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { 5804 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
5777 // This is a pseudo-instruction that ensures that the environment here is 5805 // This is a pseudo-instruction that ensures that the environment here is
5778 // properly registered for deoptimization and records the assembler's PC 5806 // properly registered for deoptimization and records the assembler's PC
5779 // offset. 5807 // offset.
5780 LEnvironment* environment = instr->environment(); 5808 LEnvironment* environment = instr->environment();
5781 environment->SetSpilledRegisters(instr->SpilledRegisterArray(),
5782 instr->SpilledDoubleRegisterArray());
5783 5809
5784 // If the environment were already registered, we would have no way of 5810 // If the environment were already registered, we would have no way of
5785 // backpatching it with the spill slot operands. 5811 // backpatching it with the spill slot operands.
5786 ASSERT(!environment->HasBeenRegistered()); 5812 ASSERT(!environment->HasBeenRegistered());
5787 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 5813 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
5788 ASSERT(osr_pc_offset_ == -1); 5814
5789 osr_pc_offset_ = masm()->pc_offset(); 5815 // Normally we record the first unknown OSR value as the entrypoint to the OSR
5816 // code, but if there were none, record the entrypoint here.
5817 if (osr_pc_offset_ == -1) osr_pc_offset_ = masm()->pc_offset();
5790 } 5818 }
5791 5819
5792 5820
5793 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { 5821 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
5794 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 5822 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
5795 __ cmp(r0, ip); 5823 __ cmp(r0, ip);
5796 DeoptimizeIf(eq, instr->environment()); 5824 DeoptimizeIf(eq, instr->environment());
5797 5825
5798 Register null_value = r5; 5826 Register null_value = r5;
5799 __ LoadRoot(null_value, Heap::kNullValueRootIndex); 5827 __ LoadRoot(null_value, Heap::kNullValueRootIndex);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
5880 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); 5908 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index));
5881 __ ldr(result, FieldMemOperand(scratch, 5909 __ ldr(result, FieldMemOperand(scratch,
5882 FixedArray::kHeaderSize - kPointerSize)); 5910 FixedArray::kHeaderSize - kPointerSize));
5883 __ bind(&done); 5911 __ bind(&done);
5884 } 5912 }
5885 5913
5886 5914
5887 #undef __ 5915 #undef __
5888 5916
5889 } } // namespace v8::internal 5917 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698