| 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 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 } | 333 } |
| 334 | 334 |
| 335 | 335 |
| 336 void LCodeGen::GenerateOsrPrologue() { | 336 void LCodeGen::GenerateOsrPrologue() { |
| 337 // Generate the OSR entry prologue at the first unknown OSR value, or if there | 337 // Generate the OSR entry prologue at the first unknown OSR value, or if there |
| 338 // are none, at the OSR entrypoint instruction. | 338 // are none, at the OSR entrypoint instruction. |
| 339 if (osr_pc_offset_ >= 0) return; | 339 if (osr_pc_offset_ >= 0) return; |
| 340 | 340 |
| 341 osr_pc_offset_ = masm()->pc_offset(); | 341 osr_pc_offset_ = masm()->pc_offset(); |
| 342 | 342 |
| 343 // Move state of dynamic frame alignment into edx. |
| 344 __ mov(edx, Immediate(kNoAlignmentPadding)); |
| 345 |
| 346 if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { |
| 347 Label do_not_pad, align_loop; |
| 348 // Align ebp + 4 to a multiple of 2 * kPointerSize. |
| 349 __ test(ebp, Immediate(kPointerSize)); |
| 350 __ j(zero, &do_not_pad, Label::kNear); |
| 351 __ push(Immediate(0)); |
| 352 __ mov(ebx, esp); |
| 353 __ mov(edx, Immediate(kAlignmentPaddingPushed)); |
| 354 |
| 355 // Move all parts of the frame over one word. The frame consists of: |
| 356 // unoptimized frame slots, alignment state, context, frame pointer, return |
| 357 // address, receiver, and the arguments. |
| 358 __ mov(ecx, Immediate(scope()->num_parameters() + |
| 359 5 + graph()->osr()->UnoptimizedFrameSlots())); |
| 360 |
| 361 __ bind(&align_loop); |
| 362 __ mov(eax, Operand(ebx, 1 * kPointerSize)); |
| 363 __ mov(Operand(ebx, 0), eax); |
| 364 __ add(Operand(ebx), Immediate(kPointerSize)); |
| 365 __ dec(ecx); |
| 366 __ j(not_zero, &align_loop, Label::kNear); |
| 367 __ mov(Operand(ebx, 0), Immediate(kAlignmentZapValue)); |
| 368 __ sub(Operand(ebp), Immediate(kPointerSize)); |
| 369 __ bind(&do_not_pad); |
| 370 } |
| 371 |
| 343 // Save the first local, which is overwritten by the alignment state. | 372 // Save the first local, which is overwritten by the alignment state. |
| 344 Operand alignment_loc = MemOperand(ebp, -3 * kPointerSize); | 373 Operand alignment_loc = MemOperand(ebp, -3 * kPointerSize); |
| 345 __ push(alignment_loc); | 374 __ push(alignment_loc); |
| 346 | 375 |
| 347 // Set the dynamic frame alignment state to "not aligned". | 376 // Set the dynamic frame alignment state. |
| 348 __ mov(alignment_loc, Immediate(kNoAlignmentPadding)); | 377 __ mov(alignment_loc, edx); |
| 349 | 378 |
| 350 // Adjust the frame size, subsuming the unoptimized frame into the | 379 // Adjust the frame size, subsuming the unoptimized frame into the |
| 351 // optimized frame. | 380 // optimized frame. |
| 352 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); | 381 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); |
| 353 ASSERT(slots >= 1); | 382 ASSERT(slots >= 1); |
| 354 __ sub(esp, Immediate((slots - 1) * kPointerSize)); | 383 __ sub(esp, Immediate((slots - 1) * kPointerSize)); |
| 355 } | 384 } |
| 356 | 385 |
| 357 | 386 |
| 358 bool LCodeGen::GenerateBody() { | 387 bool LCodeGen::GenerateBody() { |
| (...skipping 1601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1960 } else { | 1989 } else { |
| 1961 __ xorps(res, res); | 1990 __ xorps(res, res); |
| 1962 __ Set(temp, Immediate(upper)); | 1991 __ Set(temp, Immediate(upper)); |
| 1963 __ pinsrd(res, Operand(temp), 1); | 1992 __ pinsrd(res, Operand(temp), 1); |
| 1964 } | 1993 } |
| 1965 } else { | 1994 } else { |
| 1966 __ Set(temp, Immediate(upper)); | 1995 __ Set(temp, Immediate(upper)); |
| 1967 __ movd(res, Operand(temp)); | 1996 __ movd(res, Operand(temp)); |
| 1968 __ psllq(res, 32); | 1997 __ psllq(res, 32); |
| 1969 if (lower != 0) { | 1998 if (lower != 0) { |
| 1999 XMMRegister xmm_scratch = double_scratch0(); |
| 1970 __ Set(temp, Immediate(lower)); | 2000 __ Set(temp, Immediate(lower)); |
| 1971 __ movd(xmm0, Operand(temp)); | 2001 __ movd(xmm_scratch, Operand(temp)); |
| 1972 __ por(res, xmm0); | 2002 __ por(res, xmm_scratch); |
| 1973 } | 2003 } |
| 1974 } | 2004 } |
| 1975 } | 2005 } |
| 1976 } | 2006 } |
| 1977 } | 2007 } |
| 1978 | 2008 |
| 1979 | 2009 |
| 1980 void LCodeGen::DoConstantE(LConstantE* instr) { | 2010 void LCodeGen::DoConstantE(LConstantE* instr) { |
| 1981 __ lea(ToRegister(instr->result()), Operand::StaticVariable(instr->value())); | 2011 __ lea(ToRegister(instr->result()), Operand::StaticVariable(instr->value())); |
| 1982 } | 2012 } |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2171 Condition condition = (operation == HMathMinMax::kMathMin) ? below : above; | 2201 Condition condition = (operation == HMathMinMax::kMathMin) ? below : above; |
| 2172 XMMRegister left_reg = ToDoubleRegister(left); | 2202 XMMRegister left_reg = ToDoubleRegister(left); |
| 2173 XMMRegister right_reg = ToDoubleRegister(right); | 2203 XMMRegister right_reg = ToDoubleRegister(right); |
| 2174 __ ucomisd(left_reg, right_reg); | 2204 __ ucomisd(left_reg, right_reg); |
| 2175 __ j(parity_even, &check_nan_left, Label::kNear); // At least one NaN. | 2205 __ j(parity_even, &check_nan_left, Label::kNear); // At least one NaN. |
| 2176 __ j(equal, &check_zero, Label::kNear); // left == right. | 2206 __ j(equal, &check_zero, Label::kNear); // left == right. |
| 2177 __ j(condition, &return_left, Label::kNear); | 2207 __ j(condition, &return_left, Label::kNear); |
| 2178 __ jmp(&return_right, Label::kNear); | 2208 __ jmp(&return_right, Label::kNear); |
| 2179 | 2209 |
| 2180 __ bind(&check_zero); | 2210 __ bind(&check_zero); |
| 2181 XMMRegister xmm_scratch = xmm0; | 2211 XMMRegister xmm_scratch = double_scratch0(); |
| 2182 __ xorps(xmm_scratch, xmm_scratch); | 2212 __ xorps(xmm_scratch, xmm_scratch); |
| 2183 __ ucomisd(left_reg, xmm_scratch); | 2213 __ ucomisd(left_reg, xmm_scratch); |
| 2184 __ j(not_equal, &return_left, Label::kNear); // left == right != 0. | 2214 __ j(not_equal, &return_left, Label::kNear); // left == right != 0. |
| 2185 // At this point, both left and right are either 0 or -0. | 2215 // At this point, both left and right are either 0 or -0. |
| 2186 if (operation == HMathMinMax::kMathMin) { | 2216 if (operation == HMathMinMax::kMathMin) { |
| 2187 __ orpd(left_reg, right_reg); | 2217 __ orpd(left_reg, right_reg); |
| 2188 } else { | 2218 } else { |
| 2189 // Since we operate on +0 and/or -0, addsd and andsd have the same effect. | 2219 // Since we operate on +0 and/or -0, addsd and andsd have the same effect. |
| 2190 __ addsd(left_reg, right_reg); | 2220 __ addsd(left_reg, right_reg); |
| 2191 } | 2221 } |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2331 void LCodeGen::EmitFalseBranch(InstrType instr, Condition cc) { | 2361 void LCodeGen::EmitFalseBranch(InstrType instr, Condition cc) { |
| 2332 int false_block = instr->FalseDestination(chunk_); | 2362 int false_block = instr->FalseDestination(chunk_); |
| 2333 if (cc == no_condition) { | 2363 if (cc == no_condition) { |
| 2334 __ jmp(chunk_->GetAssemblyLabel(false_block)); | 2364 __ jmp(chunk_->GetAssemblyLabel(false_block)); |
| 2335 } else { | 2365 } else { |
| 2336 __ j(cc, chunk_->GetAssemblyLabel(false_block)); | 2366 __ j(cc, chunk_->GetAssemblyLabel(false_block)); |
| 2337 } | 2367 } |
| 2338 } | 2368 } |
| 2339 | 2369 |
| 2340 | 2370 |
| 2341 void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) { | |
| 2342 Representation r = instr->hydrogen()->value()->representation(); | |
| 2343 if (r.IsSmiOrInteger32() || r.IsDouble()) { | |
| 2344 EmitBranch(instr, no_condition); | |
| 2345 } else { | |
| 2346 ASSERT(r.IsTagged()); | |
| 2347 Register reg = ToRegister(instr->value()); | |
| 2348 HType type = instr->hydrogen()->value()->type(); | |
| 2349 if (type.IsTaggedNumber()) { | |
| 2350 EmitBranch(instr, no_condition); | |
| 2351 } | |
| 2352 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); | |
| 2353 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | |
| 2354 factory()->heap_number_map()); | |
| 2355 EmitBranch(instr, equal); | |
| 2356 } | |
| 2357 } | |
| 2358 | |
| 2359 | |
| 2360 void LCodeGen::DoBranch(LBranch* instr) { | 2371 void LCodeGen::DoBranch(LBranch* instr) { |
| 2361 Representation r = instr->hydrogen()->value()->representation(); | 2372 Representation r = instr->hydrogen()->value()->representation(); |
| 2362 if (r.IsSmiOrInteger32()) { | 2373 if (r.IsSmiOrInteger32()) { |
| 2363 Register reg = ToRegister(instr->value()); | 2374 Register reg = ToRegister(instr->value()); |
| 2364 __ test(reg, Operand(reg)); | 2375 __ test(reg, Operand(reg)); |
| 2365 EmitBranch(instr, not_zero); | 2376 EmitBranch(instr, not_zero); |
| 2366 } else if (r.IsDouble()) { | 2377 } else if (r.IsDouble()) { |
| 2367 ASSERT(!info()->IsStub()); | 2378 ASSERT(!info()->IsStub()); |
| 2368 CpuFeatureScope scope(masm(), SSE2); | 2379 CpuFeatureScope scope(masm(), SSE2); |
| 2369 XMMRegister reg = ToDoubleRegister(instr->value()); | 2380 XMMRegister reg = ToDoubleRegister(instr->value()); |
| 2370 __ xorps(xmm0, xmm0); | 2381 XMMRegister xmm_scratch = double_scratch0(); |
| 2371 __ ucomisd(reg, xmm0); | 2382 __ xorps(xmm_scratch, xmm_scratch); |
| 2383 __ ucomisd(reg, xmm_scratch); |
| 2372 EmitBranch(instr, not_equal); | 2384 EmitBranch(instr, not_equal); |
| 2373 } else { | 2385 } else { |
| 2374 ASSERT(r.IsTagged()); | 2386 ASSERT(r.IsTagged()); |
| 2375 Register reg = ToRegister(instr->value()); | 2387 Register reg = ToRegister(instr->value()); |
| 2376 HType type = instr->hydrogen()->value()->type(); | 2388 HType type = instr->hydrogen()->value()->type(); |
| 2377 if (type.IsBoolean()) { | 2389 if (type.IsBoolean()) { |
| 2378 ASSERT(!info()->IsStub()); | 2390 ASSERT(!info()->IsStub()); |
| 2379 __ cmp(reg, factory()->true_value()); | 2391 __ cmp(reg, factory()->true_value()); |
| 2380 EmitBranch(instr, equal); | 2392 EmitBranch(instr, equal); |
| 2381 } else if (type.IsSmi()) { | 2393 } else if (type.IsSmi()) { |
| 2382 ASSERT(!info()->IsStub()); | 2394 ASSERT(!info()->IsStub()); |
| 2383 __ test(reg, Operand(reg)); | 2395 __ test(reg, Operand(reg)); |
| 2384 EmitBranch(instr, not_equal); | 2396 EmitBranch(instr, not_equal); |
| 2385 } else if (type.IsJSArray()) { | 2397 } else if (type.IsJSArray()) { |
| 2386 ASSERT(!info()->IsStub()); | 2398 ASSERT(!info()->IsStub()); |
| 2387 EmitBranch(instr, no_condition); | 2399 EmitBranch(instr, no_condition); |
| 2388 } else if (type.IsHeapNumber()) { | 2400 } else if (type.IsHeapNumber()) { |
| 2389 ASSERT(!info()->IsStub()); | 2401 ASSERT(!info()->IsStub()); |
| 2390 CpuFeatureScope scope(masm(), SSE2); | 2402 CpuFeatureScope scope(masm(), SSE2); |
| 2391 __ xorps(xmm0, xmm0); | 2403 XMMRegister xmm_scratch = double_scratch0(); |
| 2392 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); | 2404 __ xorps(xmm_scratch, xmm_scratch); |
| 2405 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); |
| 2393 EmitBranch(instr, not_equal); | 2406 EmitBranch(instr, not_equal); |
| 2394 } else if (type.IsString()) { | 2407 } else if (type.IsString()) { |
| 2395 ASSERT(!info()->IsStub()); | 2408 ASSERT(!info()->IsStub()); |
| 2396 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | 2409 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
| 2397 EmitBranch(instr, not_equal); | 2410 EmitBranch(instr, not_equal); |
| 2398 } else { | 2411 } else { |
| 2399 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); | 2412 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
| 2400 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); | 2413 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); |
| 2401 | 2414 |
| 2402 if (expected.Contains(ToBooleanStub::UNDEFINED)) { | 2415 if (expected.Contains(ToBooleanStub::UNDEFINED)) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2467 } | 2480 } |
| 2468 | 2481 |
| 2469 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 2482 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
| 2470 // heap number -> false iff +0, -0, or NaN. | 2483 // heap number -> false iff +0, -0, or NaN. |
| 2471 Label not_heap_number; | 2484 Label not_heap_number; |
| 2472 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 2485 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 2473 factory()->heap_number_map()); | 2486 factory()->heap_number_map()); |
| 2474 __ j(not_equal, ¬_heap_number, Label::kNear); | 2487 __ j(not_equal, ¬_heap_number, Label::kNear); |
| 2475 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { | 2488 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 2476 CpuFeatureScope scope(masm(), SSE2); | 2489 CpuFeatureScope scope(masm(), SSE2); |
| 2477 __ xorps(xmm0, xmm0); | 2490 XMMRegister xmm_scratch = double_scratch0(); |
| 2478 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); | 2491 __ xorps(xmm_scratch, xmm_scratch); |
| 2492 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); |
| 2479 } else { | 2493 } else { |
| 2480 __ fldz(); | 2494 __ fldz(); |
| 2481 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); | 2495 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); |
| 2482 __ FCmp(); | 2496 __ FCmp(); |
| 2483 } | 2497 } |
| 2484 __ j(zero, instr->FalseLabel(chunk_)); | 2498 __ j(zero, instr->FalseLabel(chunk_)); |
| 2485 __ jmp(instr->TrueLabel(chunk_)); | 2499 __ jmp(instr->TrueLabel(chunk_)); |
| 2486 __ bind(¬_heap_number); | 2500 __ bind(¬_heap_number); |
| 2487 } | 2501 } |
| 2488 | 2502 |
| (...skipping 859 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3348 // Non-instance prototype: Fetch prototype from constructor field | 3362 // Non-instance prototype: Fetch prototype from constructor field |
| 3349 // in the function's map. | 3363 // in the function's map. |
| 3350 __ bind(&non_instance); | 3364 __ bind(&non_instance); |
| 3351 __ mov(result, FieldOperand(result, Map::kConstructorOffset)); | 3365 __ mov(result, FieldOperand(result, Map::kConstructorOffset)); |
| 3352 | 3366 |
| 3353 // All done. | 3367 // All done. |
| 3354 __ bind(&done); | 3368 __ bind(&done); |
| 3355 } | 3369 } |
| 3356 | 3370 |
| 3357 | 3371 |
| 3372 void LCodeGen::DoLoadRoot(LLoadRoot* instr) { |
| 3373 Register result = ToRegister(instr->result()); |
| 3374 __ LoadRoot(result, instr->index()); |
| 3375 } |
| 3376 |
| 3377 |
| 3358 void LCodeGen::DoLoadExternalArrayPointer( | 3378 void LCodeGen::DoLoadExternalArrayPointer( |
| 3359 LLoadExternalArrayPointer* instr) { | 3379 LLoadExternalArrayPointer* instr) { |
| 3360 Register result = ToRegister(instr->result()); | 3380 Register result = ToRegister(instr->result()); |
| 3361 Register input = ToRegister(instr->object()); | 3381 Register input = ToRegister(instr->object()); |
| 3362 __ mov(result, FieldOperand(input, | 3382 __ mov(result, FieldOperand(input, |
| 3363 ExternalArray::kExternalPointerOffset)); | 3383 ExternalArray::kExternalPointerOffset)); |
| 3364 } | 3384 } |
| 3365 | 3385 |
| 3366 | 3386 |
| 3367 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 3387 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
| (...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3902 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 3922 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 3903 private: | 3923 private: |
| 3904 LMathAbs* instr_; | 3924 LMathAbs* instr_; |
| 3905 }; | 3925 }; |
| 3906 | 3926 |
| 3907 ASSERT(instr->value()->Equals(instr->result())); | 3927 ASSERT(instr->value()->Equals(instr->result())); |
| 3908 Representation r = instr->hydrogen()->value()->representation(); | 3928 Representation r = instr->hydrogen()->value()->representation(); |
| 3909 | 3929 |
| 3910 CpuFeatureScope scope(masm(), SSE2); | 3930 CpuFeatureScope scope(masm(), SSE2); |
| 3911 if (r.IsDouble()) { | 3931 if (r.IsDouble()) { |
| 3912 XMMRegister scratch = xmm0; | 3932 XMMRegister scratch = double_scratch0(); |
| 3913 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3933 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3914 __ xorps(scratch, scratch); | 3934 __ xorps(scratch, scratch); |
| 3915 __ subsd(scratch, input_reg); | 3935 __ subsd(scratch, input_reg); |
| 3916 __ pand(input_reg, scratch); | 3936 __ pand(input_reg, scratch); |
| 3917 } else if (r.IsSmiOrInteger32()) { | 3937 } else if (r.IsSmiOrInteger32()) { |
| 3918 EmitIntegerMathAbs(instr); | 3938 EmitIntegerMathAbs(instr); |
| 3919 } else { // Tagged case. | 3939 } else { // Tagged case. |
| 3920 DeferredMathAbsTaggedHeapNumber* deferred = | 3940 DeferredMathAbsTaggedHeapNumber* deferred = |
| 3921 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr, x87_stack_); | 3941 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr, x87_stack_); |
| 3922 Register input_reg = ToRegister(instr->value()); | 3942 Register input_reg = ToRegister(instr->value()); |
| 3923 // Smi check. | 3943 // Smi check. |
| 3924 __ JumpIfNotSmi(input_reg, deferred->entry()); | 3944 __ JumpIfNotSmi(input_reg, deferred->entry()); |
| 3925 EmitIntegerMathAbs(instr); | 3945 EmitIntegerMathAbs(instr); |
| 3926 __ bind(deferred->exit()); | 3946 __ bind(deferred->exit()); |
| 3927 } | 3947 } |
| 3928 } | 3948 } |
| 3929 | 3949 |
| 3930 | 3950 |
| 3931 void LCodeGen::DoMathFloor(LMathFloor* instr) { | 3951 void LCodeGen::DoMathFloor(LMathFloor* instr) { |
| 3932 CpuFeatureScope scope(masm(), SSE2); | 3952 CpuFeatureScope scope(masm(), SSE2); |
| 3933 XMMRegister xmm_scratch = xmm0; | 3953 XMMRegister xmm_scratch = double_scratch0(); |
| 3934 Register output_reg = ToRegister(instr->result()); | 3954 Register output_reg = ToRegister(instr->result()); |
| 3935 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3955 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3936 | 3956 |
| 3937 if (CpuFeatures::IsSupported(SSE4_1)) { | 3957 if (CpuFeatures::IsSupported(SSE4_1)) { |
| 3938 CpuFeatureScope scope(masm(), SSE4_1); | 3958 CpuFeatureScope scope(masm(), SSE4_1); |
| 3939 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3959 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3940 // Deoptimize on negative zero. | 3960 // Deoptimize on negative zero. |
| 3941 Label non_zero; | 3961 Label non_zero; |
| 3942 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. | 3962 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. |
| 3943 __ ucomisd(input_reg, xmm_scratch); | 3963 __ ucomisd(input_reg, xmm_scratch); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3991 | 4011 |
| 3992 __ bind(&done); | 4012 __ bind(&done); |
| 3993 } | 4013 } |
| 3994 } | 4014 } |
| 3995 | 4015 |
| 3996 | 4016 |
| 3997 void LCodeGen::DoMathRound(LMathRound* instr) { | 4017 void LCodeGen::DoMathRound(LMathRound* instr) { |
| 3998 CpuFeatureScope scope(masm(), SSE2); | 4018 CpuFeatureScope scope(masm(), SSE2); |
| 3999 Register output_reg = ToRegister(instr->result()); | 4019 Register output_reg = ToRegister(instr->result()); |
| 4000 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 4020 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 4001 XMMRegister xmm_scratch = xmm0; | 4021 XMMRegister xmm_scratch = double_scratch0(); |
| 4002 XMMRegister input_temp = ToDoubleRegister(instr->temp()); | 4022 XMMRegister input_temp = ToDoubleRegister(instr->temp()); |
| 4003 ExternalReference one_half = ExternalReference::address_of_one_half(); | 4023 ExternalReference one_half = ExternalReference::address_of_one_half(); |
| 4004 ExternalReference minus_one_half = | 4024 ExternalReference minus_one_half = |
| 4005 ExternalReference::address_of_minus_one_half(); | 4025 ExternalReference::address_of_minus_one_half(); |
| 4006 | 4026 |
| 4007 Label done, round_to_zero, below_one_half, do_not_compensate; | 4027 Label done, round_to_zero, below_one_half, do_not_compensate; |
| 4008 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half)); | 4028 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half)); |
| 4009 __ ucomisd(xmm_scratch, input_reg); | 4029 __ ucomisd(xmm_scratch, input_reg); |
| 4010 __ j(above, &below_one_half); | 4030 __ j(above, &below_one_half); |
| 4011 | 4031 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4058 void LCodeGen::DoMathSqrt(LMathSqrt* instr) { | 4078 void LCodeGen::DoMathSqrt(LMathSqrt* instr) { |
| 4059 CpuFeatureScope scope(masm(), SSE2); | 4079 CpuFeatureScope scope(masm(), SSE2); |
| 4060 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 4080 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 4061 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 4081 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
| 4062 __ sqrtsd(input_reg, input_reg); | 4082 __ sqrtsd(input_reg, input_reg); |
| 4063 } | 4083 } |
| 4064 | 4084 |
| 4065 | 4085 |
| 4066 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { | 4086 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { |
| 4067 CpuFeatureScope scope(masm(), SSE2); | 4087 CpuFeatureScope scope(masm(), SSE2); |
| 4068 XMMRegister xmm_scratch = xmm0; | 4088 XMMRegister xmm_scratch = double_scratch0(); |
| 4069 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 4089 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 4070 Register scratch = ToRegister(instr->temp()); | 4090 Register scratch = ToRegister(instr->temp()); |
| 4071 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 4091 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
| 4072 | 4092 |
| 4073 // Note that according to ECMA-262 15.8.2.13: | 4093 // Note that according to ECMA-262 15.8.2.13: |
| 4074 // Math.pow(-Infinity, 0.5) == Infinity | 4094 // Math.pow(-Infinity, 0.5) == Infinity |
| 4075 // Math.sqrt(-Infinity) == NaN | 4095 // Math.sqrt(-Infinity) == NaN |
| 4076 Label done, sqrt; | 4096 Label done, sqrt; |
| 4077 // Check base for -Infinity. According to IEEE-754, single-precision | 4097 // Check base for -Infinity. According to IEEE-754, single-precision |
| 4078 // -Infinity has the highest 9 bits set and the lowest 23 bits cleared. | 4098 // -Infinity has the highest 9 bits set and the lowest 23 bits cleared. |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4177 // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF) | 4197 // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF) |
| 4178 Register random = state0; | 4198 Register random = state0; |
| 4179 __ shl(random, 14); | 4199 __ shl(random, 14); |
| 4180 __ and_(state1, Immediate(0x3FFFF)); | 4200 __ and_(state1, Immediate(0x3FFFF)); |
| 4181 __ add(random, state1); | 4201 __ add(random, state1); |
| 4182 | 4202 |
| 4183 // Convert 32 random bits in random to 0.(32 random bits) in a double | 4203 // Convert 32 random bits in random to 0.(32 random bits) in a double |
| 4184 // by computing: | 4204 // by computing: |
| 4185 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). | 4205 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). |
| 4186 XMMRegister result = ToDoubleRegister(instr->result()); | 4206 XMMRegister result = ToDoubleRegister(instr->result()); |
| 4187 // We use xmm0 as fixed scratch register here. | 4207 XMMRegister scratch4 = double_scratch0(); |
| 4188 XMMRegister scratch4 = xmm0; | |
| 4189 __ mov(scratch3, Immediate(0x49800000)); // 1.0 x 2^20 as single. | 4208 __ mov(scratch3, Immediate(0x49800000)); // 1.0 x 2^20 as single. |
| 4190 __ movd(scratch4, scratch3); | 4209 __ movd(scratch4, scratch3); |
| 4191 __ movd(result, random); | 4210 __ movd(result, random); |
| 4192 __ cvtss2sd(scratch4, scratch4); | 4211 __ cvtss2sd(scratch4, scratch4); |
| 4193 __ xorps(result, scratch4); | 4212 __ xorps(result, scratch4); |
| 4194 __ subsd(result, scratch4); | 4213 __ subsd(result, scratch4); |
| 4195 } | 4214 } |
| 4196 | 4215 |
| 4197 | 4216 |
| 4198 void LCodeGen::DoMathLog(LMathLog* instr) { | 4217 void LCodeGen::DoMathLog(LMathLog* instr) { |
| 4199 CpuFeatureScope scope(masm(), SSE2); | 4218 CpuFeatureScope scope(masm(), SSE2); |
| 4200 ASSERT(instr->value()->Equals(instr->result())); | 4219 ASSERT(instr->value()->Equals(instr->result())); |
| 4201 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 4220 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 4221 XMMRegister xmm_scratch = double_scratch0(); |
| 4202 Label positive, done, zero; | 4222 Label positive, done, zero; |
| 4203 __ xorps(xmm0, xmm0); | 4223 __ xorps(xmm_scratch, xmm_scratch); |
| 4204 __ ucomisd(input_reg, xmm0); | 4224 __ ucomisd(input_reg, xmm_scratch); |
| 4205 __ j(above, &positive, Label::kNear); | 4225 __ j(above, &positive, Label::kNear); |
| 4206 __ j(equal, &zero, Label::kNear); | 4226 __ j(equal, &zero, Label::kNear); |
| 4207 ExternalReference nan = | 4227 ExternalReference nan = |
| 4208 ExternalReference::address_of_canonical_non_hole_nan(); | 4228 ExternalReference::address_of_canonical_non_hole_nan(); |
| 4209 __ movdbl(input_reg, Operand::StaticVariable(nan)); | 4229 __ movdbl(input_reg, Operand::StaticVariable(nan)); |
| 4210 __ jmp(&done, Label::kNear); | 4230 __ jmp(&done, Label::kNear); |
| 4211 __ bind(&zero); | 4231 __ bind(&zero); |
| 4212 __ push(Immediate(0xFFF00000)); | 4232 __ push(Immediate(0xFFF00000)); |
| 4213 __ push(Immediate(0)); | 4233 __ push(Immediate(0)); |
| 4214 __ movdbl(input_reg, Operand(esp, 0)); | 4234 __ movdbl(input_reg, Operand(esp, 0)); |
| 4215 __ add(Operand(esp), Immediate(kDoubleSize)); | 4235 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 4216 __ jmp(&done, Label::kNear); | 4236 __ jmp(&done, Label::kNear); |
| 4217 __ bind(&positive); | 4237 __ bind(&positive); |
| 4218 __ fldln2(); | 4238 __ fldln2(); |
| 4219 __ sub(Operand(esp), Immediate(kDoubleSize)); | 4239 __ sub(Operand(esp), Immediate(kDoubleSize)); |
| 4220 __ movdbl(Operand(esp, 0), input_reg); | 4240 __ movdbl(Operand(esp, 0), input_reg); |
| 4221 __ fld_d(Operand(esp, 0)); | 4241 __ fld_d(Operand(esp, 0)); |
| 4222 __ fyl2x(); | 4242 __ fyl2x(); |
| 4223 __ fstp_d(Operand(esp, 0)); | 4243 __ fstp_d(Operand(esp, 0)); |
| 4224 __ movdbl(input_reg, Operand(esp, 0)); | 4244 __ movdbl(input_reg, Operand(esp, 0)); |
| 4225 __ add(Operand(esp), Immediate(kDoubleSize)); | 4245 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 4226 __ bind(&done); | 4246 __ bind(&done); |
| 4227 } | 4247 } |
| 4228 | 4248 |
| 4229 | 4249 |
| 4230 void LCodeGen::DoMathExp(LMathExp* instr) { | 4250 void LCodeGen::DoMathExp(LMathExp* instr) { |
| 4231 CpuFeatureScope scope(masm(), SSE2); | 4251 CpuFeatureScope scope(masm(), SSE2); |
| 4232 XMMRegister input = ToDoubleRegister(instr->value()); | 4252 XMMRegister input = ToDoubleRegister(instr->value()); |
| 4233 XMMRegister result = ToDoubleRegister(instr->result()); | 4253 XMMRegister result = ToDoubleRegister(instr->result()); |
| 4254 XMMRegister temp0 = double_scratch0(); |
| 4234 Register temp1 = ToRegister(instr->temp1()); | 4255 Register temp1 = ToRegister(instr->temp1()); |
| 4235 Register temp2 = ToRegister(instr->temp2()); | 4256 Register temp2 = ToRegister(instr->temp2()); |
| 4236 | 4257 |
| 4237 MathExpGenerator::EmitMathExp(masm(), input, result, xmm0, temp1, temp2); | 4258 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2); |
| 4238 } | 4259 } |
| 4239 | 4260 |
| 4240 | 4261 |
| 4241 void LCodeGen::DoMathTan(LMathTan* instr) { | 4262 void LCodeGen::DoMathTan(LMathTan* instr) { |
| 4242 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 4263 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| 4243 // Set the context register to a GC-safe fake value. Clobbering it is | 4264 // Set the context register to a GC-safe fake value. Clobbering it is |
| 4244 // OK because this instruction is marked as a call. | 4265 // OK because this instruction is marked as a call. |
| 4245 __ Set(esi, Immediate(0)); | 4266 __ Set(esi, Immediate(0)); |
| 4246 TranscendentalCacheStub stub(TranscendentalCache::TAN, | 4267 TranscendentalCacheStub stub(TranscendentalCache::TAN, |
| 4247 TranscendentalCacheStub::UNTAGGED); | 4268 TranscendentalCacheStub::UNTAGGED); |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4608 Operand operand(BuildFastArrayOperand( | 4629 Operand operand(BuildFastArrayOperand( |
| 4609 instr->elements(), | 4630 instr->elements(), |
| 4610 key, | 4631 key, |
| 4611 instr->hydrogen()->key()->representation(), | 4632 instr->hydrogen()->key()->representation(), |
| 4612 elements_kind, | 4633 elements_kind, |
| 4613 0, | 4634 0, |
| 4614 instr->additional_index())); | 4635 instr->additional_index())); |
| 4615 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | 4636 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
| 4616 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { | 4637 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 4617 CpuFeatureScope scope(masm(), SSE2); | 4638 CpuFeatureScope scope(masm(), SSE2); |
| 4618 __ cvtsd2ss(xmm0, ToDoubleRegister(instr->value())); | 4639 XMMRegister xmm_scratch = double_scratch0(); |
| 4619 __ movss(operand, xmm0); | 4640 __ cvtsd2ss(xmm_scratch, ToDoubleRegister(instr->value())); |
| 4641 __ movss(operand, xmm_scratch); |
| 4620 } else { | 4642 } else { |
| 4621 __ fld(0); | 4643 __ fld(0); |
| 4622 __ fstp_s(operand); | 4644 __ fstp_s(operand); |
| 4623 } | 4645 } |
| 4624 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | 4646 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
| 4625 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { | 4647 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 4626 CpuFeatureScope scope(masm(), SSE2); | 4648 CpuFeatureScope scope(masm(), SSE2); |
| 4627 __ movdbl(operand, ToDoubleRegister(instr->value())); | 4649 __ movdbl(operand, ToDoubleRegister(instr->value())); |
| 4628 } else { | 4650 } else { |
| 4629 X87Mov(operand, ToX87Register(instr->value())); | 4651 X87Mov(operand, ToX87Register(instr->value())); |
| (...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5072 __ bind(deferred->exit()); | 5094 __ bind(deferred->exit()); |
| 5073 } | 5095 } |
| 5074 | 5096 |
| 5075 | 5097 |
| 5076 void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, | 5098 void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, |
| 5077 LOperand* value, | 5099 LOperand* value, |
| 5078 IntegerSignedness signedness) { | 5100 IntegerSignedness signedness) { |
| 5079 Label slow; | 5101 Label slow; |
| 5080 Register reg = ToRegister(value); | 5102 Register reg = ToRegister(value); |
| 5081 Register tmp = reg.is(eax) ? ecx : eax; | 5103 Register tmp = reg.is(eax) ? ecx : eax; |
| 5104 XMMRegister xmm_scratch = double_scratch0(); |
| 5082 | 5105 |
| 5083 // Preserve the value of all registers. | 5106 // Preserve the value of all registers. |
| 5084 PushSafepointRegistersScope scope(this); | 5107 PushSafepointRegistersScope scope(this); |
| 5085 | 5108 |
| 5086 Label done; | 5109 Label done; |
| 5087 | 5110 |
| 5088 if (signedness == SIGNED_INT32) { | 5111 if (signedness == SIGNED_INT32) { |
| 5089 // There was overflow, so bits 30 and 31 of the original integer | 5112 // There was overflow, so bits 30 and 31 of the original integer |
| 5090 // disagree. Try to allocate a heap number in new space and store | 5113 // disagree. Try to allocate a heap number in new space and store |
| 5091 // the value in there. If that fails, call the runtime system. | 5114 // the value in there. If that fails, call the runtime system. |
| 5092 __ SmiUntag(reg); | 5115 __ SmiUntag(reg); |
| 5093 __ xor_(reg, 0x80000000); | 5116 __ xor_(reg, 0x80000000); |
| 5094 if (CpuFeatures::IsSupported(SSE2)) { | 5117 if (CpuFeatures::IsSupported(SSE2)) { |
| 5095 CpuFeatureScope feature_scope(masm(), SSE2); | 5118 CpuFeatureScope feature_scope(masm(), SSE2); |
| 5096 __ Cvtsi2sd(xmm0, Operand(reg)); | 5119 __ Cvtsi2sd(xmm_scratch, Operand(reg)); |
| 5097 } else { | 5120 } else { |
| 5098 __ push(reg); | 5121 __ push(reg); |
| 5099 __ fild_s(Operand(esp, 0)); | 5122 __ fild_s(Operand(esp, 0)); |
| 5100 __ pop(reg); | 5123 __ pop(reg); |
| 5101 } | 5124 } |
| 5102 } else { | 5125 } else { |
| 5103 if (CpuFeatures::IsSupported(SSE2)) { | 5126 if (CpuFeatures::IsSupported(SSE2)) { |
| 5104 CpuFeatureScope feature_scope(masm(), SSE2); | 5127 CpuFeatureScope feature_scope(masm(), SSE2); |
| 5105 __ LoadUint32(xmm0, reg, | 5128 __ LoadUint32(xmm_scratch, reg, |
| 5106 ToDoubleRegister(LNumberTagU::cast(instr)->temp())); | 5129 ToDoubleRegister(LNumberTagU::cast(instr)->temp())); |
| 5107 } else { | 5130 } else { |
| 5108 // There's no fild variant for unsigned values, so zero-extend to a 64-bit | 5131 // There's no fild variant for unsigned values, so zero-extend to a 64-bit |
| 5109 // int manually. | 5132 // int manually. |
| 5110 __ push(Immediate(0)); | 5133 __ push(Immediate(0)); |
| 5111 __ push(reg); | 5134 __ push(reg); |
| 5112 __ fild_d(Operand(esp, 0)); | 5135 __ fild_d(Operand(esp, 0)); |
| 5113 __ pop(reg); | 5136 __ pop(reg); |
| 5114 __ pop(reg); | 5137 __ pop(reg); |
| 5115 } | 5138 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 5131 // the environment's HContext or HInlinedContext value. | 5154 // the environment's HContext or HInlinedContext value. |
| 5132 // They only call Runtime::kAllocateHeapNumber. | 5155 // They only call Runtime::kAllocateHeapNumber. |
| 5133 // The corresponding HChange instructions are added in a phase that does | 5156 // The corresponding HChange instructions are added in a phase that does |
| 5134 // not have easy access to the local context. | 5157 // not have easy access to the local context. |
| 5135 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 5158 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 5136 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 5159 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| 5137 RecordSafepointWithRegisters( | 5160 RecordSafepointWithRegisters( |
| 5138 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 5161 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 5139 if (!reg.is(eax)) __ mov(reg, eax); | 5162 if (!reg.is(eax)) __ mov(reg, eax); |
| 5140 | 5163 |
| 5141 // Done. Put the value in xmm0 into the value of the allocated heap | 5164 // Done. Put the value in xmm_scratch into the value of the allocated heap |
| 5142 // number. | 5165 // number. |
| 5143 __ bind(&done); | 5166 __ bind(&done); |
| 5144 if (CpuFeatures::IsSupported(SSE2)) { | 5167 if (CpuFeatures::IsSupported(SSE2)) { |
| 5145 CpuFeatureScope feature_scope(masm(), SSE2); | 5168 CpuFeatureScope feature_scope(masm(), SSE2); |
| 5146 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm0); | 5169 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm_scratch); |
| 5147 } else { | 5170 } else { |
| 5148 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); | 5171 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); |
| 5149 } | 5172 } |
| 5150 __ StoreToSafepointRegisterSlot(reg, reg); | 5173 __ StoreToSafepointRegisterSlot(reg, reg); |
| 5151 } | 5174 } |
| 5152 | 5175 |
| 5153 | 5176 |
| 5154 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 5177 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
| 5155 class DeferredNumberTagD V8_FINAL : public LDeferredCode { | 5178 class DeferredNumberTagD V8_FINAL : public LDeferredCode { |
| 5156 public: | 5179 public: |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5326 if (can_convert_undefined_to_nan) { | 5349 if (can_convert_undefined_to_nan) { |
| 5327 __ j(not_equal, &convert, Label::kNear); | 5350 __ j(not_equal, &convert, Label::kNear); |
| 5328 } else { | 5351 } else { |
| 5329 DeoptimizeIf(not_equal, env); | 5352 DeoptimizeIf(not_equal, env); |
| 5330 } | 5353 } |
| 5331 | 5354 |
| 5332 // Heap number to XMM conversion. | 5355 // Heap number to XMM conversion. |
| 5333 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 5356 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 5334 | 5357 |
| 5335 if (deoptimize_on_minus_zero) { | 5358 if (deoptimize_on_minus_zero) { |
| 5336 XMMRegister xmm_scratch = xmm0; | 5359 XMMRegister xmm_scratch = double_scratch0(); |
| 5337 __ xorps(xmm_scratch, xmm_scratch); | 5360 __ xorps(xmm_scratch, xmm_scratch); |
| 5338 __ ucomisd(result_reg, xmm_scratch); | 5361 __ ucomisd(result_reg, xmm_scratch); |
| 5339 __ j(not_zero, &done, Label::kNear); | 5362 __ j(not_zero, &done, Label::kNear); |
| 5340 __ movmskpd(temp_reg, result_reg); | 5363 __ movmskpd(temp_reg, result_reg); |
| 5341 __ test_b(temp_reg, 1); | 5364 __ test_b(temp_reg, 1); |
| 5342 DeoptimizeIf(not_zero, env); | 5365 DeoptimizeIf(not_zero, env); |
| 5343 } | 5366 } |
| 5344 __ jmp(&done, Label::kNear); | 5367 __ jmp(&done, Label::kNear); |
| 5345 | 5368 |
| 5346 if (can_convert_undefined_to_nan) { | 5369 if (can_convert_undefined_to_nan) { |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5492 } else { | 5515 } else { |
| 5493 X87Register input_reg = ToX87Register(input); | 5516 X87Register input_reg = ToX87Register(input); |
| 5494 X87Fxch(input_reg); | 5517 X87Fxch(input_reg); |
| 5495 __ TruncateX87TOSToI(result_reg); | 5518 __ TruncateX87TOSToI(result_reg); |
| 5496 } | 5519 } |
| 5497 } else { | 5520 } else { |
| 5498 Label bailout, done; | 5521 Label bailout, done; |
| 5499 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { | 5522 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 5500 CpuFeatureScope scope(masm(), SSE2); | 5523 CpuFeatureScope scope(masm(), SSE2); |
| 5501 XMMRegister input_reg = ToDoubleRegister(input); | 5524 XMMRegister input_reg = ToDoubleRegister(input); |
| 5502 __ DoubleToI(result_reg, input_reg, xmm0, | 5525 XMMRegister xmm_scratch = double_scratch0(); |
| 5526 __ DoubleToI(result_reg, input_reg, xmm_scratch, |
| 5503 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); | 5527 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); |
| 5504 } else { | 5528 } else { |
| 5505 X87Register input_reg = ToX87Register(input); | 5529 X87Register input_reg = ToX87Register(input); |
| 5506 X87Fxch(input_reg); | 5530 X87Fxch(input_reg); |
| 5507 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), | 5531 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), |
| 5508 &bailout, Label::kNear); | 5532 &bailout, Label::kNear); |
| 5509 } | 5533 } |
| 5510 __ jmp(&done, Label::kNear); | 5534 __ jmp(&done, Label::kNear); |
| 5511 __ bind(&bailout); | 5535 __ bind(&bailout); |
| 5512 DeoptimizeIf(no_condition, instr->environment()); | 5536 DeoptimizeIf(no_condition, instr->environment()); |
| 5513 __ bind(&done); | 5537 __ bind(&done); |
| 5514 } | 5538 } |
| 5515 } | 5539 } |
| 5516 | 5540 |
| 5517 | 5541 |
| 5518 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { | 5542 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { |
| 5519 LOperand* input = instr->value(); | 5543 LOperand* input = instr->value(); |
| 5520 ASSERT(input->IsDoubleRegister()); | 5544 ASSERT(input->IsDoubleRegister()); |
| 5521 LOperand* result = instr->result(); | 5545 LOperand* result = instr->result(); |
| 5522 ASSERT(result->IsRegister()); | 5546 ASSERT(result->IsRegister()); |
| 5523 Register result_reg = ToRegister(result); | 5547 Register result_reg = ToRegister(result); |
| 5524 | 5548 |
| 5525 Label bailout, done; | 5549 Label bailout, done; |
| 5526 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { | 5550 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 5527 CpuFeatureScope scope(masm(), SSE2); | 5551 CpuFeatureScope scope(masm(), SSE2); |
| 5528 XMMRegister input_reg = ToDoubleRegister(input); | 5552 XMMRegister input_reg = ToDoubleRegister(input); |
| 5529 __ DoubleToI(result_reg, input_reg, xmm0, | 5553 XMMRegister xmm_scratch = double_scratch0(); |
| 5554 __ DoubleToI(result_reg, input_reg, xmm_scratch, |
| 5530 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); | 5555 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); |
| 5531 } else { | 5556 } else { |
| 5532 X87Register input_reg = ToX87Register(input); | 5557 X87Register input_reg = ToX87Register(input); |
| 5533 X87Fxch(input_reg); | 5558 X87Fxch(input_reg); |
| 5534 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), | 5559 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), |
| 5535 &bailout, Label::kNear); | 5560 &bailout, Label::kNear); |
| 5536 } | 5561 } |
| 5537 __ jmp(&done, Label::kNear); | 5562 __ jmp(&done, Label::kNear); |
| 5538 __ bind(&bailout); | 5563 __ bind(&bailout); |
| 5539 DeoptimizeIf(no_condition, instr->environment()); | 5564 DeoptimizeIf(no_condition, instr->environment()); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5599 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); | 5624 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); |
| 5600 __ and_(temp, mask); | 5625 __ and_(temp, mask); |
| 5601 __ cmp(temp, tag); | 5626 __ cmp(temp, tag); |
| 5602 DeoptimizeIf(not_equal, instr->environment()); | 5627 DeoptimizeIf(not_equal, instr->environment()); |
| 5603 } | 5628 } |
| 5604 } | 5629 } |
| 5605 } | 5630 } |
| 5606 | 5631 |
| 5607 | 5632 |
| 5608 void LCodeGen::DoCheckValue(LCheckValue* instr) { | 5633 void LCodeGen::DoCheckValue(LCheckValue* instr) { |
| 5609 Handle<HeapObject> object = instr->hydrogen()->object(); | 5634 Handle<HeapObject> object = instr->hydrogen()->object().handle(); |
| 5610 if (instr->hydrogen()->object_in_new_space()) { | 5635 if (instr->hydrogen()->object_in_new_space()) { |
| 5611 Register reg = ToRegister(instr->value()); | 5636 Register reg = ToRegister(instr->value()); |
| 5612 Handle<Cell> cell = isolate()->factory()->NewCell(object); | 5637 Handle<Cell> cell = isolate()->factory()->NewCell(object); |
| 5613 __ cmp(reg, Operand::ForCell(cell)); | 5638 __ cmp(reg, Operand::ForCell(cell)); |
| 5614 } else { | 5639 } else { |
| 5615 Operand operand = ToOperand(instr->value()); | 5640 Operand operand = ToOperand(instr->value()); |
| 5616 __ cmp(operand, object); | 5641 __ cmp(operand, object); |
| 5617 } | 5642 } |
| 5618 DeoptimizeIf(not_equal, instr->environment()); | 5643 DeoptimizeIf(not_equal, instr->environment()); |
| 5619 } | 5644 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5654 Label check_maps_; | 5679 Label check_maps_; |
| 5655 Register object_; | 5680 Register object_; |
| 5656 }; | 5681 }; |
| 5657 | 5682 |
| 5658 if (instr->hydrogen()->CanOmitMapChecks()) return; | 5683 if (instr->hydrogen()->CanOmitMapChecks()) return; |
| 5659 | 5684 |
| 5660 LOperand* input = instr->value(); | 5685 LOperand* input = instr->value(); |
| 5661 ASSERT(input->IsRegister()); | 5686 ASSERT(input->IsRegister()); |
| 5662 Register reg = ToRegister(input); | 5687 Register reg = ToRegister(input); |
| 5663 | 5688 |
| 5664 SmallMapList* map_set = instr->hydrogen()->map_set(); | |
| 5665 | |
| 5666 DeferredCheckMaps* deferred = NULL; | 5689 DeferredCheckMaps* deferred = NULL; |
| 5667 if (instr->hydrogen()->has_migration_target()) { | 5690 if (instr->hydrogen()->has_migration_target()) { |
| 5668 deferred = new(zone()) DeferredCheckMaps(this, instr, reg, x87_stack_); | 5691 deferred = new(zone()) DeferredCheckMaps(this, instr, reg, x87_stack_); |
| 5669 __ bind(deferred->check_maps()); | 5692 __ bind(deferred->check_maps()); |
| 5670 } | 5693 } |
| 5671 | 5694 |
| 5695 UniqueSet<Map> map_set = instr->hydrogen()->map_set(); |
| 5672 Label success; | 5696 Label success; |
| 5673 for (int i = 0; i < map_set->length() - 1; i++) { | 5697 for (int i = 0; i < map_set.size() - 1; i++) { |
| 5674 Handle<Map> map = map_set->at(i); | 5698 Handle<Map> map = map_set.at(i).handle(); |
| 5675 __ CompareMap(reg, map, &success); | 5699 __ CompareMap(reg, map, &success); |
| 5676 __ j(equal, &success); | 5700 __ j(equal, &success); |
| 5677 } | 5701 } |
| 5678 | 5702 |
| 5679 Handle<Map> map = map_set->last(); | 5703 Handle<Map> map = map_set.at(map_set.size() - 1).handle(); |
| 5680 __ CompareMap(reg, map, &success); | 5704 __ CompareMap(reg, map, &success); |
| 5681 if (instr->hydrogen()->has_migration_target()) { | 5705 if (instr->hydrogen()->has_migration_target()) { |
| 5682 __ j(not_equal, deferred->entry()); | 5706 __ j(not_equal, deferred->entry()); |
| 5683 } else { | 5707 } else { |
| 5684 DeoptimizeIf(not_equal, instr->environment()); | 5708 DeoptimizeIf(not_equal, instr->environment()); |
| 5685 } | 5709 } |
| 5686 | 5710 |
| 5687 __ bind(&success); | 5711 __ bind(&success); |
| 5688 } | 5712 } |
| 5689 | 5713 |
| 5690 | 5714 |
| 5691 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 5715 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
| 5692 CpuFeatureScope scope(masm(), SSE2); | 5716 CpuFeatureScope scope(masm(), SSE2); |
| 5693 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); | 5717 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); |
| 5718 XMMRegister xmm_scratch = double_scratch0(); |
| 5694 Register result_reg = ToRegister(instr->result()); | 5719 Register result_reg = ToRegister(instr->result()); |
| 5695 __ ClampDoubleToUint8(value_reg, xmm0, result_reg); | 5720 __ ClampDoubleToUint8(value_reg, xmm_scratch, result_reg); |
| 5696 } | 5721 } |
| 5697 | 5722 |
| 5698 | 5723 |
| 5699 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { | 5724 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { |
| 5700 ASSERT(instr->unclamped()->Equals(instr->result())); | 5725 ASSERT(instr->unclamped()->Equals(instr->result())); |
| 5701 Register value_reg = ToRegister(instr->result()); | 5726 Register value_reg = ToRegister(instr->result()); |
| 5702 __ ClampUint8(value_reg); | 5727 __ ClampUint8(value_reg); |
| 5703 } | 5728 } |
| 5704 | 5729 |
| 5705 | 5730 |
| 5706 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { | 5731 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { |
| 5707 CpuFeatureScope scope(masm(), SSE2); | 5732 CpuFeatureScope scope(masm(), SSE2); |
| 5708 | 5733 |
| 5709 ASSERT(instr->unclamped()->Equals(instr->result())); | 5734 ASSERT(instr->unclamped()->Equals(instr->result())); |
| 5710 Register input_reg = ToRegister(instr->unclamped()); | 5735 Register input_reg = ToRegister(instr->unclamped()); |
| 5736 XMMRegister xmm_scratch = double_scratch0(); |
| 5711 Label is_smi, done, heap_number; | 5737 Label is_smi, done, heap_number; |
| 5712 | 5738 |
| 5713 __ JumpIfSmi(input_reg, &is_smi); | 5739 __ JumpIfSmi(input_reg, &is_smi); |
| 5714 | 5740 |
| 5715 // Check for heap number | 5741 // Check for heap number |
| 5716 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 5742 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 5717 factory()->heap_number_map()); | 5743 factory()->heap_number_map()); |
| 5718 __ j(equal, &heap_number, Label::kNear); | 5744 __ j(equal, &heap_number, Label::kNear); |
| 5719 | 5745 |
| 5720 // Check for undefined. Undefined is converted to zero for clamping | 5746 // Check for undefined. Undefined is converted to zero for clamping |
| 5721 // conversions. | 5747 // conversions. |
| 5722 __ cmp(input_reg, factory()->undefined_value()); | 5748 __ cmp(input_reg, factory()->undefined_value()); |
| 5723 DeoptimizeIf(not_equal, instr->environment()); | 5749 DeoptimizeIf(not_equal, instr->environment()); |
| 5724 __ mov(input_reg, 0); | 5750 __ mov(input_reg, 0); |
| 5725 __ jmp(&done, Label::kNear); | 5751 __ jmp(&done, Label::kNear); |
| 5726 | 5752 |
| 5727 // Heap number | 5753 // Heap number |
| 5728 __ bind(&heap_number); | 5754 __ bind(&heap_number); |
| 5729 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 5755 __ movdbl(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 5730 __ ClampDoubleToUint8(xmm0, xmm1, input_reg); | 5756 __ ClampDoubleToUint8(xmm_scratch, xmm1, input_reg); |
| 5731 __ jmp(&done, Label::kNear); | 5757 __ jmp(&done, Label::kNear); |
| 5732 | 5758 |
| 5733 // smi | 5759 // smi |
| 5734 __ bind(&is_smi); | 5760 __ bind(&is_smi); |
| 5735 __ SmiUntag(input_reg); | 5761 __ SmiUntag(input_reg); |
| 5736 __ ClampUint8(input_reg); | 5762 __ ClampUint8(input_reg); |
| 5737 __ bind(&done); | 5763 __ bind(&done); |
| 5738 } | 5764 } |
| 5739 | 5765 |
| 5740 | 5766 |
| (...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6369 FixedArray::kHeaderSize - kPointerSize)); | 6395 FixedArray::kHeaderSize - kPointerSize)); |
| 6370 __ bind(&done); | 6396 __ bind(&done); |
| 6371 } | 6397 } |
| 6372 | 6398 |
| 6373 | 6399 |
| 6374 #undef __ | 6400 #undef __ |
| 6375 | 6401 |
| 6376 } } // namespace v8::internal | 6402 } } // namespace v8::internal |
| 6377 | 6403 |
| 6378 #endif // V8_TARGET_ARCH_IA32 | 6404 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |