| 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 966 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 977 // are about to return. | 977 // are about to return. |
| 978 if (op == Token::SHR) { | 978 if (op == Token::SHR) { |
| 979 __ mov(Operand(esp, 1 * kPointerSize), left); | 979 __ mov(Operand(esp, 1 * kPointerSize), left); |
| 980 __ mov(Operand(esp, 2 * kPointerSize), Immediate(0)); | 980 __ mov(Operand(esp, 2 * kPointerSize), Immediate(0)); |
| 981 __ fild_d(Operand(esp, 1 * kPointerSize)); | 981 __ fild_d(Operand(esp, 1 * kPointerSize)); |
| 982 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 982 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 983 } else { | 983 } else { |
| 984 ASSERT_EQ(Token::SHL, op); | 984 ASSERT_EQ(Token::SHL, op); |
| 985 if (CpuFeatures::IsSupported(SSE2)) { | 985 if (CpuFeatures::IsSupported(SSE2)) { |
| 986 CpuFeatureScope use_sse2(masm, SSE2); | 986 CpuFeatureScope use_sse2(masm, SSE2); |
| 987 __ cvtsi2sd(xmm0, left); | 987 __ Cvtsi2sd(xmm0, left); |
| 988 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 988 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
| 989 } else { | 989 } else { |
| 990 __ mov(Operand(esp, 1 * kPointerSize), left); | 990 __ mov(Operand(esp, 1 * kPointerSize), left); |
| 991 __ fild_s(Operand(esp, 1 * kPointerSize)); | 991 __ fild_s(Operand(esp, 1 * kPointerSize)); |
| 992 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 992 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 993 } | 993 } |
| 994 } | 994 } |
| 995 __ ret(2 * kPointerSize); | 995 __ ret(2 * kPointerSize); |
| 996 break; | 996 break; |
| 997 } | 997 } |
| (...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1363 // Fall through! | 1363 // Fall through! |
| 1364 case NO_OVERWRITE: | 1364 case NO_OVERWRITE: |
| 1365 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); | 1365 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); |
| 1366 __ bind(&skip_allocation); | 1366 __ bind(&skip_allocation); |
| 1367 break; | 1367 break; |
| 1368 default: UNREACHABLE(); | 1368 default: UNREACHABLE(); |
| 1369 } | 1369 } |
| 1370 // Store the result in the HeapNumber and return. | 1370 // Store the result in the HeapNumber and return. |
| 1371 if (CpuFeatures::IsSupported(SSE2)) { | 1371 if (CpuFeatures::IsSupported(SSE2)) { |
| 1372 CpuFeatureScope use_sse2(masm, SSE2); | 1372 CpuFeatureScope use_sse2(masm, SSE2); |
| 1373 __ cvtsi2sd(xmm0, ebx); | 1373 __ Cvtsi2sd(xmm0, ebx); |
| 1374 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 1374 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
| 1375 } else { | 1375 } else { |
| 1376 __ mov(Operand(esp, 1 * kPointerSize), ebx); | 1376 __ mov(Operand(esp, 1 * kPointerSize), ebx); |
| 1377 __ fild_s(Operand(esp, 1 * kPointerSize)); | 1377 __ fild_s(Operand(esp, 1 * kPointerSize)); |
| 1378 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 1378 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 1379 } | 1379 } |
| 1380 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. | 1380 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. |
| 1381 } | 1381 } |
| 1382 | 1382 |
| 1383 __ bind(¬_floats); | 1383 __ bind(¬_floats); |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1587 // Fall through! | 1587 // Fall through! |
| 1588 case NO_OVERWRITE: | 1588 case NO_OVERWRITE: |
| 1589 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); | 1589 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); |
| 1590 __ bind(&skip_allocation); | 1590 __ bind(&skip_allocation); |
| 1591 break; | 1591 break; |
| 1592 default: UNREACHABLE(); | 1592 default: UNREACHABLE(); |
| 1593 } | 1593 } |
| 1594 // Store the result in the HeapNumber and return. | 1594 // Store the result in the HeapNumber and return. |
| 1595 if (CpuFeatures::IsSupported(SSE2)) { | 1595 if (CpuFeatures::IsSupported(SSE2)) { |
| 1596 CpuFeatureScope use_sse2(masm, SSE2); | 1596 CpuFeatureScope use_sse2(masm, SSE2); |
| 1597 __ cvtsi2sd(xmm0, ebx); | 1597 __ Cvtsi2sd(xmm0, ebx); |
| 1598 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 1598 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
| 1599 } else { | 1599 } else { |
| 1600 __ mov(Operand(esp, 1 * kPointerSize), ebx); | 1600 __ mov(Operand(esp, 1 * kPointerSize), ebx); |
| 1601 __ fild_s(Operand(esp, 1 * kPointerSize)); | 1601 __ fild_s(Operand(esp, 1 * kPointerSize)); |
| 1602 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 1602 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 1603 } | 1603 } |
| 1604 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. | 1604 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. |
| 1605 } | 1605 } |
| 1606 | 1606 |
| 1607 __ bind(¬_floats); | 1607 __ bind(¬_floats); |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1775 // Fall through! | 1775 // Fall through! |
| 1776 case NO_OVERWRITE: | 1776 case NO_OVERWRITE: |
| 1777 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); | 1777 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); |
| 1778 __ bind(&skip_allocation); | 1778 __ bind(&skip_allocation); |
| 1779 break; | 1779 break; |
| 1780 default: UNREACHABLE(); | 1780 default: UNREACHABLE(); |
| 1781 } | 1781 } |
| 1782 // Store the result in the HeapNumber and return. | 1782 // Store the result in the HeapNumber and return. |
| 1783 if (CpuFeatures::IsSupported(SSE2)) { | 1783 if (CpuFeatures::IsSupported(SSE2)) { |
| 1784 CpuFeatureScope use_sse2(masm, SSE2); | 1784 CpuFeatureScope use_sse2(masm, SSE2); |
| 1785 __ cvtsi2sd(xmm0, ebx); | 1785 __ Cvtsi2sd(xmm0, ebx); |
| 1786 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 1786 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
| 1787 } else { | 1787 } else { |
| 1788 __ mov(Operand(esp, 1 * kPointerSize), ebx); | 1788 __ mov(Operand(esp, 1 * kPointerSize), ebx); |
| 1789 __ fild_s(Operand(esp, 1 * kPointerSize)); | 1789 __ fild_s(Operand(esp, 1 * kPointerSize)); |
| 1790 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 1790 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 1791 } | 1791 } |
| 1792 __ ret(2 * kPointerSize); | 1792 __ ret(2 * kPointerSize); |
| 1793 } | 1793 } |
| 1794 break; | 1794 break; |
| 1795 } | 1795 } |
| (...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2322 __ j(not_equal, not_numbers); // Argument in edx is not a number. | 2322 __ j(not_equal, not_numbers); // Argument in edx is not a number. |
| 2323 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 2323 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
| 2324 __ bind(&load_eax); | 2324 __ bind(&load_eax); |
| 2325 // Load operand in eax into xmm1, or branch to not_numbers. | 2325 // Load operand in eax into xmm1, or branch to not_numbers. |
| 2326 __ JumpIfSmi(eax, &load_smi_eax, Label::kNear); | 2326 __ JumpIfSmi(eax, &load_smi_eax, Label::kNear); |
| 2327 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), factory->heap_number_map()); | 2327 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), factory->heap_number_map()); |
| 2328 __ j(equal, &load_float_eax, Label::kNear); | 2328 __ j(equal, &load_float_eax, Label::kNear); |
| 2329 __ jmp(not_numbers); // Argument in eax is not a number. | 2329 __ jmp(not_numbers); // Argument in eax is not a number. |
| 2330 __ bind(&load_smi_edx); | 2330 __ bind(&load_smi_edx); |
| 2331 __ SmiUntag(edx); // Untag smi before converting to float. | 2331 __ SmiUntag(edx); // Untag smi before converting to float. |
| 2332 __ cvtsi2sd(xmm0, edx); | 2332 __ Cvtsi2sd(xmm0, edx); |
| 2333 __ SmiTag(edx); // Retag smi for heap number overwriting test. | 2333 __ SmiTag(edx); // Retag smi for heap number overwriting test. |
| 2334 __ jmp(&load_eax); | 2334 __ jmp(&load_eax); |
| 2335 __ bind(&load_smi_eax); | 2335 __ bind(&load_smi_eax); |
| 2336 __ SmiUntag(eax); // Untag smi before converting to float. | 2336 __ SmiUntag(eax); // Untag smi before converting to float. |
| 2337 __ cvtsi2sd(xmm1, eax); | 2337 __ Cvtsi2sd(xmm1, eax); |
| 2338 __ SmiTag(eax); // Retag smi for heap number overwriting test. | 2338 __ SmiTag(eax); // Retag smi for heap number overwriting test. |
| 2339 __ jmp(&done, Label::kNear); | 2339 __ jmp(&done, Label::kNear); |
| 2340 __ bind(&load_float_eax); | 2340 __ bind(&load_float_eax); |
| 2341 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 2341 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 2342 __ bind(&done); | 2342 __ bind(&done); |
| 2343 } | 2343 } |
| 2344 | 2344 |
| 2345 | 2345 |
| 2346 void FloatingPointHelper::LoadSSE2Smis(MacroAssembler* masm, | 2346 void FloatingPointHelper::LoadSSE2Smis(MacroAssembler* masm, |
| 2347 Register scratch) { | 2347 Register scratch) { |
| 2348 const Register left = edx; | 2348 const Register left = edx; |
| 2349 const Register right = eax; | 2349 const Register right = eax; |
| 2350 __ mov(scratch, left); | 2350 __ mov(scratch, left); |
| 2351 ASSERT(!scratch.is(right)); // We're about to clobber scratch. | 2351 ASSERT(!scratch.is(right)); // We're about to clobber scratch. |
| 2352 __ SmiUntag(scratch); | 2352 __ SmiUntag(scratch); |
| 2353 __ cvtsi2sd(xmm0, scratch); | 2353 __ Cvtsi2sd(xmm0, scratch); |
| 2354 | 2354 |
| 2355 __ mov(scratch, right); | 2355 __ mov(scratch, right); |
| 2356 __ SmiUntag(scratch); | 2356 __ SmiUntag(scratch); |
| 2357 __ cvtsi2sd(xmm1, scratch); | 2357 __ Cvtsi2sd(xmm1, scratch); |
| 2358 } | 2358 } |
| 2359 | 2359 |
| 2360 | 2360 |
| 2361 void FloatingPointHelper::CheckSSE2OperandIsInt32(MacroAssembler* masm, | 2361 void FloatingPointHelper::CheckSSE2OperandIsInt32(MacroAssembler* masm, |
| 2362 Label* non_int32, | 2362 Label* non_int32, |
| 2363 XMMRegister operand, | 2363 XMMRegister operand, |
| 2364 Register int32_result, | 2364 Register int32_result, |
| 2365 Register scratch, | 2365 Register scratch, |
| 2366 XMMRegister xmm_scratch) { | 2366 XMMRegister xmm_scratch) { |
| 2367 __ cvttsd2si(int32_result, Operand(operand)); | 2367 __ cvttsd2si(int32_result, Operand(operand)); |
| 2368 __ cvtsi2sd(xmm_scratch, int32_result); | 2368 __ Cvtsi2sd(xmm_scratch, int32_result); |
| 2369 __ pcmpeqd(xmm_scratch, operand); | 2369 __ pcmpeqd(xmm_scratch, operand); |
| 2370 __ movmskps(scratch, xmm_scratch); | 2370 __ movmskps(scratch, xmm_scratch); |
| 2371 // Two least significant bits should be both set. | 2371 // Two least significant bits should be both set. |
| 2372 __ not_(scratch); | 2372 __ not_(scratch); |
| 2373 __ test(scratch, Immediate(3)); | 2373 __ test(scratch, Immediate(3)); |
| 2374 __ j(not_zero, non_int32); | 2374 __ j(not_zero, non_int32); |
| 2375 } | 2375 } |
| 2376 | 2376 |
| 2377 | 2377 |
| 2378 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, | 2378 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2463 const Register scratch = ecx; | 2463 const Register scratch = ecx; |
| 2464 const XMMRegister double_result = xmm3; | 2464 const XMMRegister double_result = xmm3; |
| 2465 const XMMRegister double_base = xmm2; | 2465 const XMMRegister double_base = xmm2; |
| 2466 const XMMRegister double_exponent = xmm1; | 2466 const XMMRegister double_exponent = xmm1; |
| 2467 const XMMRegister double_scratch = xmm4; | 2467 const XMMRegister double_scratch = xmm4; |
| 2468 | 2468 |
| 2469 Label call_runtime, done, exponent_not_smi, int_exponent; | 2469 Label call_runtime, done, exponent_not_smi, int_exponent; |
| 2470 | 2470 |
| 2471 // Save 1 in double_result - we need this several times later on. | 2471 // Save 1 in double_result - we need this several times later on. |
| 2472 __ mov(scratch, Immediate(1)); | 2472 __ mov(scratch, Immediate(1)); |
| 2473 __ cvtsi2sd(double_result, scratch); | 2473 __ Cvtsi2sd(double_result, scratch); |
| 2474 | 2474 |
| 2475 if (exponent_type_ == ON_STACK) { | 2475 if (exponent_type_ == ON_STACK) { |
| 2476 Label base_is_smi, unpack_exponent; | 2476 Label base_is_smi, unpack_exponent; |
| 2477 // The exponent and base are supplied as arguments on the stack. | 2477 // The exponent and base are supplied as arguments on the stack. |
| 2478 // This can only happen if the stub is called from non-optimized code. | 2478 // This can only happen if the stub is called from non-optimized code. |
| 2479 // Load input parameters from stack. | 2479 // Load input parameters from stack. |
| 2480 __ mov(base, Operand(esp, 2 * kPointerSize)); | 2480 __ mov(base, Operand(esp, 2 * kPointerSize)); |
| 2481 __ mov(exponent, Operand(esp, 1 * kPointerSize)); | 2481 __ mov(exponent, Operand(esp, 1 * kPointerSize)); |
| 2482 | 2482 |
| 2483 __ JumpIfSmi(base, &base_is_smi, Label::kNear); | 2483 __ JumpIfSmi(base, &base_is_smi, Label::kNear); |
| 2484 __ cmp(FieldOperand(base, HeapObject::kMapOffset), | 2484 __ cmp(FieldOperand(base, HeapObject::kMapOffset), |
| 2485 factory->heap_number_map()); | 2485 factory->heap_number_map()); |
| 2486 __ j(not_equal, &call_runtime); | 2486 __ j(not_equal, &call_runtime); |
| 2487 | 2487 |
| 2488 __ movdbl(double_base, FieldOperand(base, HeapNumber::kValueOffset)); | 2488 __ movdbl(double_base, FieldOperand(base, HeapNumber::kValueOffset)); |
| 2489 __ jmp(&unpack_exponent, Label::kNear); | 2489 __ jmp(&unpack_exponent, Label::kNear); |
| 2490 | 2490 |
| 2491 __ bind(&base_is_smi); | 2491 __ bind(&base_is_smi); |
| 2492 __ SmiUntag(base); | 2492 __ SmiUntag(base); |
| 2493 __ cvtsi2sd(double_base, base); | 2493 __ Cvtsi2sd(double_base, base); |
| 2494 | 2494 |
| 2495 __ bind(&unpack_exponent); | 2495 __ bind(&unpack_exponent); |
| 2496 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); | 2496 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); |
| 2497 __ SmiUntag(exponent); | 2497 __ SmiUntag(exponent); |
| 2498 __ jmp(&int_exponent); | 2498 __ jmp(&int_exponent); |
| 2499 | 2499 |
| 2500 __ bind(&exponent_not_smi); | 2500 __ bind(&exponent_not_smi); |
| 2501 __ cmp(FieldOperand(exponent, HeapObject::kMapOffset), | 2501 __ cmp(FieldOperand(exponent, HeapObject::kMapOffset), |
| 2502 factory->heap_number_map()); | 2502 factory->heap_number_map()); |
| 2503 __ j(not_equal, &call_runtime); | 2503 __ j(not_equal, &call_runtime); |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2676 __ divsd(double_scratch2, double_result); | 2676 __ divsd(double_scratch2, double_result); |
| 2677 __ movsd(double_result, double_scratch2); | 2677 __ movsd(double_result, double_scratch2); |
| 2678 // Test whether result is zero. Bail out to check for subnormal result. | 2678 // Test whether result is zero. Bail out to check for subnormal result. |
| 2679 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. | 2679 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. |
| 2680 __ xorps(double_scratch2, double_scratch2); | 2680 __ xorps(double_scratch2, double_scratch2); |
| 2681 __ ucomisd(double_scratch2, double_result); // Result cannot be NaN. | 2681 __ ucomisd(double_scratch2, double_result); // Result cannot be NaN. |
| 2682 // double_exponent aliased as double_scratch2 has already been overwritten | 2682 // double_exponent aliased as double_scratch2 has already been overwritten |
| 2683 // and may not have contained the exponent value in the first place when the | 2683 // and may not have contained the exponent value in the first place when the |
| 2684 // exponent is a smi. We reset it with exponent value before bailing out. | 2684 // exponent is a smi. We reset it with exponent value before bailing out. |
| 2685 __ j(not_equal, &done); | 2685 __ j(not_equal, &done); |
| 2686 __ cvtsi2sd(double_exponent, exponent); | 2686 __ Cvtsi2sd(double_exponent, exponent); |
| 2687 | 2687 |
| 2688 // Returning or bailing out. | 2688 // Returning or bailing out. |
| 2689 Counters* counters = masm->isolate()->counters(); | 2689 Counters* counters = masm->isolate()->counters(); |
| 2690 if (exponent_type_ == ON_STACK) { | 2690 if (exponent_type_ == ON_STACK) { |
| 2691 // The arguments are still on the stack. | 2691 // The arguments are still on the stack. |
| 2692 __ bind(&call_runtime); | 2692 __ bind(&call_runtime); |
| 2693 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); | 2693 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); |
| 2694 | 2694 |
| 2695 // The stub is called from non-optimized code, which expects the result | 2695 // The stub is called from non-optimized code, which expects the result |
| 2696 // as heap number in exponent. | 2696 // as heap number in exponent. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2749 // -- edx : receiver | 2749 // -- edx : receiver |
| 2750 // -- esp[0] : return address | 2750 // -- esp[0] : return address |
| 2751 // ----------------------------------- | 2751 // ----------------------------------- |
| 2752 Label miss; | 2752 Label miss; |
| 2753 | 2753 |
| 2754 if (kind() == Code::KEYED_LOAD_IC) { | 2754 if (kind() == Code::KEYED_LOAD_IC) { |
| 2755 __ cmp(ecx, Immediate(masm->isolate()->factory()->length_string())); | 2755 __ cmp(ecx, Immediate(masm->isolate()->factory()->length_string())); |
| 2756 __ j(not_equal, &miss); | 2756 __ j(not_equal, &miss); |
| 2757 } | 2757 } |
| 2758 | 2758 |
| 2759 StubCompiler::GenerateLoadStringLength(masm, edx, eax, ebx, &miss, | 2759 StubCompiler::GenerateLoadStringLength(masm, edx, eax, ebx, &miss); |
| 2760 support_wrapper_); | |
| 2761 __ bind(&miss); | 2760 __ bind(&miss); |
| 2762 StubCompiler::TailCallBuiltin( | 2761 StubCompiler::TailCallBuiltin( |
| 2763 masm, BaseLoadStoreStubCompiler::MissBuiltin(kind())); | 2762 masm, BaseLoadStoreStubCompiler::MissBuiltin(kind())); |
| 2764 } | 2763 } |
| 2765 | 2764 |
| 2766 | 2765 |
| 2767 void StoreArrayLengthStub::Generate(MacroAssembler* masm) { | 2766 void StoreArrayLengthStub::Generate(MacroAssembler* masm) { |
| 2768 // ----------- S t a t e ------------- | 2767 // ----------- S t a t e ------------- |
| 2769 // -- eax : value | 2768 // -- eax : value |
| 2770 // -- ecx : name | 2769 // -- ecx : name |
| (...skipping 1730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4501 if (FLAG_debug_code) { | 4500 if (FLAG_debug_code) { |
| 4502 __ CheckStackAlignment(); | 4501 __ CheckStackAlignment(); |
| 4503 } | 4502 } |
| 4504 | 4503 |
| 4505 if (do_gc) { | 4504 if (do_gc) { |
| 4506 // Pass failure code returned from last attempt as first argument to | 4505 // Pass failure code returned from last attempt as first argument to |
| 4507 // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the | 4506 // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the |
| 4508 // stack alignment is known to be correct. This function takes one argument | 4507 // stack alignment is known to be correct. This function takes one argument |
| 4509 // which is passed on the stack, and we know that the stack has been | 4508 // which is passed on the stack, and we know that the stack has been |
| 4510 // prepared to pass at least one argument. | 4509 // prepared to pass at least one argument. |
| 4510 __ mov(Operand(esp, 1 * kPointerSize), |
| 4511 Immediate(ExternalReference::isolate_address(masm->isolate()))); |
| 4511 __ mov(Operand(esp, 0 * kPointerSize), eax); // Result. | 4512 __ mov(Operand(esp, 0 * kPointerSize), eax); // Result. |
| 4512 __ call(FUNCTION_ADDR(Runtime::PerformGC), RelocInfo::RUNTIME_ENTRY); | 4513 __ call(FUNCTION_ADDR(Runtime::PerformGC), RelocInfo::RUNTIME_ENTRY); |
| 4513 } | 4514 } |
| 4514 | 4515 |
| 4515 ExternalReference scope_depth = | 4516 ExternalReference scope_depth = |
| 4516 ExternalReference::heap_always_allocate_scope_depth(masm->isolate()); | 4517 ExternalReference::heap_always_allocate_scope_depth(masm->isolate()); |
| 4517 if (always_allocate_scope) { | 4518 if (always_allocate_scope) { |
| 4518 __ inc(Operand::StaticVariable(scope_depth)); | 4519 __ inc(Operand::StaticVariable(scope_depth)); |
| 4519 } | 4520 } |
| 4520 | 4521 |
| (...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5508 Register scratch2, | 5509 Register scratch2, |
| 5509 Register scratch3, | 5510 Register scratch3, |
| 5510 Label* slow) { | 5511 Label* slow) { |
| 5511 // First check if the argument is already a string. | 5512 // First check if the argument is already a string. |
| 5512 Label not_string, done; | 5513 Label not_string, done; |
| 5513 __ JumpIfSmi(arg, ¬_string); | 5514 __ JumpIfSmi(arg, ¬_string); |
| 5514 __ CmpObjectType(arg, FIRST_NONSTRING_TYPE, scratch1); | 5515 __ CmpObjectType(arg, FIRST_NONSTRING_TYPE, scratch1); |
| 5515 __ j(below, &done); | 5516 __ j(below, &done); |
| 5516 | 5517 |
| 5517 // Check the number to string cache. | 5518 // Check the number to string cache. |
| 5518 Label not_cached; | |
| 5519 __ bind(¬_string); | 5519 __ bind(¬_string); |
| 5520 // Puts the cached result into scratch1. | 5520 // Puts the cached result into scratch1. |
| 5521 NumberToStringStub::GenerateLookupNumberStringCache(masm, | 5521 NumberToStringStub::GenerateLookupNumberStringCache(masm, |
| 5522 arg, | 5522 arg, |
| 5523 scratch1, | 5523 scratch1, |
| 5524 scratch2, | 5524 scratch2, |
| 5525 scratch3, | 5525 scratch3, |
| 5526 ¬_cached); | 5526 slow); |
| 5527 __ mov(arg, scratch1); | 5527 __ mov(arg, scratch1); |
| 5528 __ mov(Operand(esp, stack_offset), arg); | 5528 __ mov(Operand(esp, stack_offset), arg); |
| 5529 __ jmp(&done); | |
| 5530 | |
| 5531 // Check if the argument is a safe string wrapper. | |
| 5532 __ bind(¬_cached); | |
| 5533 __ JumpIfSmi(arg, slow); | |
| 5534 __ CmpObjectType(arg, JS_VALUE_TYPE, scratch1); // map -> scratch1. | |
| 5535 __ j(not_equal, slow); | |
| 5536 __ test_b(FieldOperand(scratch1, Map::kBitField2Offset), | |
| 5537 1 << Map::kStringWrapperSafeForDefaultValueOf); | |
| 5538 __ j(zero, slow); | |
| 5539 __ mov(arg, FieldOperand(arg, JSValue::kValueOffset)); | |
| 5540 __ mov(Operand(esp, stack_offset), arg); | |
| 5541 | |
| 5542 __ bind(&done); | 5529 __ bind(&done); |
| 5543 } | 5530 } |
| 5544 | 5531 |
| 5545 | 5532 |
| 5546 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, | 5533 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, |
| 5547 Register dest, | 5534 Register dest, |
| 5548 Register src, | 5535 Register src, |
| 5549 Register count, | 5536 Register count, |
| 5550 Register scratch, | 5537 Register scratch, |
| 5551 bool ascii) { | 5538 bool ascii) { |
| (...skipping 713 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6265 Label done, left, left_smi, right_smi; | 6252 Label done, left, left_smi, right_smi; |
| 6266 __ JumpIfSmi(eax, &right_smi, Label::kNear); | 6253 __ JumpIfSmi(eax, &right_smi, Label::kNear); |
| 6267 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 6254 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
| 6268 masm->isolate()->factory()->heap_number_map()); | 6255 masm->isolate()->factory()->heap_number_map()); |
| 6269 __ j(not_equal, &maybe_undefined1, Label::kNear); | 6256 __ j(not_equal, &maybe_undefined1, Label::kNear); |
| 6270 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 6257 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 6271 __ jmp(&left, Label::kNear); | 6258 __ jmp(&left, Label::kNear); |
| 6272 __ bind(&right_smi); | 6259 __ bind(&right_smi); |
| 6273 __ mov(ecx, eax); // Can't clobber eax because we can still jump away. | 6260 __ mov(ecx, eax); // Can't clobber eax because we can still jump away. |
| 6274 __ SmiUntag(ecx); | 6261 __ SmiUntag(ecx); |
| 6275 __ cvtsi2sd(xmm1, ecx); | 6262 __ Cvtsi2sd(xmm1, ecx); |
| 6276 | 6263 |
| 6277 __ bind(&left); | 6264 __ bind(&left); |
| 6278 __ JumpIfSmi(edx, &left_smi, Label::kNear); | 6265 __ JumpIfSmi(edx, &left_smi, Label::kNear); |
| 6279 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 6266 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 6280 masm->isolate()->factory()->heap_number_map()); | 6267 masm->isolate()->factory()->heap_number_map()); |
| 6281 __ j(not_equal, &maybe_undefined2, Label::kNear); | 6268 __ j(not_equal, &maybe_undefined2, Label::kNear); |
| 6282 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 6269 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
| 6283 __ jmp(&done); | 6270 __ jmp(&done); |
| 6284 __ bind(&left_smi); | 6271 __ bind(&left_smi); |
| 6285 __ mov(ecx, edx); // Can't clobber edx because we can still jump away. | 6272 __ mov(ecx, edx); // Can't clobber edx because we can still jump away. |
| 6286 __ SmiUntag(ecx); | 6273 __ SmiUntag(ecx); |
| 6287 __ cvtsi2sd(xmm0, ecx); | 6274 __ Cvtsi2sd(xmm0, ecx); |
| 6288 | 6275 |
| 6289 __ bind(&done); | 6276 __ bind(&done); |
| 6290 // Compare operands. | 6277 // Compare operands. |
| 6291 __ ucomisd(xmm0, xmm1); | 6278 __ ucomisd(xmm0, xmm1); |
| 6292 | 6279 |
| 6293 // Don't base result on EFLAGS when a NaN is involved. | 6280 // Don't base result on EFLAGS when a NaN is involved. |
| 6294 __ j(parity_even, &unordered, Label::kNear); | 6281 __ j(parity_even, &unordered, Label::kNear); |
| 6295 | 6282 |
| 6296 // Return a result of -1, 0, or 1, based on EFLAGS. | 6283 // Return a result of -1, 0, or 1, based on EFLAGS. |
| 6297 // Performing mov, because xor would destroy the flag register. | 6284 // Performing mov, because xor would destroy the flag register. |
| (...skipping 934 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7232 // Restore ecx. | 7219 // Restore ecx. |
| 7233 __ pop(edx); | 7220 __ pop(edx); |
| 7234 __ pop(ecx); | 7221 __ pop(ecx); |
| 7235 __ pop(eax); | 7222 __ pop(eax); |
| 7236 | 7223 |
| 7237 __ ret(0); | 7224 __ ret(0); |
| 7238 } | 7225 } |
| 7239 | 7226 |
| 7240 | 7227 |
| 7241 template<class T> | 7228 template<class T> |
| 7242 static void CreateArrayDispatch(MacroAssembler* masm) { | 7229 static void CreateArrayDispatch(MacroAssembler* masm, |
| 7243 int last_index = GetSequenceIndexFromFastElementsKind( | 7230 AllocationSiteOverrideMode mode) { |
| 7244 TERMINAL_FAST_ELEMENTS_KIND); | 7231 if (mode == DISABLE_ALLOCATION_SITES) { |
| 7245 for (int i = 0; i <= last_index; ++i) { | 7232 T stub(GetInitialFastElementsKind(), |
| 7246 Label next; | 7233 CONTEXT_CHECK_REQUIRED, |
| 7247 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 7234 mode); |
| 7248 __ cmp(edx, kind); | |
| 7249 __ j(not_equal, &next); | |
| 7250 T stub(kind); | |
| 7251 __ TailCallStub(&stub); | 7235 __ TailCallStub(&stub); |
| 7252 __ bind(&next); | 7236 } else if (mode == DONT_OVERRIDE) { |
| 7237 int last_index = GetSequenceIndexFromFastElementsKind( |
| 7238 TERMINAL_FAST_ELEMENTS_KIND); |
| 7239 for (int i = 0; i <= last_index; ++i) { |
| 7240 Label next; |
| 7241 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 7242 __ cmp(edx, kind); |
| 7243 __ j(not_equal, &next); |
| 7244 T stub(kind); |
| 7245 __ TailCallStub(&stub); |
| 7246 __ bind(&next); |
| 7247 } |
| 7248 |
| 7249 // If we reached this point there is a problem. |
| 7250 __ Abort(kUnexpectedElementsKindInArrayConstructor); |
| 7251 } else { |
| 7252 UNREACHABLE(); |
| 7253 } | 7253 } |
| 7254 | |
| 7255 // If we reached this point there is a problem. | |
| 7256 __ Abort(kUnexpectedElementsKindInArrayConstructor); | |
| 7257 } | 7254 } |
| 7258 | 7255 |
| 7259 | 7256 |
| 7260 static void CreateArrayDispatchOneArgument(MacroAssembler* masm) { | 7257 static void CreateArrayDispatchOneArgument(MacroAssembler* masm, |
| 7261 // ebx - type info cell | 7258 AllocationSiteOverrideMode mode) { |
| 7262 // edx - kind | 7259 // ebx - type info cell (if mode != DISABLE_ALLOCATION_SITES) |
| 7260 // edx - kind (if mode != DISABLE_ALLOCATION_SITES) |
| 7263 // eax - number of arguments | 7261 // eax - number of arguments |
| 7264 // edi - constructor? | 7262 // edi - constructor? |
| 7265 // esp[0] - return address | 7263 // esp[0] - return address |
| 7266 // esp[4] - last argument | 7264 // esp[4] - last argument |
| 7267 ASSERT(FAST_SMI_ELEMENTS == 0); | 7265 Label normal_sequence; |
| 7268 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | 7266 if (mode == DONT_OVERRIDE) { |
| 7269 ASSERT(FAST_ELEMENTS == 2); | 7267 ASSERT(FAST_SMI_ELEMENTS == 0); |
| 7270 ASSERT(FAST_HOLEY_ELEMENTS == 3); | 7268 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); |
| 7271 ASSERT(FAST_DOUBLE_ELEMENTS == 4); | 7269 ASSERT(FAST_ELEMENTS == 2); |
| 7272 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); | 7270 ASSERT(FAST_HOLEY_ELEMENTS == 3); |
| 7271 ASSERT(FAST_DOUBLE_ELEMENTS == 4); |
| 7272 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); |
| 7273 | 7273 |
| 7274 Handle<Object> undefined_sentinel( | 7274 // is the low bit set? If so, we are holey and that is good. |
| 7275 masm->isolate()->heap()->undefined_value(), | 7275 __ test_b(edx, 1); |
| 7276 masm->isolate()); | 7276 __ j(not_zero, &normal_sequence); |
| 7277 | 7277 } |
| 7278 // is the low bit set? If so, we are holey and that is good. | |
| 7279 __ test_b(edx, 1); | |
| 7280 Label normal_sequence; | |
| 7281 __ j(not_zero, &normal_sequence); | |
| 7282 | 7278 |
| 7283 // look at the first argument | 7279 // look at the first argument |
| 7284 __ mov(ecx, Operand(esp, kPointerSize)); | 7280 __ mov(ecx, Operand(esp, kPointerSize)); |
| 7285 __ test(ecx, ecx); | 7281 __ test(ecx, ecx); |
| 7286 __ j(zero, &normal_sequence); | 7282 __ j(zero, &normal_sequence); |
| 7287 | 7283 |
| 7288 // We are going to create a holey array, but our kind is non-holey. | 7284 if (mode == DISABLE_ALLOCATION_SITES) { |
| 7289 // Fix kind and retry (only if we have an allocation site in the cell). | 7285 ElementsKind initial = GetInitialFastElementsKind(); |
| 7290 __ inc(edx); | 7286 ElementsKind holey_initial = GetHoleyElementsKind(initial); |
| 7291 __ cmp(ebx, Immediate(undefined_sentinel)); | |
| 7292 __ j(equal, &normal_sequence); | |
| 7293 __ mov(ecx, FieldOperand(ebx, Cell::kValueOffset)); | |
| 7294 Handle<Map> allocation_site_map( | |
| 7295 masm->isolate()->heap()->allocation_site_map(), | |
| 7296 masm->isolate()); | |
| 7297 __ cmp(FieldOperand(ecx, 0), Immediate(allocation_site_map)); | |
| 7298 __ j(not_equal, &normal_sequence); | |
| 7299 | 7287 |
| 7300 // Save the resulting elements kind in type info | 7288 ArraySingleArgumentConstructorStub stub_holey(holey_initial, |
| 7301 __ SmiTag(edx); | 7289 CONTEXT_CHECK_REQUIRED, |
| 7302 __ mov(FieldOperand(ecx, AllocationSite::kTransitionInfoOffset), edx); | 7290 DISABLE_ALLOCATION_SITES); |
| 7303 __ SmiUntag(edx); | 7291 __ TailCallStub(&stub_holey); |
| 7304 | 7292 |
| 7305 __ bind(&normal_sequence); | 7293 __ bind(&normal_sequence); |
| 7306 int last_index = GetSequenceIndexFromFastElementsKind( | 7294 ArraySingleArgumentConstructorStub stub(initial, |
| 7307 TERMINAL_FAST_ELEMENTS_KIND); | 7295 CONTEXT_CHECK_REQUIRED, |
| 7308 for (int i = 0; i <= last_index; ++i) { | 7296 DISABLE_ALLOCATION_SITES); |
| 7309 Label next; | |
| 7310 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | |
| 7311 __ cmp(edx, kind); | |
| 7312 __ j(not_equal, &next); | |
| 7313 ArraySingleArgumentConstructorStub stub(kind); | |
| 7314 __ TailCallStub(&stub); | 7297 __ TailCallStub(&stub); |
| 7315 __ bind(&next); | 7298 } else if (mode == DONT_OVERRIDE) { |
| 7299 // We are going to create a holey array, but our kind is non-holey. |
| 7300 // Fix kind and retry. |
| 7301 __ inc(edx); |
| 7302 __ mov(ecx, FieldOperand(ebx, Cell::kValueOffset)); |
| 7303 if (FLAG_debug_code) { |
| 7304 Handle<Map> allocation_site_map( |
| 7305 masm->isolate()->heap()->allocation_site_map(), |
| 7306 masm->isolate()); |
| 7307 __ cmp(FieldOperand(ecx, 0), Immediate(allocation_site_map)); |
| 7308 __ Assert(equal, kExpectedAllocationSiteInCell); |
| 7309 } |
| 7310 |
| 7311 // Save the resulting elements kind in type info |
| 7312 __ SmiTag(edx); |
| 7313 __ mov(FieldOperand(ecx, AllocationSite::kTransitionInfoOffset), edx); |
| 7314 __ SmiUntag(edx); |
| 7315 |
| 7316 __ bind(&normal_sequence); |
| 7317 int last_index = GetSequenceIndexFromFastElementsKind( |
| 7318 TERMINAL_FAST_ELEMENTS_KIND); |
| 7319 for (int i = 0; i <= last_index; ++i) { |
| 7320 Label next; |
| 7321 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 7322 __ cmp(edx, kind); |
| 7323 __ j(not_equal, &next); |
| 7324 ArraySingleArgumentConstructorStub stub(kind); |
| 7325 __ TailCallStub(&stub); |
| 7326 __ bind(&next); |
| 7327 } |
| 7328 |
| 7329 // If we reached this point there is a problem. |
| 7330 __ Abort(kUnexpectedElementsKindInArrayConstructor); |
| 7331 } else { |
| 7332 UNREACHABLE(); |
| 7316 } | 7333 } |
| 7317 | |
| 7318 // If we reached this point there is a problem. | |
| 7319 __ Abort(kUnexpectedElementsKindInArrayConstructor); | |
| 7320 } | 7334 } |
| 7321 | 7335 |
| 7322 | 7336 |
| 7323 template<class T> | 7337 template<class T> |
| 7324 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { | 7338 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { |
| 7339 ElementsKind initial_kind = GetInitialFastElementsKind(); |
| 7340 ElementsKind initial_holey_kind = GetHoleyElementsKind(initial_kind); |
| 7341 |
| 7325 int to_index = GetSequenceIndexFromFastElementsKind( | 7342 int to_index = GetSequenceIndexFromFastElementsKind( |
| 7326 TERMINAL_FAST_ELEMENTS_KIND); | 7343 TERMINAL_FAST_ELEMENTS_KIND); |
| 7327 for (int i = 0; i <= to_index; ++i) { | 7344 for (int i = 0; i <= to_index; ++i) { |
| 7328 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 7345 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 7329 T stub(kind); | 7346 T stub(kind); |
| 7330 stub.GetCode(isolate)->set_is_pregenerated(true); | 7347 stub.GetCode(isolate)->set_is_pregenerated(true); |
| 7331 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { | 7348 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE || |
| 7349 (!FLAG_track_allocation_sites && |
| 7350 (kind == initial_kind || kind == initial_holey_kind))) { |
| 7332 T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES); | 7351 T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES); |
| 7333 stub1.GetCode(isolate)->set_is_pregenerated(true); | 7352 stub1.GetCode(isolate)->set_is_pregenerated(true); |
| 7334 } | 7353 } |
| 7335 } | 7354 } |
| 7336 } | 7355 } |
| 7337 | 7356 |
| 7338 | 7357 |
| 7339 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { | 7358 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { |
| 7340 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( | 7359 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( |
| 7341 isolate); | 7360 isolate); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 7354 InternalArrayNoArgumentConstructorStub stubh1(kinds[i]); | 7373 InternalArrayNoArgumentConstructorStub stubh1(kinds[i]); |
| 7355 stubh1.GetCode(isolate)->set_is_pregenerated(true); | 7374 stubh1.GetCode(isolate)->set_is_pregenerated(true); |
| 7356 InternalArraySingleArgumentConstructorStub stubh2(kinds[i]); | 7375 InternalArraySingleArgumentConstructorStub stubh2(kinds[i]); |
| 7357 stubh2.GetCode(isolate)->set_is_pregenerated(true); | 7376 stubh2.GetCode(isolate)->set_is_pregenerated(true); |
| 7358 InternalArrayNArgumentsConstructorStub stubh3(kinds[i]); | 7377 InternalArrayNArgumentsConstructorStub stubh3(kinds[i]); |
| 7359 stubh3.GetCode(isolate)->set_is_pregenerated(true); | 7378 stubh3.GetCode(isolate)->set_is_pregenerated(true); |
| 7360 } | 7379 } |
| 7361 } | 7380 } |
| 7362 | 7381 |
| 7363 | 7382 |
| 7383 void ArrayConstructorStub::GenerateDispatchToArrayStub( |
| 7384 MacroAssembler* masm, |
| 7385 AllocationSiteOverrideMode mode) { |
| 7386 if (argument_count_ == ANY) { |
| 7387 Label not_zero_case, not_one_case; |
| 7388 __ test(eax, eax); |
| 7389 __ j(not_zero, ¬_zero_case); |
| 7390 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
| 7391 |
| 7392 __ bind(¬_zero_case); |
| 7393 __ cmp(eax, 1); |
| 7394 __ j(greater, ¬_one_case); |
| 7395 CreateArrayDispatchOneArgument(masm, mode); |
| 7396 |
| 7397 __ bind(¬_one_case); |
| 7398 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
| 7399 } else if (argument_count_ == NONE) { |
| 7400 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
| 7401 } else if (argument_count_ == ONE) { |
| 7402 CreateArrayDispatchOneArgument(masm, mode); |
| 7403 } else if (argument_count_ == MORE_THAN_ONE) { |
| 7404 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
| 7405 } else { |
| 7406 UNREACHABLE(); |
| 7407 } |
| 7408 } |
| 7409 |
| 7410 |
| 7364 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 7411 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
| 7365 // ----------- S t a t e ------------- | 7412 // ----------- S t a t e ------------- |
| 7366 // -- eax : argc (only if argument_count_ == ANY) | 7413 // -- eax : argc (only if argument_count_ == ANY) |
| 7367 // -- ebx : type info cell | 7414 // -- ebx : type info cell |
| 7368 // -- edi : constructor | 7415 // -- edi : constructor |
| 7369 // -- esp[0] : return address | 7416 // -- esp[0] : return address |
| 7370 // -- esp[4] : last argument | 7417 // -- esp[4] : last argument |
| 7371 // ----------------------------------- | 7418 // ----------------------------------- |
| 7372 Handle<Object> undefined_sentinel( | 7419 Handle<Object> undefined_sentinel( |
| 7373 masm->isolate()->heap()->undefined_value(), | 7420 masm->isolate()->heap()->undefined_value(), |
| (...skipping 14 matching lines...) Expand all Loading... |
| 7388 // We should either have undefined in ebx or a valid cell | 7435 // We should either have undefined in ebx or a valid cell |
| 7389 Label okay_here; | 7436 Label okay_here; |
| 7390 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); | 7437 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); |
| 7391 __ cmp(ebx, Immediate(undefined_sentinel)); | 7438 __ cmp(ebx, Immediate(undefined_sentinel)); |
| 7392 __ j(equal, &okay_here); | 7439 __ j(equal, &okay_here); |
| 7393 __ cmp(FieldOperand(ebx, 0), Immediate(cell_map)); | 7440 __ cmp(FieldOperand(ebx, 0), Immediate(cell_map)); |
| 7394 __ Assert(equal, kExpectedPropertyCellInRegisterEbx); | 7441 __ Assert(equal, kExpectedPropertyCellInRegisterEbx); |
| 7395 __ bind(&okay_here); | 7442 __ bind(&okay_here); |
| 7396 } | 7443 } |
| 7397 | 7444 |
| 7398 Label no_info, switch_ready; | 7445 Label no_info; |
| 7399 // Get the elements kind and case on that. | 7446 // If the type cell is undefined, or contains anything other than an |
| 7447 // AllocationSite, call an array constructor that doesn't use AllocationSites. |
| 7400 __ cmp(ebx, Immediate(undefined_sentinel)); | 7448 __ cmp(ebx, Immediate(undefined_sentinel)); |
| 7401 __ j(equal, &no_info); | 7449 __ j(equal, &no_info); |
| 7402 __ mov(edx, FieldOperand(ebx, Cell::kValueOffset)); | 7450 __ mov(edx, FieldOperand(ebx, Cell::kValueOffset)); |
| 7403 | |
| 7404 // The type cell may have undefined in its value. | |
| 7405 __ cmp(edx, Immediate(undefined_sentinel)); | |
| 7406 __ j(equal, &no_info); | |
| 7407 | |
| 7408 // The type cell has either an AllocationSite or a JSFunction | |
| 7409 __ cmp(FieldOperand(edx, 0), Immediate(Handle<Map>( | 7451 __ cmp(FieldOperand(edx, 0), Immediate(Handle<Map>( |
| 7410 masm->isolate()->heap()->allocation_site_map()))); | 7452 masm->isolate()->heap()->allocation_site_map()))); |
| 7411 __ j(not_equal, &no_info); | 7453 __ j(not_equal, &no_info); |
| 7412 | 7454 |
| 7413 __ mov(edx, FieldOperand(edx, AllocationSite::kTransitionInfoOffset)); | 7455 __ mov(edx, FieldOperand(edx, AllocationSite::kTransitionInfoOffset)); |
| 7414 __ SmiUntag(edx); | 7456 __ SmiUntag(edx); |
| 7415 __ jmp(&switch_ready); | 7457 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); |
| 7458 |
| 7416 __ bind(&no_info); | 7459 __ bind(&no_info); |
| 7417 __ mov(edx, Immediate(GetInitialFastElementsKind())); | 7460 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); |
| 7418 __ bind(&switch_ready); | |
| 7419 | |
| 7420 if (argument_count_ == ANY) { | |
| 7421 Label not_zero_case, not_one_case; | |
| 7422 __ test(eax, eax); | |
| 7423 __ j(not_zero, ¬_zero_case); | |
| 7424 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); | |
| 7425 | |
| 7426 __ bind(¬_zero_case); | |
| 7427 __ cmp(eax, 1); | |
| 7428 __ j(greater, ¬_one_case); | |
| 7429 CreateArrayDispatchOneArgument(masm); | |
| 7430 | |
| 7431 __ bind(¬_one_case); | |
| 7432 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); | |
| 7433 } else if (argument_count_ == NONE) { | |
| 7434 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); | |
| 7435 } else if (argument_count_ == ONE) { | |
| 7436 CreateArrayDispatchOneArgument(masm); | |
| 7437 } else if (argument_count_ == MORE_THAN_ONE) { | |
| 7438 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); | |
| 7439 } else { | |
| 7440 UNREACHABLE(); | |
| 7441 } | |
| 7442 } | 7461 } |
| 7443 | 7462 |
| 7444 | 7463 |
| 7445 void InternalArrayConstructorStub::GenerateCase( | 7464 void InternalArrayConstructorStub::GenerateCase( |
| 7446 MacroAssembler* masm, ElementsKind kind) { | 7465 MacroAssembler* masm, ElementsKind kind) { |
| 7447 Label not_zero_case, not_one_case; | 7466 Label not_zero_case, not_one_case; |
| 7448 Label normal_sequence; | 7467 Label normal_sequence; |
| 7449 | 7468 |
| 7450 __ test(eax, eax); | 7469 __ test(eax, eax); |
| 7451 __ j(not_zero, ¬_zero_case); | 7470 __ j(not_zero, ¬_zero_case); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7528 __ bind(&fast_elements_case); | 7547 __ bind(&fast_elements_case); |
| 7529 GenerateCase(masm, FAST_ELEMENTS); | 7548 GenerateCase(masm, FAST_ELEMENTS); |
| 7530 } | 7549 } |
| 7531 | 7550 |
| 7532 | 7551 |
| 7533 #undef __ | 7552 #undef __ |
| 7534 | 7553 |
| 7535 } } // namespace v8::internal | 7554 } } // namespace v8::internal |
| 7536 | 7555 |
| 7537 #endif // V8_TARGET_ARCH_IA32 | 7556 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |