| 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 |