| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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, ¬_string); | 2261 __ b(ge, ¬_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(¬_string); | 2266 __ bind(¬_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, ¬_heap_number); | 2280 __ b(ne, ¬_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(¬_heap_number); | 2286 __ bind(¬_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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |