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 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 __ mov(ecx, GlobalObjectOperand()); | 192 __ mov(ecx, GlobalObjectOperand()); |
193 __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); | 193 __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); |
194 | 194 |
195 __ mov(Operand(esp, receiver_offset), ecx); | 195 __ mov(Operand(esp, receiver_offset), ecx); |
196 | 196 |
197 __ bind(&ok); | 197 __ bind(&ok); |
198 } | 198 } |
199 | 199 |
200 if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { | 200 if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { |
201 // Move state of dynamic frame alignment into edx. | 201 // Move state of dynamic frame alignment into edx. |
202 __ Set(edx, Immediate(kNoAlignmentPadding)); | 202 __ Move(edx, Immediate(kNoAlignmentPadding)); |
203 | 203 |
204 Label do_not_pad, align_loop; | 204 Label do_not_pad, align_loop; |
205 STATIC_ASSERT(kDoubleSize == 2 * kPointerSize); | 205 STATIC_ASSERT(kDoubleSize == 2 * kPointerSize); |
206 // Align esp + 4 to a multiple of 2 * kPointerSize. | 206 // Align esp + 4 to a multiple of 2 * kPointerSize. |
207 __ test(esp, Immediate(kPointerSize)); | 207 __ test(esp, Immediate(kPointerSize)); |
208 __ j(not_zero, &do_not_pad, Label::kNear); | 208 __ j(not_zero, &do_not_pad, Label::kNear); |
209 __ push(Immediate(0)); | 209 __ push(Immediate(0)); |
210 __ mov(ebx, esp); | 210 __ mov(ebx, esp); |
211 __ mov(edx, Immediate(kAlignmentPaddingPushed)); | 211 __ mov(edx, Immediate(kAlignmentPaddingPushed)); |
212 // Copy arguments, receiver, and return address. | 212 // Copy arguments, receiver, and return address. |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
339 | 339 |
340 | 340 |
341 void LCodeGen::GenerateOsrPrologue() { | 341 void LCodeGen::GenerateOsrPrologue() { |
342 // Generate the OSR entry prologue at the first unknown OSR value, or if there | 342 // Generate the OSR entry prologue at the first unknown OSR value, or if there |
343 // are none, at the OSR entrypoint instruction. | 343 // are none, at the OSR entrypoint instruction. |
344 if (osr_pc_offset_ >= 0) return; | 344 if (osr_pc_offset_ >= 0) return; |
345 | 345 |
346 osr_pc_offset_ = masm()->pc_offset(); | 346 osr_pc_offset_ = masm()->pc_offset(); |
347 | 347 |
348 // Move state of dynamic frame alignment into edx. | 348 // Move state of dynamic frame alignment into edx. |
349 __ Set(edx, Immediate(kNoAlignmentPadding)); | 349 __ Move(edx, Immediate(kNoAlignmentPadding)); |
350 | 350 |
351 if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { | 351 if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { |
352 Label do_not_pad, align_loop; | 352 Label do_not_pad, align_loop; |
353 // Align ebp + 4 to a multiple of 2 * kPointerSize. | 353 // Align ebp + 4 to a multiple of 2 * kPointerSize. |
354 __ test(ebp, Immediate(kPointerSize)); | 354 __ test(ebp, Immediate(kPointerSize)); |
355 __ j(zero, &do_not_pad, Label::kNear); | 355 __ j(zero, &do_not_pad, Label::kNear); |
356 __ push(Immediate(0)); | 356 __ push(Immediate(0)); |
357 __ mov(ebx, esp); | 357 __ mov(ebx, esp); |
358 __ mov(edx, Immediate(kAlignmentPaddingPushed)); | 358 __ mov(edx, Immediate(kAlignmentPaddingPushed)); |
359 | 359 |
(...skipping 1097 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1457 // have to deopt if we care about -0, because we can't return that. | 1457 // have to deopt if we care about -0, because we can't return that. |
1458 if (hmod->CheckFlag(HValue::kCanOverflow)) { | 1458 if (hmod->CheckFlag(HValue::kCanOverflow)) { |
1459 Label no_overflow_possible; | 1459 Label no_overflow_possible; |
1460 __ cmp(left_reg, kMinInt); | 1460 __ cmp(left_reg, kMinInt); |
1461 __ j(not_equal, &no_overflow_possible, Label::kNear); | 1461 __ j(not_equal, &no_overflow_possible, Label::kNear); |
1462 __ cmp(right_reg, -1); | 1462 __ cmp(right_reg, -1); |
1463 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1463 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1464 DeoptimizeIf(equal, instr->environment()); | 1464 DeoptimizeIf(equal, instr->environment()); |
1465 } else { | 1465 } else { |
1466 __ j(not_equal, &no_overflow_possible, Label::kNear); | 1466 __ j(not_equal, &no_overflow_possible, Label::kNear); |
1467 __ Set(result_reg, Immediate(0)); | 1467 __ Move(result_reg, Immediate(0)); |
1468 __ jmp(&done, Label::kNear); | 1468 __ jmp(&done, Label::kNear); |
1469 } | 1469 } |
1470 __ bind(&no_overflow_possible); | 1470 __ bind(&no_overflow_possible); |
1471 } | 1471 } |
1472 | 1472 |
1473 // Sign extend dividend in eax into edx:eax. | 1473 // Sign extend dividend in eax into edx:eax. |
1474 __ cdq(); | 1474 __ cdq(); |
1475 | 1475 |
1476 // If we care about -0, test if the dividend is <0 and the result is 0. | 1476 // If we care about -0, test if the dividend is <0 and the result is 0. |
1477 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1477 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1919 } else { | 1919 } else { |
1920 __ sub(ToRegister(left), ToOperand(right)); | 1920 __ sub(ToRegister(left), ToOperand(right)); |
1921 } | 1921 } |
1922 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1922 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
1923 DeoptimizeIf(overflow, instr->environment()); | 1923 DeoptimizeIf(overflow, instr->environment()); |
1924 } | 1924 } |
1925 } | 1925 } |
1926 | 1926 |
1927 | 1927 |
1928 void LCodeGen::DoConstantI(LConstantI* instr) { | 1928 void LCodeGen::DoConstantI(LConstantI* instr) { |
1929 __ Set(ToRegister(instr->result()), Immediate(instr->value())); | 1929 __ Move(ToRegister(instr->result()), Immediate(instr->value())); |
1930 } | 1930 } |
1931 | 1931 |
1932 | 1932 |
1933 void LCodeGen::DoConstantS(LConstantS* instr) { | 1933 void LCodeGen::DoConstantS(LConstantS* instr) { |
1934 __ Set(ToRegister(instr->result()), Immediate(instr->value())); | 1934 __ Move(ToRegister(instr->result()), Immediate(instr->value())); |
1935 } | 1935 } |
1936 | 1936 |
1937 | 1937 |
1938 void LCodeGen::DoConstantD(LConstantD* instr) { | 1938 void LCodeGen::DoConstantD(LConstantD* instr) { |
1939 double v = instr->value(); | 1939 double v = instr->value(); |
1940 uint64_t int_val = BitCast<uint64_t, double>(v); | 1940 uint64_t int_val = BitCast<uint64_t, double>(v); |
1941 int32_t lower = static_cast<int32_t>(int_val); | 1941 int32_t lower = static_cast<int32_t>(int_val); |
1942 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); | 1942 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); |
1943 ASSERT(instr->result()->IsDoubleRegister()); | 1943 ASSERT(instr->result()->IsDoubleRegister()); |
1944 | 1944 |
1945 if (!CpuFeatures::IsSafeForSnapshot(SSE2)) { | 1945 if (!CpuFeatures::IsSafeForSnapshot(SSE2)) { |
1946 __ push(Immediate(upper)); | 1946 __ push(Immediate(upper)); |
1947 __ push(Immediate(lower)); | 1947 __ push(Immediate(lower)); |
1948 X87Register reg = ToX87Register(instr->result()); | 1948 X87Register reg = ToX87Register(instr->result()); |
1949 X87Mov(reg, Operand(esp, 0)); | 1949 X87Mov(reg, Operand(esp, 0)); |
1950 __ add(Operand(esp), Immediate(kDoubleSize)); | 1950 __ add(Operand(esp), Immediate(kDoubleSize)); |
1951 } else { | 1951 } else { |
1952 CpuFeatureScope scope1(masm(), SSE2); | 1952 CpuFeatureScope scope1(masm(), SSE2); |
1953 XMMRegister res = ToDoubleRegister(instr->result()); | 1953 XMMRegister res = ToDoubleRegister(instr->result()); |
1954 if (int_val == 0) { | 1954 if (int_val == 0) { |
1955 __ xorps(res, res); | 1955 __ xorps(res, res); |
1956 } else { | 1956 } else { |
1957 Register temp = ToRegister(instr->temp()); | 1957 Register temp = ToRegister(instr->temp()); |
1958 if (CpuFeatures::IsSupported(SSE4_1)) { | 1958 if (CpuFeatures::IsSupported(SSE4_1)) { |
1959 CpuFeatureScope scope2(masm(), SSE4_1); | 1959 CpuFeatureScope scope2(masm(), SSE4_1); |
1960 if (lower != 0) { | 1960 if (lower != 0) { |
1961 __ Set(temp, Immediate(lower)); | 1961 __ Move(temp, Immediate(lower)); |
1962 __ movd(res, Operand(temp)); | 1962 __ movd(res, Operand(temp)); |
1963 __ Set(temp, Immediate(upper)); | 1963 __ Move(temp, Immediate(upper)); |
1964 __ pinsrd(res, Operand(temp), 1); | 1964 __ pinsrd(res, Operand(temp), 1); |
1965 } else { | 1965 } else { |
1966 __ xorps(res, res); | 1966 __ xorps(res, res); |
1967 __ Set(temp, Immediate(upper)); | 1967 __ Move(temp, Immediate(upper)); |
1968 __ pinsrd(res, Operand(temp), 1); | 1968 __ pinsrd(res, Operand(temp), 1); |
1969 } | 1969 } |
1970 } else { | 1970 } else { |
1971 __ Set(temp, Immediate(upper)); | 1971 __ Move(temp, Immediate(upper)); |
1972 __ movd(res, Operand(temp)); | 1972 __ movd(res, Operand(temp)); |
1973 __ psllq(res, 32); | 1973 __ psllq(res, 32); |
1974 if (lower != 0) { | 1974 if (lower != 0) { |
1975 XMMRegister xmm_scratch = double_scratch0(); | 1975 XMMRegister xmm_scratch = double_scratch0(); |
1976 __ Set(temp, Immediate(lower)); | 1976 __ Move(temp, Immediate(lower)); |
1977 __ movd(xmm_scratch, Operand(temp)); | 1977 __ movd(xmm_scratch, Operand(temp)); |
1978 __ orps(res, xmm_scratch); | 1978 __ orps(res, xmm_scratch); |
1979 } | 1979 } |
1980 } | 1980 } |
1981 } | 1981 } |
1982 } | 1982 } |
1983 } | 1983 } |
1984 | 1984 |
1985 | 1985 |
1986 void LCodeGen::DoConstantE(LConstantE* instr) { | 1986 void LCodeGen::DoConstantE(LConstantE* instr) { |
(...skipping 1978 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3965 DeoptimizeIf(parity_even, instr->environment()); | 3965 DeoptimizeIf(parity_even, instr->environment()); |
3966 __ j(below, &negative_sign, Label::kNear); | 3966 __ j(below, &negative_sign, Label::kNear); |
3967 | 3967 |
3968 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3968 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3969 // Check for negative zero. | 3969 // Check for negative zero. |
3970 Label positive_sign; | 3970 Label positive_sign; |
3971 __ j(above, &positive_sign, Label::kNear); | 3971 __ j(above, &positive_sign, Label::kNear); |
3972 __ movmskpd(output_reg, input_reg); | 3972 __ movmskpd(output_reg, input_reg); |
3973 __ test(output_reg, Immediate(1)); | 3973 __ test(output_reg, Immediate(1)); |
3974 DeoptimizeIf(not_zero, instr->environment()); | 3974 DeoptimizeIf(not_zero, instr->environment()); |
3975 __ Set(output_reg, Immediate(0)); | 3975 __ Move(output_reg, Immediate(0)); |
3976 __ jmp(&done, Label::kNear); | 3976 __ jmp(&done, Label::kNear); |
3977 __ bind(&positive_sign); | 3977 __ bind(&positive_sign); |
3978 } | 3978 } |
3979 | 3979 |
3980 // Use truncating instruction (OK because input is positive). | 3980 // Use truncating instruction (OK because input is positive). |
3981 __ cvttsd2si(output_reg, Operand(input_reg)); | 3981 __ cvttsd2si(output_reg, Operand(input_reg)); |
3982 // Overflow is signalled with minint. | 3982 // Overflow is signalled with minint. |
3983 __ cmp(output_reg, 0x80000000u); | 3983 __ cmp(output_reg, 0x80000000u); |
3984 DeoptimizeIf(equal, instr->environment()); | 3984 DeoptimizeIf(equal, instr->environment()); |
3985 __ jmp(&done, Label::kNear); | 3985 __ jmp(&done, Label::kNear); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4050 __ bind(&round_to_zero); | 4050 __ bind(&round_to_zero); |
4051 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if | 4051 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if |
4052 // we can ignore the difference between a result of -0 and +0. | 4052 // we can ignore the difference between a result of -0 and +0. |
4053 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4053 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
4054 // If the sign is positive, we return +0. | 4054 // If the sign is positive, we return +0. |
4055 __ movmskpd(output_reg, input_reg); | 4055 __ movmskpd(output_reg, input_reg); |
4056 __ test(output_reg, Immediate(1)); | 4056 __ test(output_reg, Immediate(1)); |
4057 __ RecordComment("Minus zero"); | 4057 __ RecordComment("Minus zero"); |
4058 DeoptimizeIf(not_zero, instr->environment()); | 4058 DeoptimizeIf(not_zero, instr->environment()); |
4059 } | 4059 } |
4060 __ Set(output_reg, Immediate(0)); | 4060 __ Move(output_reg, Immediate(0)); |
4061 __ bind(&done); | 4061 __ bind(&done); |
4062 } | 4062 } |
4063 | 4063 |
4064 | 4064 |
4065 void LCodeGen::DoMathSqrt(LMathSqrt* instr) { | 4065 void LCodeGen::DoMathSqrt(LMathSqrt* instr) { |
4066 CpuFeatureScope scope(masm(), SSE2); | 4066 CpuFeatureScope scope(masm(), SSE2); |
4067 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 4067 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
4068 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 4068 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
4069 __ sqrtsd(input_reg, input_reg); | 4069 __ sqrtsd(input_reg, input_reg); |
4070 } | 4070 } |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4171 | 4171 |
4172 | 4172 |
4173 void LCodeGen::DoMathClz32(LMathClz32* instr) { | 4173 void LCodeGen::DoMathClz32(LMathClz32* instr) { |
4174 CpuFeatureScope scope(masm(), SSE2); | 4174 CpuFeatureScope scope(masm(), SSE2); |
4175 Register input = ToRegister(instr->value()); | 4175 Register input = ToRegister(instr->value()); |
4176 Register result = ToRegister(instr->result()); | 4176 Register result = ToRegister(instr->result()); |
4177 Label not_zero_input; | 4177 Label not_zero_input; |
4178 __ bsr(result, input); | 4178 __ bsr(result, input); |
4179 | 4179 |
4180 __ j(not_zero, ¬_zero_input); | 4180 __ j(not_zero, ¬_zero_input); |
4181 __ Set(result, Immediate(63)); // 63^31 == 32 | 4181 __ Move(result, Immediate(63)); // 63^31 == 32 |
4182 | 4182 |
4183 __ bind(¬_zero_input); | 4183 __ bind(¬_zero_input); |
4184 __ xor_(result, Immediate(31)); // for x in [0..31], 31^x == 31-x. | 4184 __ xor_(result, Immediate(31)); // for x in [0..31], 31^x == 31-x. |
4185 } | 4185 } |
4186 | 4186 |
4187 | 4187 |
4188 void LCodeGen::DoMathExp(LMathExp* instr) { | 4188 void LCodeGen::DoMathExp(LMathExp* instr) { |
4189 CpuFeatureScope scope(masm(), SSE2); | 4189 CpuFeatureScope scope(masm(), SSE2); |
4190 XMMRegister input = ToDoubleRegister(instr->value()); | 4190 XMMRegister input = ToDoubleRegister(instr->value()); |
4191 XMMRegister result = ToDoubleRegister(instr->result()); | 4191 XMMRegister result = ToDoubleRegister(instr->result()); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4231 | 4231 |
4232 | 4232 |
4233 void LCodeGen::DoCallNew(LCallNew* instr) { | 4233 void LCodeGen::DoCallNew(LCallNew* instr) { |
4234 ASSERT(ToRegister(instr->context()).is(esi)); | 4234 ASSERT(ToRegister(instr->context()).is(esi)); |
4235 ASSERT(ToRegister(instr->constructor()).is(edi)); | 4235 ASSERT(ToRegister(instr->constructor()).is(edi)); |
4236 ASSERT(ToRegister(instr->result()).is(eax)); | 4236 ASSERT(ToRegister(instr->result()).is(eax)); |
4237 | 4237 |
4238 // No cell in ebx for construct type feedback in optimized code | 4238 // No cell in ebx for construct type feedback in optimized code |
4239 __ mov(ebx, isolate()->factory()->undefined_value()); | 4239 __ mov(ebx, isolate()->factory()->undefined_value()); |
4240 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 4240 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
4241 __ Set(eax, Immediate(instr->arity())); | 4241 __ Move(eax, Immediate(instr->arity())); |
4242 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4242 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
4243 } | 4243 } |
4244 | 4244 |
4245 | 4245 |
4246 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { | 4246 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
4247 ASSERT(ToRegister(instr->context()).is(esi)); | 4247 ASSERT(ToRegister(instr->context()).is(esi)); |
4248 ASSERT(ToRegister(instr->constructor()).is(edi)); | 4248 ASSERT(ToRegister(instr->constructor()).is(edi)); |
4249 ASSERT(ToRegister(instr->result()).is(eax)); | 4249 ASSERT(ToRegister(instr->result()).is(eax)); |
4250 | 4250 |
4251 __ Set(eax, Immediate(instr->arity())); | 4251 __ Move(eax, Immediate(instr->arity())); |
4252 __ mov(ebx, isolate()->factory()->undefined_value()); | 4252 __ mov(ebx, isolate()->factory()->undefined_value()); |
4253 ElementsKind kind = instr->hydrogen()->elements_kind(); | 4253 ElementsKind kind = instr->hydrogen()->elements_kind(); |
4254 AllocationSiteOverrideMode override_mode = | 4254 AllocationSiteOverrideMode override_mode = |
4255 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) | 4255 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) |
4256 ? DISABLE_ALLOCATION_SITES | 4256 ? DISABLE_ALLOCATION_SITES |
4257 : DONT_OVERRIDE; | 4257 : DONT_OVERRIDE; |
4258 | 4258 |
4259 if (instr->arity() == 0) { | 4259 if (instr->arity() == 0) { |
4260 ArrayNoArgumentConstructorStub stub(kind, override_mode); | 4260 ArrayNoArgumentConstructorStub stub(kind, override_mode); |
4261 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4261 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4783 } | 4783 } |
4784 | 4784 |
4785 | 4785 |
4786 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { | 4786 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { |
4787 Register string = ToRegister(instr->string()); | 4787 Register string = ToRegister(instr->string()); |
4788 Register result = ToRegister(instr->result()); | 4788 Register result = ToRegister(instr->result()); |
4789 | 4789 |
4790 // TODO(3095996): Get rid of this. For now, we need to make the | 4790 // TODO(3095996): Get rid of this. For now, we need to make the |
4791 // result register contain a valid pointer because it is already | 4791 // result register contain a valid pointer because it is already |
4792 // contained in the register pointer map. | 4792 // contained in the register pointer map. |
4793 __ Set(result, Immediate(0)); | 4793 __ Move(result, Immediate(0)); |
4794 | 4794 |
4795 PushSafepointRegistersScope scope(this); | 4795 PushSafepointRegistersScope scope(this); |
4796 __ push(string); | 4796 __ push(string); |
4797 // Push the index as a smi. This is safe because of the checks in | 4797 // Push the index as a smi. This is safe because of the checks in |
4798 // DoStringCharCodeAt above. | 4798 // DoStringCharCodeAt above. |
4799 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); | 4799 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); |
4800 if (instr->index()->IsConstantOperand()) { | 4800 if (instr->index()->IsConstantOperand()) { |
4801 Immediate immediate = ToImmediate(LConstantOperand::cast(instr->index()), | 4801 Immediate immediate = ToImmediate(LConstantOperand::cast(instr->index()), |
4802 Representation::Smi()); | 4802 Representation::Smi()); |
4803 __ push(immediate); | 4803 __ push(immediate); |
(...skipping 28 matching lines...) Expand all Loading... |
4832 DeferredStringCharFromCode* deferred = | 4832 DeferredStringCharFromCode* deferred = |
4833 new(zone()) DeferredStringCharFromCode(this, instr, x87_stack_); | 4833 new(zone()) DeferredStringCharFromCode(this, instr, x87_stack_); |
4834 | 4834 |
4835 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); | 4835 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); |
4836 Register char_code = ToRegister(instr->char_code()); | 4836 Register char_code = ToRegister(instr->char_code()); |
4837 Register result = ToRegister(instr->result()); | 4837 Register result = ToRegister(instr->result()); |
4838 ASSERT(!char_code.is(result)); | 4838 ASSERT(!char_code.is(result)); |
4839 | 4839 |
4840 __ cmp(char_code, String::kMaxOneByteCharCode); | 4840 __ cmp(char_code, String::kMaxOneByteCharCode); |
4841 __ j(above, deferred->entry()); | 4841 __ j(above, deferred->entry()); |
4842 __ Set(result, Immediate(factory()->single_character_string_cache())); | 4842 __ Move(result, Immediate(factory()->single_character_string_cache())); |
4843 __ mov(result, FieldOperand(result, | 4843 __ mov(result, FieldOperand(result, |
4844 char_code, times_pointer_size, | 4844 char_code, times_pointer_size, |
4845 FixedArray::kHeaderSize)); | 4845 FixedArray::kHeaderSize)); |
4846 __ cmp(result, factory()->undefined_value()); | 4846 __ cmp(result, factory()->undefined_value()); |
4847 __ j(equal, deferred->entry()); | 4847 __ j(equal, deferred->entry()); |
4848 __ bind(deferred->exit()); | 4848 __ bind(deferred->exit()); |
4849 } | 4849 } |
4850 | 4850 |
4851 | 4851 |
4852 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { | 4852 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { |
4853 Register char_code = ToRegister(instr->char_code()); | 4853 Register char_code = ToRegister(instr->char_code()); |
4854 Register result = ToRegister(instr->result()); | 4854 Register result = ToRegister(instr->result()); |
4855 | 4855 |
4856 // TODO(3095996): Get rid of this. For now, we need to make the | 4856 // TODO(3095996): Get rid of this. For now, we need to make the |
4857 // result register contain a valid pointer because it is already | 4857 // result register contain a valid pointer because it is already |
4858 // contained in the register pointer map. | 4858 // contained in the register pointer map. |
4859 __ Set(result, Immediate(0)); | 4859 __ Move(result, Immediate(0)); |
4860 | 4860 |
4861 PushSafepointRegistersScope scope(this); | 4861 PushSafepointRegistersScope scope(this); |
4862 __ SmiTag(char_code); | 4862 __ SmiTag(char_code); |
4863 __ push(char_code); | 4863 __ push(char_code); |
4864 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); | 4864 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); |
4865 __ StoreToSafepointRegisterSlot(result, eax); | 4865 __ StoreToSafepointRegisterSlot(result, eax); |
4866 } | 4866 } |
4867 | 4867 |
4868 | 4868 |
4869 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4869 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5014 __ AllocateHeapNumber(reg, tmp, no_reg, &slow); | 5014 __ AllocateHeapNumber(reg, tmp, no_reg, &slow); |
5015 __ jmp(&done, Label::kNear); | 5015 __ jmp(&done, Label::kNear); |
5016 } | 5016 } |
5017 | 5017 |
5018 // Slow case: Call the runtime system to do the number allocation. | 5018 // Slow case: Call the runtime system to do the number allocation. |
5019 __ bind(&slow); | 5019 __ bind(&slow); |
5020 { | 5020 { |
5021 // TODO(3095996): Put a valid pointer value in the stack slot where the | 5021 // TODO(3095996): Put a valid pointer value in the stack slot where the |
5022 // result register is stored, as this register is in the pointer map, but | 5022 // result register is stored, as this register is in the pointer map, but |
5023 // contains an integer value. | 5023 // contains an integer value. |
5024 __ Set(reg, Immediate(0)); | 5024 __ Move(reg, Immediate(0)); |
5025 | 5025 |
5026 // Preserve the value of all registers. | 5026 // Preserve the value of all registers. |
5027 PushSafepointRegistersScope scope(this); | 5027 PushSafepointRegistersScope scope(this); |
5028 | 5028 |
5029 // NumberTagI and NumberTagD use the context from the frame, rather than | 5029 // NumberTagI and NumberTagD use the context from the frame, rather than |
5030 // the environment's HContext or HInlinedContext value. | 5030 // the environment's HContext or HInlinedContext value. |
5031 // They only call Runtime::kAllocateHeapNumber. | 5031 // They only call Runtime::kAllocateHeapNumber. |
5032 // The corresponding HChange instructions are added in a phase that does | 5032 // The corresponding HChange instructions are added in a phase that does |
5033 // not have easy access to the local context. | 5033 // not have easy access to the local context. |
5034 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 5034 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5091 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); | 5091 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); |
5092 } | 5092 } |
5093 } | 5093 } |
5094 | 5094 |
5095 | 5095 |
5096 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 5096 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
5097 // TODO(3095996): Get rid of this. For now, we need to make the | 5097 // TODO(3095996): Get rid of this. For now, we need to make the |
5098 // result register contain a valid pointer because it is already | 5098 // result register contain a valid pointer because it is already |
5099 // contained in the register pointer map. | 5099 // contained in the register pointer map. |
5100 Register reg = ToRegister(instr->result()); | 5100 Register reg = ToRegister(instr->result()); |
5101 __ Set(reg, Immediate(0)); | 5101 __ Move(reg, Immediate(0)); |
5102 | 5102 |
5103 PushSafepointRegistersScope scope(this); | 5103 PushSafepointRegistersScope scope(this); |
5104 // NumberTagI and NumberTagD use the context from the frame, rather than | 5104 // NumberTagI and NumberTagD use the context from the frame, rather than |
5105 // the environment's HContext or HInlinedContext value. | 5105 // the environment's HContext or HInlinedContext value. |
5106 // They only call Runtime::kAllocateHeapNumber. | 5106 // They only call Runtime::kAllocateHeapNumber. |
5107 // The corresponding HChange instructions are added in a phase that does | 5107 // The corresponding HChange instructions are added in a phase that does |
5108 // not have easy access to the local context. | 5108 // not have easy access to the local context. |
5109 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 5109 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
5110 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 5110 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
5111 RecordSafepointWithRegisters( | 5111 RecordSafepointWithRegisters( |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5291 factory()->heap_number_map()); | 5291 factory()->heap_number_map()); |
5292 __ j(not_equal, &no_heap_number, Label::kNear); | 5292 __ j(not_equal, &no_heap_number, Label::kNear); |
5293 __ TruncateHeapNumberToI(input_reg, input_reg); | 5293 __ TruncateHeapNumberToI(input_reg, input_reg); |
5294 __ jmp(done); | 5294 __ jmp(done); |
5295 | 5295 |
5296 __ bind(&no_heap_number); | 5296 __ bind(&no_heap_number); |
5297 // Check for Oddballs. Undefined/False is converted to zero and True to one | 5297 // Check for Oddballs. Undefined/False is converted to zero and True to one |
5298 // for truncating conversions. | 5298 // for truncating conversions. |
5299 __ cmp(input_reg, factory()->undefined_value()); | 5299 __ cmp(input_reg, factory()->undefined_value()); |
5300 __ j(not_equal, &check_bools, Label::kNear); | 5300 __ j(not_equal, &check_bools, Label::kNear); |
5301 __ Set(input_reg, Immediate(0)); | 5301 __ Move(input_reg, Immediate(0)); |
5302 __ jmp(done); | 5302 __ jmp(done); |
5303 | 5303 |
5304 __ bind(&check_bools); | 5304 __ bind(&check_bools); |
5305 __ cmp(input_reg, factory()->true_value()); | 5305 __ cmp(input_reg, factory()->true_value()); |
5306 __ j(not_equal, &check_false, Label::kNear); | 5306 __ j(not_equal, &check_false, Label::kNear); |
5307 __ Set(input_reg, Immediate(1)); | 5307 __ Move(input_reg, Immediate(1)); |
5308 __ jmp(done); | 5308 __ jmp(done); |
5309 | 5309 |
5310 __ bind(&check_false); | 5310 __ bind(&check_false); |
5311 __ cmp(input_reg, factory()->false_value()); | 5311 __ cmp(input_reg, factory()->false_value()); |
5312 __ RecordComment("Deferred TaggedToI: cannot truncate"); | 5312 __ RecordComment("Deferred TaggedToI: cannot truncate"); |
5313 DeoptimizeIf(not_equal, instr->environment()); | 5313 DeoptimizeIf(not_equal, instr->environment()); |
5314 __ Set(input_reg, Immediate(0)); | 5314 __ Move(input_reg, Immediate(0)); |
5315 } else { | 5315 } else { |
5316 Label bailout; | 5316 Label bailout; |
5317 XMMRegister scratch = (instr->temp() != NULL) | 5317 XMMRegister scratch = (instr->temp() != NULL) |
5318 ? ToDoubleRegister(instr->temp()) | 5318 ? ToDoubleRegister(instr->temp()) |
5319 : no_xmm_reg; | 5319 : no_xmm_reg; |
5320 __ TaggedToI(input_reg, input_reg, scratch, | 5320 __ TaggedToI(input_reg, input_reg, scratch, |
5321 instr->hydrogen()->GetMinusZeroMode(), &bailout); | 5321 instr->hydrogen()->GetMinusZeroMode(), &bailout); |
5322 __ jmp(done); | 5322 __ jmp(done); |
5323 __ bind(&bailout); | 5323 __ bind(&bailout); |
5324 DeoptimizeIf(no_condition, instr->environment()); | 5324 DeoptimizeIf(no_condition, instr->environment()); |
(...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5895 } | 5895 } |
5896 } | 5896 } |
5897 | 5897 |
5898 | 5898 |
5899 void LCodeGen::DoDeferredAllocate(LAllocate* instr) { | 5899 void LCodeGen::DoDeferredAllocate(LAllocate* instr) { |
5900 Register result = ToRegister(instr->result()); | 5900 Register result = ToRegister(instr->result()); |
5901 | 5901 |
5902 // TODO(3095996): Get rid of this. For now, we need to make the | 5902 // TODO(3095996): Get rid of this. For now, we need to make the |
5903 // result register contain a valid pointer because it is already | 5903 // result register contain a valid pointer because it is already |
5904 // contained in the register pointer map. | 5904 // contained in the register pointer map. |
5905 __ Set(result, Immediate(Smi::FromInt(0))); | 5905 __ Move(result, Immediate(Smi::FromInt(0))); |
5906 | 5906 |
5907 PushSafepointRegistersScope scope(this); | 5907 PushSafepointRegistersScope scope(this); |
5908 if (instr->size()->IsRegister()) { | 5908 if (instr->size()->IsRegister()) { |
5909 Register size = ToRegister(instr->size()); | 5909 Register size = ToRegister(instr->size()); |
5910 ASSERT(!size.is(result)); | 5910 ASSERT(!size.is(result)); |
5911 __ SmiTag(ToRegister(instr->size())); | 5911 __ SmiTag(ToRegister(instr->size())); |
5912 __ push(size); | 5912 __ push(size); |
5913 } else { | 5913 } else { |
5914 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5914 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
5915 __ push(Immediate(Smi::FromInt(size))); | 5915 __ push(Immediate(Smi::FromInt(size))); |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6352 FixedArray::kHeaderSize - kPointerSize)); | 6352 FixedArray::kHeaderSize - kPointerSize)); |
6353 __ bind(&done); | 6353 __ bind(&done); |
6354 } | 6354 } |
6355 | 6355 |
6356 | 6356 |
6357 #undef __ | 6357 #undef __ |
6358 | 6358 |
6359 } } // namespace v8::internal | 6359 } } // namespace v8::internal |
6360 | 6360 |
6361 #endif // V8_TARGET_ARCH_IA32 | 6361 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |