OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 // Return and remove the on-stack parameters. | 201 // Return and remove the on-stack parameters. |
202 __ ret(3 * kPointerSize); | 202 __ ret(3 * kPointerSize); |
203 | 203 |
204 __ bind(&slow_case); | 204 __ bind(&slow_case); |
205 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); | 205 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); |
206 } | 206 } |
207 | 207 |
208 | 208 |
209 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). | 209 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). |
210 void ToBooleanStub::Generate(MacroAssembler* masm) { | 210 void ToBooleanStub::Generate(MacroAssembler* masm) { |
211 Label false_result, true_result, not_string; | 211 NearLabel false_result, true_result, not_string; |
212 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 212 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
213 | 213 |
214 // 'null' => false. | 214 // 'null' => false. |
215 __ cmp(eax, Factory::null_value()); | 215 __ cmp(eax, Factory::null_value()); |
216 __ j(equal, &false_result); | 216 __ j(equal, &false_result); |
217 | 217 |
218 // Get the map and type of the heap object. | 218 // Get the map and type of the heap object. |
219 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 219 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
220 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset)); | 220 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset)); |
221 | 221 |
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 // Tag smi result and return. | 959 // Tag smi result and return. |
960 __ SmiTag(eax); | 960 __ SmiTag(eax); |
961 GenerateReturn(masm); | 961 GenerateReturn(masm); |
962 | 962 |
963 // All ops except SHR return a signed int32 that we load in | 963 // All ops except SHR return a signed int32 that we load in |
964 // a HeapNumber. | 964 // a HeapNumber. |
965 if (op_ != Token::SHR) { | 965 if (op_ != Token::SHR) { |
966 __ bind(&non_smi_result); | 966 __ bind(&non_smi_result); |
967 // Allocate a heap number if needed. | 967 // Allocate a heap number if needed. |
968 __ mov(ebx, Operand(eax)); // ebx: result | 968 __ mov(ebx, Operand(eax)); // ebx: result |
969 Label skip_allocation; | 969 NearLabel skip_allocation; |
970 switch (mode_) { | 970 switch (mode_) { |
971 case OVERWRITE_LEFT: | 971 case OVERWRITE_LEFT: |
972 case OVERWRITE_RIGHT: | 972 case OVERWRITE_RIGHT: |
973 // If the operand was an object, we skip the | 973 // If the operand was an object, we skip the |
974 // allocation of a heap number. | 974 // allocation of a heap number. |
975 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? | 975 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? |
976 1 * kPointerSize : 2 * kPointerSize)); | 976 1 * kPointerSize : 2 * kPointerSize)); |
977 __ test(eax, Immediate(kSmiTagMask)); | 977 __ test(eax, Immediate(kSmiTagMask)); |
978 __ j(not_zero, &skip_allocation, not_taken); | 978 __ j(not_zero, &skip_allocation, not_taken); |
979 // Fall through! | 979 // Fall through! |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1029 Register lhs, rhs; | 1029 Register lhs, rhs; |
1030 if (HasArgsReversed()) { | 1030 if (HasArgsReversed()) { |
1031 lhs = eax; | 1031 lhs = eax; |
1032 rhs = edx; | 1032 rhs = edx; |
1033 } else { | 1033 } else { |
1034 lhs = edx; | 1034 lhs = edx; |
1035 rhs = eax; | 1035 rhs = eax; |
1036 } | 1036 } |
1037 | 1037 |
1038 // Test if left operand is a string. | 1038 // Test if left operand is a string. |
1039 Label lhs_not_string; | 1039 NearLabel lhs_not_string; |
1040 __ test(lhs, Immediate(kSmiTagMask)); | 1040 __ test(lhs, Immediate(kSmiTagMask)); |
1041 __ j(zero, &lhs_not_string); | 1041 __ j(zero, &lhs_not_string); |
1042 __ CmpObjectType(lhs, FIRST_NONSTRING_TYPE, ecx); | 1042 __ CmpObjectType(lhs, FIRST_NONSTRING_TYPE, ecx); |
1043 __ j(above_equal, &lhs_not_string); | 1043 __ j(above_equal, &lhs_not_string); |
1044 | 1044 |
1045 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); | 1045 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); |
1046 __ TailCallStub(&string_add_left_stub); | 1046 __ TailCallStub(&string_add_left_stub); |
1047 | 1047 |
1048 Label call_runtime_with_args; | 1048 NearLabel call_runtime_with_args; |
1049 // Left operand is not a string, test right. | 1049 // Left operand is not a string, test right. |
1050 __ bind(&lhs_not_string); | 1050 __ bind(&lhs_not_string); |
1051 __ test(rhs, Immediate(kSmiTagMask)); | 1051 __ test(rhs, Immediate(kSmiTagMask)); |
1052 __ j(zero, &call_runtime_with_args); | 1052 __ j(zero, &call_runtime_with_args); |
1053 __ CmpObjectType(rhs, FIRST_NONSTRING_TYPE, ecx); | 1053 __ CmpObjectType(rhs, FIRST_NONSTRING_TYPE, ecx); |
1054 __ j(above_equal, &call_runtime_with_args); | 1054 __ j(above_equal, &call_runtime_with_args); |
1055 | 1055 |
1056 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); | 1056 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); |
1057 __ TailCallStub(&string_add_right_stub); | 1057 __ TailCallStub(&string_add_right_stub); |
1058 | 1058 |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1214 } | 1214 } |
1215 | 1215 |
1216 | 1216 |
1217 void TranscendentalCacheStub::Generate(MacroAssembler* masm) { | 1217 void TranscendentalCacheStub::Generate(MacroAssembler* masm) { |
1218 // Input on stack: | 1218 // Input on stack: |
1219 // esp[4]: argument (should be number). | 1219 // esp[4]: argument (should be number). |
1220 // esp[0]: return address. | 1220 // esp[0]: return address. |
1221 // Test that eax is a number. | 1221 // Test that eax is a number. |
1222 Label runtime_call; | 1222 Label runtime_call; |
1223 Label runtime_call_clear_stack; | 1223 Label runtime_call_clear_stack; |
1224 Label input_not_smi; | 1224 NearLabel input_not_smi; |
1225 Label loaded; | 1225 NearLabel loaded; |
1226 __ mov(eax, Operand(esp, kPointerSize)); | 1226 __ mov(eax, Operand(esp, kPointerSize)); |
1227 __ test(eax, Immediate(kSmiTagMask)); | 1227 __ test(eax, Immediate(kSmiTagMask)); |
1228 __ j(not_zero, &input_not_smi); | 1228 __ j(not_zero, &input_not_smi); |
1229 // Input is a smi. Untag and load it onto the FPU stack. | 1229 // Input is a smi. Untag and load it onto the FPU stack. |
1230 // Then load the low and high words of the double into ebx, edx. | 1230 // Then load the low and high words of the double into ebx, edx. |
1231 STATIC_ASSERT(kSmiTagSize == 1); | 1231 STATIC_ASSERT(kSmiTagSize == 1); |
1232 __ sar(eax, 1); | 1232 __ sar(eax, 1); |
1233 __ sub(Operand(esp), Immediate(2 * kPointerSize)); | 1233 __ sub(Operand(esp), Immediate(2 * kPointerSize)); |
1234 __ mov(Operand(esp, 0), eax); | 1234 __ mov(Operand(esp, 0), eax); |
1235 __ fild_s(Operand(esp, 0)); | 1235 __ fild_s(Operand(esp, 0)); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1288 CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer. | 1288 CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer. |
1289 CHECK_EQ(0, elem_in0 - elem_start); | 1289 CHECK_EQ(0, elem_in0 - elem_start); |
1290 CHECK_EQ(kIntSize, elem_in1 - elem_start); | 1290 CHECK_EQ(kIntSize, elem_in1 - elem_start); |
1291 CHECK_EQ(2 * kIntSize, elem_out - elem_start); | 1291 CHECK_EQ(2 * kIntSize, elem_out - elem_start); |
1292 } | 1292 } |
1293 #endif | 1293 #endif |
1294 // Find the address of the ecx'th entry in the cache, i.e., &eax[ecx*12]. | 1294 // Find the address of the ecx'th entry in the cache, i.e., &eax[ecx*12]. |
1295 __ lea(ecx, Operand(ecx, ecx, times_2, 0)); | 1295 __ lea(ecx, Operand(ecx, ecx, times_2, 0)); |
1296 __ lea(ecx, Operand(eax, ecx, times_4, 0)); | 1296 __ lea(ecx, Operand(eax, ecx, times_4, 0)); |
1297 // Check if cache matches: Double value is stored in uint32_t[2] array. | 1297 // Check if cache matches: Double value is stored in uint32_t[2] array. |
1298 Label cache_miss; | 1298 NearLabel cache_miss; |
1299 __ cmp(ebx, Operand(ecx, 0)); | 1299 __ cmp(ebx, Operand(ecx, 0)); |
1300 __ j(not_equal, &cache_miss); | 1300 __ j(not_equal, &cache_miss); |
1301 __ cmp(edx, Operand(ecx, kIntSize)); | 1301 __ cmp(edx, Operand(ecx, kIntSize)); |
1302 __ j(not_equal, &cache_miss); | 1302 __ j(not_equal, &cache_miss); |
1303 // Cache hit! | 1303 // Cache hit! |
1304 __ mov(eax, Operand(ecx, 2 * kIntSize)); | 1304 __ mov(eax, Operand(ecx, 2 * kIntSize)); |
1305 __ fstp(0); | 1305 __ fstp(0); |
1306 __ ret(kPointerSize); | 1306 __ ret(kPointerSize); |
1307 | 1307 |
1308 __ bind(&cache_miss); | 1308 __ bind(&cache_miss); |
(...skipping 22 matching lines...) Expand all Loading... |
1331 case TranscendentalCache::COS: return Runtime::kMath_cos; | 1331 case TranscendentalCache::COS: return Runtime::kMath_cos; |
1332 default: | 1332 default: |
1333 UNIMPLEMENTED(); | 1333 UNIMPLEMENTED(); |
1334 return Runtime::kAbort; | 1334 return Runtime::kAbort; |
1335 } | 1335 } |
1336 } | 1336 } |
1337 | 1337 |
1338 | 1338 |
1339 void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) { | 1339 void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) { |
1340 // Only free register is edi. | 1340 // Only free register is edi. |
1341 Label done; | 1341 NearLabel done; |
1342 ASSERT(type_ == TranscendentalCache::SIN || | 1342 ASSERT(type_ == TranscendentalCache::SIN || |
1343 type_ == TranscendentalCache::COS); | 1343 type_ == TranscendentalCache::COS); |
1344 // More transcendental types can be added later. | 1344 // More transcendental types can be added later. |
1345 | 1345 |
1346 // Both fsin and fcos require arguments in the range +/-2^63 and | 1346 // Both fsin and fcos require arguments in the range +/-2^63 and |
1347 // return NaN for infinities and NaN. They can share all code except | 1347 // return NaN for infinities and NaN. They can share all code except |
1348 // the actual fsin/fcos operation. | 1348 // the actual fsin/fcos operation. |
1349 Label in_range; | 1349 NearLabel in_range; |
1350 // If argument is outside the range -2^63..2^63, fsin/cos doesn't | 1350 // If argument is outside the range -2^63..2^63, fsin/cos doesn't |
1351 // work. We must reduce it to the appropriate range. | 1351 // work. We must reduce it to the appropriate range. |
1352 __ mov(edi, edx); | 1352 __ mov(edi, edx); |
1353 __ and_(Operand(edi), Immediate(0x7ff00000)); // Exponent only. | 1353 __ and_(Operand(edi), Immediate(0x7ff00000)); // Exponent only. |
1354 int supported_exponent_limit = | 1354 int supported_exponent_limit = |
1355 (63 + HeapNumber::kExponentBias) << HeapNumber::kExponentShift; | 1355 (63 + HeapNumber::kExponentBias) << HeapNumber::kExponentShift; |
1356 __ cmp(Operand(edi), Immediate(supported_exponent_limit)); | 1356 __ cmp(Operand(edi), Immediate(supported_exponent_limit)); |
1357 __ j(below, &in_range, taken); | 1357 __ j(below, &in_range, taken); |
1358 // Check for infinity and NaN. Both return NaN for sin. | 1358 // Check for infinity and NaN. Both return NaN for sin. |
1359 __ cmp(Operand(edi), Immediate(0x7ff00000)); | 1359 __ cmp(Operand(edi), Immediate(0x7ff00000)); |
1360 Label non_nan_result; | 1360 NearLabel non_nan_result; |
1361 __ j(not_equal, &non_nan_result, taken); | 1361 __ j(not_equal, &non_nan_result, taken); |
1362 // Input is +/-Infinity or NaN. Result is NaN. | 1362 // Input is +/-Infinity or NaN. Result is NaN. |
1363 __ fstp(0); | 1363 __ fstp(0); |
1364 // NaN is represented by 0x7ff8000000000000. | 1364 // NaN is represented by 0x7ff8000000000000. |
1365 __ push(Immediate(0x7ff80000)); | 1365 __ push(Immediate(0x7ff80000)); |
1366 __ push(Immediate(0)); | 1366 __ push(Immediate(0)); |
1367 __ fld_d(Operand(esp, 0)); | 1367 __ fld_d(Operand(esp, 0)); |
1368 __ add(Operand(esp), Immediate(2 * kPointerSize)); | 1368 __ add(Operand(esp), Immediate(2 * kPointerSize)); |
1369 __ jmp(&done); | 1369 __ jmp(&done); |
1370 | 1370 |
1371 __ bind(&non_nan_result); | 1371 __ bind(&non_nan_result); |
1372 | 1372 |
1373 // Use fpmod to restrict argument to the range +/-2*PI. | 1373 // Use fpmod to restrict argument to the range +/-2*PI. |
1374 __ mov(edi, eax); // Save eax before using fnstsw_ax. | 1374 __ mov(edi, eax); // Save eax before using fnstsw_ax. |
1375 __ fldpi(); | 1375 __ fldpi(); |
1376 __ fadd(0); | 1376 __ fadd(0); |
1377 __ fld(1); | 1377 __ fld(1); |
1378 // FPU Stack: input, 2*pi, input. | 1378 // FPU Stack: input, 2*pi, input. |
1379 { | 1379 { |
1380 Label no_exceptions; | 1380 NearLabel no_exceptions; |
1381 __ fwait(); | 1381 __ fwait(); |
1382 __ fnstsw_ax(); | 1382 __ fnstsw_ax(); |
1383 // Clear if Illegal Operand or Zero Division exceptions are set. | 1383 // Clear if Illegal Operand or Zero Division exceptions are set. |
1384 __ test(Operand(eax), Immediate(5)); | 1384 __ test(Operand(eax), Immediate(5)); |
1385 __ j(zero, &no_exceptions); | 1385 __ j(zero, &no_exceptions); |
1386 __ fnclex(); | 1386 __ fnclex(); |
1387 __ bind(&no_exceptions); | 1387 __ bind(&no_exceptions); |
1388 } | 1388 } |
1389 | 1389 |
1390 // Compute st(0) % st(1) | 1390 // Compute st(0) % st(1) |
1391 { | 1391 { |
1392 Label partial_remainder_loop; | 1392 NearLabel partial_remainder_loop; |
1393 __ bind(&partial_remainder_loop); | 1393 __ bind(&partial_remainder_loop); |
1394 __ fprem1(); | 1394 __ fprem1(); |
1395 __ fwait(); | 1395 __ fwait(); |
1396 __ fnstsw_ax(); | 1396 __ fnstsw_ax(); |
1397 __ test(Operand(eax), Immediate(0x400 /* C2 */)); | 1397 __ test(Operand(eax), Immediate(0x400 /* C2 */)); |
1398 // If C2 is set, computation only has partial result. Loop to | 1398 // If C2 is set, computation only has partial result. Loop to |
1399 // continue computation. | 1399 // continue computation. |
1400 __ j(not_zero, &partial_remainder_loop); | 1400 __ j(not_zero, &partial_remainder_loop); |
1401 } | 1401 } |
1402 // FPU Stack: input, 2*pi, input % 2*pi | 1402 // FPU Stack: input, 2*pi, input % 2*pi |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1545 // it's probably slower to test than just to do it. | 1545 // it's probably slower to test than just to do it. |
1546 __ mov(scratch2, FieldOperand(source, HeapNumber::kMantissaOffset)); | 1546 __ mov(scratch2, FieldOperand(source, HeapNumber::kMantissaOffset)); |
1547 // Shift down 22 bits to get the most significant 10 bits or the low | 1547 // Shift down 22 bits to get the most significant 10 bits or the low |
1548 // mantissa word. | 1548 // mantissa word. |
1549 __ shr(scratch2, 32 - shift_distance); | 1549 __ shr(scratch2, 32 - shift_distance); |
1550 __ or_(scratch2, Operand(scratch)); | 1550 __ or_(scratch2, Operand(scratch)); |
1551 // Move down according to the exponent. | 1551 // Move down according to the exponent. |
1552 __ shr_cl(scratch2); | 1552 __ shr_cl(scratch2); |
1553 // Now the unsigned answer is in scratch2. We need to move it to ecx and | 1553 // Now the unsigned answer is in scratch2. We need to move it to ecx and |
1554 // we may need to fix the sign. | 1554 // we may need to fix the sign. |
1555 Label negative; | 1555 NearLabel negative; |
1556 __ xor_(ecx, Operand(ecx)); | 1556 __ xor_(ecx, Operand(ecx)); |
1557 __ cmp(ecx, FieldOperand(source, HeapNumber::kExponentOffset)); | 1557 __ cmp(ecx, FieldOperand(source, HeapNumber::kExponentOffset)); |
1558 __ j(greater, &negative); | 1558 __ j(greater, &negative); |
1559 __ mov(ecx, scratch2); | 1559 __ mov(ecx, scratch2); |
1560 __ jmp(&done); | 1560 __ jmp(&done); |
1561 __ bind(&negative); | 1561 __ bind(&negative); |
1562 __ sub(ecx, Operand(scratch2)); | 1562 __ sub(ecx, Operand(scratch2)); |
1563 __ bind(&done); | 1563 __ bind(&done); |
1564 } | 1564 } |
1565 } | 1565 } |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1695 if (type_info.IsNumber()) { | 1695 if (type_info.IsNumber()) { |
1696 LoadNumbersAsIntegers(masm, type_info, use_sse3, conversion_failure); | 1696 LoadNumbersAsIntegers(masm, type_info, use_sse3, conversion_failure); |
1697 } else { | 1697 } else { |
1698 LoadUnknownsAsIntegers(masm, use_sse3, conversion_failure); | 1698 LoadUnknownsAsIntegers(masm, use_sse3, conversion_failure); |
1699 } | 1699 } |
1700 } | 1700 } |
1701 | 1701 |
1702 | 1702 |
1703 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, | 1703 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, |
1704 Register number) { | 1704 Register number) { |
1705 Label load_smi, done; | 1705 NearLabel load_smi, done; |
1706 | 1706 |
1707 __ test(number, Immediate(kSmiTagMask)); | 1707 __ test(number, Immediate(kSmiTagMask)); |
1708 __ j(zero, &load_smi, not_taken); | 1708 __ j(zero, &load_smi, not_taken); |
1709 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset)); | 1709 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset)); |
1710 __ jmp(&done); | 1710 __ jmp(&done); |
1711 | 1711 |
1712 __ bind(&load_smi); | 1712 __ bind(&load_smi); |
1713 __ SmiUntag(number); | 1713 __ SmiUntag(number); |
1714 __ push(number); | 1714 __ push(number); |
1715 __ fild_s(Operand(esp, 0)); | 1715 __ fild_s(Operand(esp, 0)); |
1716 __ pop(number); | 1716 __ pop(number); |
1717 | 1717 |
1718 __ bind(&done); | 1718 __ bind(&done); |
1719 } | 1719 } |
1720 | 1720 |
1721 | 1721 |
1722 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm) { | 1722 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm) { |
1723 Label load_smi_edx, load_eax, load_smi_eax, done; | 1723 NearLabel load_smi_edx, load_eax, load_smi_eax, done; |
1724 // Load operand in edx into xmm0. | 1724 // Load operand in edx into xmm0. |
1725 __ test(edx, Immediate(kSmiTagMask)); | 1725 __ test(edx, Immediate(kSmiTagMask)); |
1726 __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi. | 1726 __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi. |
1727 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 1727 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
1728 | 1728 |
1729 __ bind(&load_eax); | 1729 __ bind(&load_eax); |
1730 // Load operand in eax into xmm1. | 1730 // Load operand in eax into xmm1. |
1731 __ test(eax, Immediate(kSmiTagMask)); | 1731 __ test(eax, Immediate(kSmiTagMask)); |
1732 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi. | 1732 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi. |
1733 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 1733 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
1734 __ jmp(&done); | 1734 __ jmp(&done); |
1735 | 1735 |
1736 __ bind(&load_smi_edx); | 1736 __ bind(&load_smi_edx); |
1737 __ SmiUntag(edx); // Untag smi before converting to float. | 1737 __ SmiUntag(edx); // Untag smi before converting to float. |
1738 __ cvtsi2sd(xmm0, Operand(edx)); | 1738 __ cvtsi2sd(xmm0, Operand(edx)); |
1739 __ SmiTag(edx); // Retag smi for heap number overwriting test. | 1739 __ SmiTag(edx); // Retag smi for heap number overwriting test. |
1740 __ jmp(&load_eax); | 1740 __ jmp(&load_eax); |
1741 | 1741 |
1742 __ bind(&load_smi_eax); | 1742 __ bind(&load_smi_eax); |
1743 __ SmiUntag(eax); // Untag smi before converting to float. | 1743 __ SmiUntag(eax); // Untag smi before converting to float. |
1744 __ cvtsi2sd(xmm1, Operand(eax)); | 1744 __ cvtsi2sd(xmm1, Operand(eax)); |
1745 __ SmiTag(eax); // Retag smi for heap number overwriting test. | 1745 __ SmiTag(eax); // Retag smi for heap number overwriting test. |
1746 | 1746 |
1747 __ bind(&done); | 1747 __ bind(&done); |
1748 } | 1748 } |
1749 | 1749 |
1750 | 1750 |
1751 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm, | 1751 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm, |
1752 Label* not_numbers) { | 1752 Label* not_numbers) { |
1753 Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done; | 1753 NearLabel load_smi_edx, load_eax, load_smi_eax, load_float_eax, done; |
1754 // Load operand in edx into xmm0, or branch to not_numbers. | 1754 // Load operand in edx into xmm0, or branch to not_numbers. |
1755 __ test(edx, Immediate(kSmiTagMask)); | 1755 __ test(edx, Immediate(kSmiTagMask)); |
1756 __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi. | 1756 __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi. |
1757 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), Factory::heap_number_map()); | 1757 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), Factory::heap_number_map()); |
1758 __ j(not_equal, not_numbers); // Argument in edx is not a number. | 1758 __ j(not_equal, not_numbers); // Argument in edx is not a number. |
1759 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 1759 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
1760 __ bind(&load_eax); | 1760 __ bind(&load_eax); |
1761 // Load operand in eax into xmm1, or branch to not_numbers. | 1761 // Load operand in eax into xmm1, or branch to not_numbers. |
1762 __ test(eax, Immediate(kSmiTagMask)); | 1762 __ test(eax, Immediate(kSmiTagMask)); |
1763 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi. | 1763 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi. |
(...skipping 27 matching lines...) Expand all Loading... |
1791 | 1791 |
1792 __ mov(scratch, right); | 1792 __ mov(scratch, right); |
1793 __ SmiUntag(scratch); | 1793 __ SmiUntag(scratch); |
1794 __ cvtsi2sd(xmm1, Operand(scratch)); | 1794 __ cvtsi2sd(xmm1, Operand(scratch)); |
1795 } | 1795 } |
1796 | 1796 |
1797 | 1797 |
1798 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, | 1798 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, |
1799 Register scratch, | 1799 Register scratch, |
1800 ArgLocation arg_location) { | 1800 ArgLocation arg_location) { |
1801 Label load_smi_1, load_smi_2, done_load_1, done; | 1801 NearLabel load_smi_1, load_smi_2, done_load_1, done; |
1802 if (arg_location == ARGS_IN_REGISTERS) { | 1802 if (arg_location == ARGS_IN_REGISTERS) { |
1803 __ mov(scratch, edx); | 1803 __ mov(scratch, edx); |
1804 } else { | 1804 } else { |
1805 __ mov(scratch, Operand(esp, 2 * kPointerSize)); | 1805 __ mov(scratch, Operand(esp, 2 * kPointerSize)); |
1806 } | 1806 } |
1807 __ test(scratch, Immediate(kSmiTagMask)); | 1807 __ test(scratch, Immediate(kSmiTagMask)); |
1808 __ j(zero, &load_smi_1, not_taken); | 1808 __ j(zero, &load_smi_1, not_taken); |
1809 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); | 1809 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); |
1810 __ bind(&done_load_1); | 1810 __ bind(&done_load_1); |
1811 | 1811 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1850 __ SmiUntag(scratch); | 1850 __ SmiUntag(scratch); |
1851 __ mov(Operand(esp, 0), scratch); | 1851 __ mov(Operand(esp, 0), scratch); |
1852 __ fild_s(Operand(esp, 0)); | 1852 __ fild_s(Operand(esp, 0)); |
1853 __ pop(scratch); | 1853 __ pop(scratch); |
1854 } | 1854 } |
1855 | 1855 |
1856 | 1856 |
1857 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm, | 1857 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm, |
1858 Label* non_float, | 1858 Label* non_float, |
1859 Register scratch) { | 1859 Register scratch) { |
1860 Label test_other, done; | 1860 NearLabel test_other, done; |
1861 // Test if both operands are floats or smi -> scratch=k_is_float; | 1861 // Test if both operands are floats or smi -> scratch=k_is_float; |
1862 // Otherwise scratch = k_not_float. | 1862 // Otherwise scratch = k_not_float. |
1863 __ test(edx, Immediate(kSmiTagMask)); | 1863 __ test(edx, Immediate(kSmiTagMask)); |
1864 __ j(zero, &test_other, not_taken); // argument in edx is OK | 1864 __ j(zero, &test_other, not_taken); // argument in edx is OK |
1865 __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset)); | 1865 __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset)); |
1866 __ cmp(scratch, Factory::heap_number_map()); | 1866 __ cmp(scratch, Factory::heap_number_map()); |
1867 __ j(not_equal, non_float); // argument in edx is not a number -> NaN | 1867 __ j(not_equal, non_float); // argument in edx is not a number -> NaN |
1868 | 1868 |
1869 __ bind(&test_other); | 1869 __ bind(&test_other); |
1870 __ test(eax, Immediate(kSmiTagMask)); | 1870 __ test(eax, Immediate(kSmiTagMask)); |
1871 __ j(zero, &done); // argument in eax is OK | 1871 __ j(zero, &done); // argument in eax is OK |
1872 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); | 1872 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); |
1873 __ cmp(scratch, Factory::heap_number_map()); | 1873 __ cmp(scratch, Factory::heap_number_map()); |
1874 __ j(not_equal, non_float); // argument in eax is not a number -> NaN | 1874 __ j(not_equal, non_float); // argument in eax is not a number -> NaN |
1875 | 1875 |
1876 // Fall-through: Both operands are numbers. | 1876 // Fall-through: Both operands are numbers. |
1877 __ bind(&done); | 1877 __ bind(&done); |
1878 } | 1878 } |
1879 | 1879 |
1880 | 1880 |
1881 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { | 1881 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { |
1882 Label slow, done; | 1882 Label slow, done; |
1883 | 1883 |
1884 if (op_ == Token::SUB) { | 1884 if (op_ == Token::SUB) { |
1885 // Check whether the value is a smi. | 1885 // Check whether the value is a smi. |
1886 Label try_float; | 1886 NearLabel try_float; |
1887 __ test(eax, Immediate(kSmiTagMask)); | 1887 __ test(eax, Immediate(kSmiTagMask)); |
1888 __ j(not_zero, &try_float, not_taken); | 1888 __ j(not_zero, &try_float, not_taken); |
1889 | 1889 |
1890 if (negative_zero_ == kStrictNegativeZero) { | 1890 if (negative_zero_ == kStrictNegativeZero) { |
1891 // Go slow case if the value of the expression is zero | 1891 // Go slow case if the value of the expression is zero |
1892 // to make sure that we switch between 0 and -0. | 1892 // to make sure that we switch between 0 and -0. |
1893 __ test(eax, Operand(eax)); | 1893 __ test(eax, Operand(eax)); |
1894 __ j(zero, &slow, not_taken); | 1894 __ j(zero, &slow, not_taken); |
1895 } | 1895 } |
1896 | 1896 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1934 __ j(not_equal, &slow, not_taken); | 1934 __ j(not_equal, &slow, not_taken); |
1935 | 1935 |
1936 // Convert the heap number in eax to an untagged integer in ecx. | 1936 // Convert the heap number in eax to an untagged integer in ecx. |
1937 IntegerConvert(masm, | 1937 IntegerConvert(masm, |
1938 eax, | 1938 eax, |
1939 TypeInfo::Unknown(), | 1939 TypeInfo::Unknown(), |
1940 CpuFeatures::IsSupported(SSE3), | 1940 CpuFeatures::IsSupported(SSE3), |
1941 &slow); | 1941 &slow); |
1942 | 1942 |
1943 // Do the bitwise operation and check if the result fits in a smi. | 1943 // Do the bitwise operation and check if the result fits in a smi. |
1944 Label try_float; | 1944 NearLabel try_float; |
1945 __ not_(ecx); | 1945 __ not_(ecx); |
1946 __ cmp(ecx, 0xc0000000); | 1946 __ cmp(ecx, 0xc0000000); |
1947 __ j(sign, &try_float, not_taken); | 1947 __ j(sign, &try_float, not_taken); |
1948 | 1948 |
1949 // Tag the result as a smi and we're done. | 1949 // Tag the result as a smi and we're done. |
1950 STATIC_ASSERT(kSmiTagSize == 1); | 1950 STATIC_ASSERT(kSmiTagSize == 1); |
1951 __ lea(eax, Operand(ecx, times_2, kSmiTag)); | 1951 __ lea(eax, Operand(ecx, times_2, kSmiTag)); |
1952 __ jmp(&done); | 1952 __ jmp(&done); |
1953 | 1953 |
1954 // Try to store the result in a heap number. | 1954 // Try to store the result in a heap number. |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2003 // stack. It is the offset of the last parameter (if any) relative | 2003 // stack. It is the offset of the last parameter (if any) relative |
2004 // to the frame pointer. | 2004 // to the frame pointer. |
2005 static const int kDisplacement = 1 * kPointerSize; | 2005 static const int kDisplacement = 1 * kPointerSize; |
2006 | 2006 |
2007 // Check that the key is a smi. | 2007 // Check that the key is a smi. |
2008 Label slow; | 2008 Label slow; |
2009 __ test(edx, Immediate(kSmiTagMask)); | 2009 __ test(edx, Immediate(kSmiTagMask)); |
2010 __ j(not_zero, &slow, not_taken); | 2010 __ j(not_zero, &slow, not_taken); |
2011 | 2011 |
2012 // Check if the calling frame is an arguments adaptor frame. | 2012 // Check if the calling frame is an arguments adaptor frame. |
2013 Label adaptor; | 2013 NearLabel adaptor; |
2014 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2014 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
2015 __ mov(ecx, Operand(ebx, StandardFrameConstants::kContextOffset)); | 2015 __ mov(ecx, Operand(ebx, StandardFrameConstants::kContextOffset)); |
2016 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 2016 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
2017 __ j(equal, &adaptor); | 2017 __ j(equal, &adaptor); |
2018 | 2018 |
2019 // Check index against formal parameters count limit passed in | 2019 // Check index against formal parameters count limit passed in |
2020 // through register eax. Use unsigned comparison to get negative | 2020 // through register eax. Use unsigned comparison to get negative |
2021 // check for free. | 2021 // check for free. |
2022 __ cmp(edx, Operand(eax)); | 2022 __ cmp(edx, Operand(eax)); |
2023 __ j(above_equal, &slow, not_taken); | 2023 __ j(above_equal, &slow, not_taken); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2080 | 2080 |
2081 // Patch the arguments.length and the parameters pointer. | 2081 // Patch the arguments.length and the parameters pointer. |
2082 __ bind(&adaptor_frame); | 2082 __ bind(&adaptor_frame); |
2083 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2083 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
2084 __ mov(Operand(esp, 1 * kPointerSize), ecx); | 2084 __ mov(Operand(esp, 1 * kPointerSize), ecx); |
2085 __ lea(edx, Operand(edx, ecx, times_2, kDisplacement)); | 2085 __ lea(edx, Operand(edx, ecx, times_2, kDisplacement)); |
2086 __ mov(Operand(esp, 2 * kPointerSize), edx); | 2086 __ mov(Operand(esp, 2 * kPointerSize), edx); |
2087 | 2087 |
2088 // Try the new space allocation. Start out with computing the size of | 2088 // Try the new space allocation. Start out with computing the size of |
2089 // the arguments object and the elements array. | 2089 // the arguments object and the elements array. |
2090 Label add_arguments_object; | 2090 NearLabel add_arguments_object; |
2091 __ bind(&try_allocate); | 2091 __ bind(&try_allocate); |
2092 __ test(ecx, Operand(ecx)); | 2092 __ test(ecx, Operand(ecx)); |
2093 __ j(zero, &add_arguments_object); | 2093 __ j(zero, &add_arguments_object); |
2094 __ lea(ecx, Operand(ecx, times_2, FixedArray::kHeaderSize)); | 2094 __ lea(ecx, Operand(ecx, times_2, FixedArray::kHeaderSize)); |
2095 __ bind(&add_arguments_object); | 2095 __ bind(&add_arguments_object); |
2096 __ add(Operand(ecx), Immediate(Heap::kArgumentsObjectSize)); | 2096 __ add(Operand(ecx), Immediate(Heap::kArgumentsObjectSize)); |
2097 | 2097 |
2098 // Do the allocation of both objects in one go. | 2098 // Do the allocation of both objects in one go. |
2099 __ AllocateInNewSpace(ecx, eax, edx, ebx, &runtime, TAG_OBJECT); | 2099 __ AllocateInNewSpace(ecx, eax, edx, ebx, &runtime, TAG_OBJECT); |
2100 | 2100 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2132 // initialize the header in the elements fixed array. | 2132 // initialize the header in the elements fixed array. |
2133 __ lea(edi, Operand(eax, Heap::kArgumentsObjectSize)); | 2133 __ lea(edi, Operand(eax, Heap::kArgumentsObjectSize)); |
2134 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); | 2134 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); |
2135 __ mov(FieldOperand(edi, FixedArray::kMapOffset), | 2135 __ mov(FieldOperand(edi, FixedArray::kMapOffset), |
2136 Immediate(Factory::fixed_array_map())); | 2136 Immediate(Factory::fixed_array_map())); |
2137 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); | 2137 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); |
2138 // Untag the length for the loop below. | 2138 // Untag the length for the loop below. |
2139 __ SmiUntag(ecx); | 2139 __ SmiUntag(ecx); |
2140 | 2140 |
2141 // Copy the fixed array slots. | 2141 // Copy the fixed array slots. |
2142 Label loop; | 2142 NearLabel loop; |
2143 __ bind(&loop); | 2143 __ bind(&loop); |
2144 __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver. | 2144 __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver. |
2145 __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx); | 2145 __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx); |
2146 __ add(Operand(edi), Immediate(kPointerSize)); | 2146 __ add(Operand(edi), Immediate(kPointerSize)); |
2147 __ sub(Operand(edx), Immediate(kPointerSize)); | 2147 __ sub(Operand(edx), Immediate(kPointerSize)); |
2148 __ dec(ecx); | 2148 __ dec(ecx); |
2149 __ j(not_zero, &loop); | 2149 __ j(not_zero, &loop); |
2150 | 2150 |
2151 // Return and remove the on-stack parameters. | 2151 // Return and remove the on-stack parameters. |
2152 __ bind(&done); | 2152 __ bind(&done); |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2360 __ mov(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_address)); | 2360 __ mov(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_address)); |
2361 __ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); | 2361 __ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); |
2362 __ mov(Operand(esp, 5 * kPointerSize), ecx); | 2362 __ mov(Operand(esp, 5 * kPointerSize), ecx); |
2363 | 2363 |
2364 // Argument 5: static offsets vector buffer. | 2364 // Argument 5: static offsets vector buffer. |
2365 __ mov(Operand(esp, 4 * kPointerSize), | 2365 __ mov(Operand(esp, 4 * kPointerSize), |
2366 Immediate(ExternalReference::address_of_static_offsets_vector())); | 2366 Immediate(ExternalReference::address_of_static_offsets_vector())); |
2367 | 2367 |
2368 // Argument 4: End of string data | 2368 // Argument 4: End of string data |
2369 // Argument 3: Start of string data | 2369 // Argument 3: Start of string data |
2370 Label setup_two_byte, setup_rest; | 2370 NearLabel setup_two_byte, setup_rest; |
2371 __ test(edi, Operand(edi)); | 2371 __ test(edi, Operand(edi)); |
2372 __ mov(edi, FieldOperand(eax, String::kLengthOffset)); | 2372 __ mov(edi, FieldOperand(eax, String::kLengthOffset)); |
2373 __ j(zero, &setup_two_byte); | 2373 __ j(zero, &setup_two_byte); |
2374 __ SmiUntag(edi); | 2374 __ SmiUntag(edi); |
2375 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize)); | 2375 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize)); |
2376 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. | 2376 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. |
2377 __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); | 2377 __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); |
2378 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. | 2378 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. |
2379 __ jmp(&setup_rest); | 2379 __ jmp(&setup_rest); |
2380 | 2380 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2454 __ RecordWrite(ecx, RegExpImpl::kLastInputOffset, eax, edi); | 2454 __ RecordWrite(ecx, RegExpImpl::kLastInputOffset, eax, edi); |
2455 | 2455 |
2456 // Get the static offsets vector filled by the native regexp code. | 2456 // Get the static offsets vector filled by the native regexp code. |
2457 ExternalReference address_of_static_offsets_vector = | 2457 ExternalReference address_of_static_offsets_vector = |
2458 ExternalReference::address_of_static_offsets_vector(); | 2458 ExternalReference::address_of_static_offsets_vector(); |
2459 __ mov(ecx, Immediate(address_of_static_offsets_vector)); | 2459 __ mov(ecx, Immediate(address_of_static_offsets_vector)); |
2460 | 2460 |
2461 // ebx: last_match_info backing store (FixedArray) | 2461 // ebx: last_match_info backing store (FixedArray) |
2462 // ecx: offsets vector | 2462 // ecx: offsets vector |
2463 // edx: number of capture registers | 2463 // edx: number of capture registers |
2464 Label next_capture, done; | 2464 NearLabel next_capture, done; |
2465 // Capture register counter starts from number of capture registers and | 2465 // Capture register counter starts from number of capture registers and |
2466 // counts down until wraping after zero. | 2466 // counts down until wraping after zero. |
2467 __ bind(&next_capture); | 2467 __ bind(&next_capture); |
2468 __ sub(Operand(edx), Immediate(1)); | 2468 __ sub(Operand(edx), Immediate(1)); |
2469 __ j(negative, &done); | 2469 __ j(negative, &done); |
2470 // Read the value from the static offsets vector buffer. | 2470 // Read the value from the static offsets vector buffer. |
2471 __ mov(edi, Operand(ecx, edx, times_int_size, 0)); | 2471 __ mov(edi, Operand(ecx, edx, times_int_size, 0)); |
2472 __ SmiTag(edi); | 2472 __ SmiTag(edi); |
2473 // Store the smi value in the last match info. | 2473 // Store the smi value in the last match info. |
2474 __ mov(FieldOperand(ebx, | 2474 __ mov(FieldOperand(ebx, |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2510 // Make the hash mask from the length of the number string cache. It | 2510 // Make the hash mask from the length of the number string cache. It |
2511 // contains two elements (number and string) for each cache entry. | 2511 // contains two elements (number and string) for each cache entry. |
2512 __ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); | 2512 __ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); |
2513 __ shr(mask, kSmiTagSize + 1); // Untag length and divide it by two. | 2513 __ shr(mask, kSmiTagSize + 1); // Untag length and divide it by two. |
2514 __ sub(Operand(mask), Immediate(1)); // Make mask. | 2514 __ sub(Operand(mask), Immediate(1)); // Make mask. |
2515 | 2515 |
2516 // Calculate the entry in the number string cache. The hash value in the | 2516 // Calculate the entry in the number string cache. The hash value in the |
2517 // number string cache for smis is just the smi value, and the hash for | 2517 // number string cache for smis is just the smi value, and the hash for |
2518 // doubles is the xor of the upper and lower words. See | 2518 // doubles is the xor of the upper and lower words. See |
2519 // Heap::GetNumberStringCache. | 2519 // Heap::GetNumberStringCache. |
2520 Label smi_hash_calculated; | 2520 NearLabel smi_hash_calculated; |
2521 Label load_result_from_cache; | 2521 NearLabel load_result_from_cache; |
2522 if (object_is_smi) { | 2522 if (object_is_smi) { |
2523 __ mov(scratch, object); | 2523 __ mov(scratch, object); |
2524 __ SmiUntag(scratch); | 2524 __ SmiUntag(scratch); |
2525 } else { | 2525 } else { |
2526 Label not_smi, hash_calculated; | 2526 NearLabel not_smi, hash_calculated; |
2527 STATIC_ASSERT(kSmiTag == 0); | 2527 STATIC_ASSERT(kSmiTag == 0); |
2528 __ test(object, Immediate(kSmiTagMask)); | 2528 __ test(object, Immediate(kSmiTagMask)); |
2529 __ j(not_zero, ¬_smi); | 2529 __ j(not_zero, ¬_smi); |
2530 __ mov(scratch, object); | 2530 __ mov(scratch, object); |
2531 __ SmiUntag(scratch); | 2531 __ SmiUntag(scratch); |
2532 __ jmp(&smi_hash_calculated); | 2532 __ jmp(&smi_hash_calculated); |
2533 __ bind(¬_smi); | 2533 __ bind(¬_smi); |
2534 __ cmp(FieldOperand(object, HeapObject::kMapOffset), | 2534 __ cmp(FieldOperand(object, HeapObject::kMapOffset), |
2535 Factory::heap_number_map()); | 2535 Factory::heap_number_map()); |
2536 __ j(not_equal, not_found); | 2536 __ j(not_equal, not_found); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2619 // Identical objects can be compared fast, but there are some tricky cases | 2619 // Identical objects can be compared fast, but there are some tricky cases |
2620 // for NaN and undefined. | 2620 // for NaN and undefined. |
2621 { | 2621 { |
2622 Label not_identical; | 2622 Label not_identical; |
2623 __ cmp(eax, Operand(edx)); | 2623 __ cmp(eax, Operand(edx)); |
2624 __ j(not_equal, ¬_identical); | 2624 __ j(not_equal, ¬_identical); |
2625 | 2625 |
2626 if (cc_ != equal) { | 2626 if (cc_ != equal) { |
2627 // Check for undefined. undefined OP undefined is false even though | 2627 // Check for undefined. undefined OP undefined is false even though |
2628 // undefined == undefined. | 2628 // undefined == undefined. |
2629 Label check_for_nan; | 2629 NearLabel check_for_nan; |
2630 __ cmp(edx, Factory::undefined_value()); | 2630 __ cmp(edx, Factory::undefined_value()); |
2631 __ j(not_equal, &check_for_nan); | 2631 __ j(not_equal, &check_for_nan); |
2632 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); | 2632 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); |
2633 __ ret(0); | 2633 __ ret(0); |
2634 __ bind(&check_for_nan); | 2634 __ bind(&check_for_nan); |
2635 } | 2635 } |
2636 | 2636 |
2637 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), | 2637 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), |
2638 // so we do the second best thing - test it ourselves. | 2638 // so we do the second best thing - test it ourselves. |
2639 // Note: if cc_ != equal, never_nan_nan_ is not used. | 2639 // Note: if cc_ != equal, never_nan_nan_ is not used. |
2640 if (never_nan_nan_ && (cc_ == equal)) { | 2640 if (never_nan_nan_ && (cc_ == equal)) { |
2641 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 2641 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
2642 __ ret(0); | 2642 __ ret(0); |
2643 } else { | 2643 } else { |
2644 Label heap_number; | 2644 NearLabel heap_number; |
2645 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2645 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
2646 Immediate(Factory::heap_number_map())); | 2646 Immediate(Factory::heap_number_map())); |
2647 __ j(equal, &heap_number); | 2647 __ j(equal, &heap_number); |
2648 if (cc_ != equal) { | 2648 if (cc_ != equal) { |
2649 // Call runtime on identical JSObjects. Otherwise return equal. | 2649 // Call runtime on identical JSObjects. Otherwise return equal. |
2650 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); | 2650 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); |
2651 __ j(above_equal, ¬_identical); | 2651 __ j(above_equal, ¬_identical); |
2652 } | 2652 } |
2653 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 2653 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
2654 __ ret(0); | 2654 __ ret(0); |
(...skipping 14 matching lines...) Expand all Loading... |
2669 __ xor_(eax, Operand(eax)); | 2669 __ xor_(eax, Operand(eax)); |
2670 // Shift value and mask so kQuietNaNHighBitsMask applies to topmost | 2670 // Shift value and mask so kQuietNaNHighBitsMask applies to topmost |
2671 // bits. | 2671 // bits. |
2672 __ add(edx, Operand(edx)); | 2672 __ add(edx, Operand(edx)); |
2673 __ cmp(edx, kQuietNaNHighBitsMask << 1); | 2673 __ cmp(edx, kQuietNaNHighBitsMask << 1); |
2674 if (cc_ == equal) { | 2674 if (cc_ == equal) { |
2675 STATIC_ASSERT(EQUAL != 1); | 2675 STATIC_ASSERT(EQUAL != 1); |
2676 __ setcc(above_equal, eax); | 2676 __ setcc(above_equal, eax); |
2677 __ ret(0); | 2677 __ ret(0); |
2678 } else { | 2678 } else { |
2679 Label nan; | 2679 NearLabel nan; |
2680 __ j(above_equal, &nan); | 2680 __ j(above_equal, &nan); |
2681 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 2681 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
2682 __ ret(0); | 2682 __ ret(0); |
2683 __ bind(&nan); | 2683 __ bind(&nan); |
2684 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); | 2684 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); |
2685 __ ret(0); | 2685 __ ret(0); |
2686 } | 2686 } |
2687 } | 2687 } |
2688 | 2688 |
2689 __ bind(¬_identical); | 2689 __ bind(¬_identical); |
2690 } | 2690 } |
2691 | 2691 |
2692 // Strict equality can quickly decide whether objects are equal. | 2692 // Strict equality can quickly decide whether objects are equal. |
2693 // Non-strict object equality is slower, so it is handled later in the stub. | 2693 // Non-strict object equality is slower, so it is handled later in the stub. |
2694 if (cc_ == equal && strict_) { | 2694 if (cc_ == equal && strict_) { |
2695 Label slow; // Fallthrough label. | 2695 Label slow; // Fallthrough label. |
2696 Label not_smis; | 2696 NearLabel not_smis; |
2697 // If we're doing a strict equality comparison, we don't have to do | 2697 // If we're doing a strict equality comparison, we don't have to do |
2698 // type conversion, so we generate code to do fast comparison for objects | 2698 // type conversion, so we generate code to do fast comparison for objects |
2699 // and oddballs. Non-smi numbers and strings still go through the usual | 2699 // and oddballs. Non-smi numbers and strings still go through the usual |
2700 // slow-case code. | 2700 // slow-case code. |
2701 // If either is a Smi (we know that not both are), then they can only | 2701 // If either is a Smi (we know that not both are), then they can only |
2702 // be equal if the other is a HeapNumber. If so, use the slow case. | 2702 // be equal if the other is a HeapNumber. If so, use the slow case. |
2703 STATIC_ASSERT(kSmiTag == 0); | 2703 STATIC_ASSERT(kSmiTag == 0); |
2704 ASSERT_EQ(0, Smi::FromInt(0)); | 2704 ASSERT_EQ(0, Smi::FromInt(0)); |
2705 __ mov(ecx, Immediate(kSmiTagMask)); | 2705 __ mov(ecx, Immediate(kSmiTagMask)); |
2706 __ and_(ecx, Operand(eax)); | 2706 __ and_(ecx, Operand(eax)); |
(...skipping 20 matching lines...) Expand all Loading... |
2727 __ mov(eax, ebx); | 2727 __ mov(eax, ebx); |
2728 __ ret(0); | 2728 __ ret(0); |
2729 | 2729 |
2730 __ bind(¬_smis); | 2730 __ bind(¬_smis); |
2731 // If either operand is a JSObject or an oddball value, then they are not | 2731 // If either operand is a JSObject or an oddball value, then they are not |
2732 // equal since their pointers are different | 2732 // equal since their pointers are different |
2733 // There is no test for undetectability in strict equality. | 2733 // There is no test for undetectability in strict equality. |
2734 | 2734 |
2735 // Get the type of the first operand. | 2735 // Get the type of the first operand. |
2736 // If the first object is a JS object, we have done pointer comparison. | 2736 // If the first object is a JS object, we have done pointer comparison. |
2737 Label first_non_object; | 2737 NearLabel first_non_object; |
2738 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | 2738 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); |
2739 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); | 2739 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); |
2740 __ j(below, &first_non_object); | 2740 __ j(below, &first_non_object); |
2741 | 2741 |
2742 // Return non-zero (eax is not zero) | 2742 // Return non-zero (eax is not zero) |
2743 Label return_not_equal; | 2743 NearLabel return_not_equal; |
2744 STATIC_ASSERT(kHeapObjectTag != 0); | 2744 STATIC_ASSERT(kHeapObjectTag != 0); |
2745 __ bind(&return_not_equal); | 2745 __ bind(&return_not_equal); |
2746 __ ret(0); | 2746 __ ret(0); |
2747 | 2747 |
2748 __ bind(&first_non_object); | 2748 __ bind(&first_non_object); |
2749 // Check for oddballs: true, false, null, undefined. | 2749 // Check for oddballs: true, false, null, undefined. |
2750 __ CmpInstanceType(ecx, ODDBALL_TYPE); | 2750 __ CmpInstanceType(ecx, ODDBALL_TYPE); |
2751 __ j(equal, &return_not_equal); | 2751 __ j(equal, &return_not_equal); |
2752 | 2752 |
2753 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ecx); | 2753 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ecx); |
(...skipping 30 matching lines...) Expand all Loading... |
2784 } else { | 2784 } else { |
2785 FloatingPointHelper::CheckFloatOperands( | 2785 FloatingPointHelper::CheckFloatOperands( |
2786 masm, &non_number_comparison, ebx); | 2786 masm, &non_number_comparison, ebx); |
2787 FloatingPointHelper::LoadFloatOperand(masm, eax); | 2787 FloatingPointHelper::LoadFloatOperand(masm, eax); |
2788 FloatingPointHelper::LoadFloatOperand(masm, edx); | 2788 FloatingPointHelper::LoadFloatOperand(masm, edx); |
2789 __ FCmp(); | 2789 __ FCmp(); |
2790 | 2790 |
2791 // Don't base result on EFLAGS when a NaN is involved. | 2791 // Don't base result on EFLAGS when a NaN is involved. |
2792 __ j(parity_even, &unordered, not_taken); | 2792 __ j(parity_even, &unordered, not_taken); |
2793 | 2793 |
2794 Label below_label, above_label; | 2794 NearLabel below_label, above_label; |
2795 // Return a result of -1, 0, or 1, based on EFLAGS. | 2795 // Return a result of -1, 0, or 1, based on EFLAGS. |
2796 __ j(below, &below_label, not_taken); | 2796 __ j(below, &below_label, not_taken); |
2797 __ j(above, &above_label, not_taken); | 2797 __ j(above, &above_label, not_taken); |
2798 | 2798 |
2799 __ xor_(eax, Operand(eax)); | 2799 __ xor_(eax, Operand(eax)); |
2800 __ ret(0); | 2800 __ ret(0); |
2801 | 2801 |
2802 __ bind(&below_label); | 2802 __ bind(&below_label); |
2803 __ mov(eax, Immediate(Smi::FromInt(-1))); | 2803 __ mov(eax, Immediate(Smi::FromInt(-1))); |
2804 __ ret(0); | 2804 __ ret(0); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2849 edi); | 2849 edi); |
2850 #ifdef DEBUG | 2850 #ifdef DEBUG |
2851 __ Abort("Unexpected fall-through from string comparison"); | 2851 __ Abort("Unexpected fall-through from string comparison"); |
2852 #endif | 2852 #endif |
2853 | 2853 |
2854 __ bind(&check_unequal_objects); | 2854 __ bind(&check_unequal_objects); |
2855 if (cc_ == equal && !strict_) { | 2855 if (cc_ == equal && !strict_) { |
2856 // Non-strict equality. Objects are unequal if | 2856 // Non-strict equality. Objects are unequal if |
2857 // they are both JSObjects and not undetectable, | 2857 // they are both JSObjects and not undetectable, |
2858 // and their pointers are different. | 2858 // and their pointers are different. |
2859 Label not_both_objects; | 2859 NearLabel not_both_objects; |
2860 Label return_unequal; | 2860 NearLabel return_unequal; |
2861 // At most one is a smi, so we can test for smi by adding the two. | 2861 // At most one is a smi, so we can test for smi by adding the two. |
2862 // A smi plus a heap object has the low bit set, a heap object plus | 2862 // A smi plus a heap object has the low bit set, a heap object plus |
2863 // a heap object has the low bit clear. | 2863 // a heap object has the low bit clear. |
2864 STATIC_ASSERT(kSmiTag == 0); | 2864 STATIC_ASSERT(kSmiTag == 0); |
2865 STATIC_ASSERT(kSmiTagMask == 1); | 2865 STATIC_ASSERT(kSmiTagMask == 1); |
2866 __ lea(ecx, Operand(eax, edx, times_1, 0)); | 2866 __ lea(ecx, Operand(eax, edx, times_1, 0)); |
2867 __ test(ecx, Immediate(kSmiTagMask)); | 2867 __ test(ecx, Immediate(kSmiTagMask)); |
2868 __ j(not_zero, ¬_both_objects); | 2868 __ j(not_zero, ¬_both_objects); |
2869 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); | 2869 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); |
2870 __ j(below, ¬_both_objects); | 2870 __ j(below, ¬_both_objects); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3012 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | 3012 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
3013 __ pop(Operand::StaticVariable(handler_address)); | 3013 __ pop(Operand::StaticVariable(handler_address)); |
3014 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize); | 3014 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize); |
3015 __ pop(ebp); | 3015 __ pop(ebp); |
3016 __ pop(edx); // Remove state. | 3016 __ pop(edx); // Remove state. |
3017 | 3017 |
3018 // Before returning we restore the context from the frame pointer if | 3018 // Before returning we restore the context from the frame pointer if |
3019 // not NULL. The frame pointer is NULL in the exception handler of | 3019 // not NULL. The frame pointer is NULL in the exception handler of |
3020 // a JS entry frame. | 3020 // a JS entry frame. |
3021 __ xor_(esi, Operand(esi)); // Tentatively set context pointer to NULL. | 3021 __ xor_(esi, Operand(esi)); // Tentatively set context pointer to NULL. |
3022 Label skip; | 3022 NearLabel skip; |
3023 __ cmp(ebp, 0); | 3023 __ cmp(ebp, 0); |
3024 __ j(equal, &skip, not_taken); | 3024 __ j(equal, &skip, not_taken); |
3025 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3025 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
3026 __ bind(&skip); | 3026 __ bind(&skip); |
3027 | 3027 |
3028 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); | 3028 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); |
3029 __ ret(0); | 3029 __ ret(0); |
3030 } | 3030 } |
3031 | 3031 |
3032 | 3032 |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3144 __ call(Operand(ebx)); | 3144 __ call(Operand(ebx)); |
3145 // Result is in eax or edx:eax - do not destroy these registers! | 3145 // Result is in eax or edx:eax - do not destroy these registers! |
3146 | 3146 |
3147 if (always_allocate_scope) { | 3147 if (always_allocate_scope) { |
3148 __ dec(Operand::StaticVariable(scope_depth)); | 3148 __ dec(Operand::StaticVariable(scope_depth)); |
3149 } | 3149 } |
3150 | 3150 |
3151 // Make sure we're not trying to return 'the hole' from the runtime | 3151 // Make sure we're not trying to return 'the hole' from the runtime |
3152 // call as this may lead to crashes in the IC code later. | 3152 // call as this may lead to crashes in the IC code later. |
3153 if (FLAG_debug_code) { | 3153 if (FLAG_debug_code) { |
3154 Label okay; | 3154 NearLabel okay; |
3155 __ cmp(eax, Factory::the_hole_value()); | 3155 __ cmp(eax, Factory::the_hole_value()); |
3156 __ j(not_equal, &okay); | 3156 __ j(not_equal, &okay); |
3157 __ int3(); | 3157 __ int3(); |
3158 __ bind(&okay); | 3158 __ bind(&okay); |
3159 } | 3159 } |
3160 | 3160 |
3161 // Check for failure result. | 3161 // Check for failure result. |
3162 Label failure_returned; | 3162 Label failure_returned; |
3163 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); | 3163 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); |
3164 __ lea(ecx, Operand(eax, 1)); | 3164 __ lea(ecx, Operand(eax, 1)); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3206 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, | 3206 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, |
3207 UncatchableExceptionType type) { | 3207 UncatchableExceptionType type) { |
3208 // Adjust this code if not the case. | 3208 // Adjust this code if not the case. |
3209 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | 3209 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); |
3210 | 3210 |
3211 // Drop sp to the top stack handler. | 3211 // Drop sp to the top stack handler. |
3212 ExternalReference handler_address(Top::k_handler_address); | 3212 ExternalReference handler_address(Top::k_handler_address); |
3213 __ mov(esp, Operand::StaticVariable(handler_address)); | 3213 __ mov(esp, Operand::StaticVariable(handler_address)); |
3214 | 3214 |
3215 // Unwind the handlers until the ENTRY handler is found. | 3215 // Unwind the handlers until the ENTRY handler is found. |
3216 Label loop, done; | 3216 NearLabel loop, done; |
3217 __ bind(&loop); | 3217 __ bind(&loop); |
3218 // Load the type of the current stack handler. | 3218 // Load the type of the current stack handler. |
3219 const int kStateOffset = StackHandlerConstants::kStateOffset; | 3219 const int kStateOffset = StackHandlerConstants::kStateOffset; |
3220 __ cmp(Operand(esp, kStateOffset), Immediate(StackHandler::ENTRY)); | 3220 __ cmp(Operand(esp, kStateOffset), Immediate(StackHandler::ENTRY)); |
3221 __ j(equal, &done); | 3221 __ j(equal, &done); |
3222 // Fetch the next handler in the list. | 3222 // Fetch the next handler in the list. |
3223 const int kNextOffset = StackHandlerConstants::kNextOffset; | 3223 const int kNextOffset = StackHandlerConstants::kNextOffset; |
3224 __ mov(esp, Operand(esp, kNextOffset)); | 3224 __ mov(esp, Operand(esp, kNextOffset)); |
3225 __ jmp(&loop); | 3225 __ jmp(&loop); |
3226 __ bind(&done); | 3226 __ bind(&done); |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3424 __ j(zero, &slow, not_taken); | 3424 __ j(zero, &slow, not_taken); |
3425 | 3425 |
3426 // Check that the left hand is a JS object. | 3426 // Check that the left hand is a JS object. |
3427 __ IsObjectJSObjectType(eax, eax, edx, &slow); | 3427 __ IsObjectJSObjectType(eax, eax, edx, &slow); |
3428 | 3428 |
3429 // Get the prototype of the function. | 3429 // Get the prototype of the function. |
3430 __ mov(edx, Operand(esp, 1 * kPointerSize)); // 1 ~ return address | 3430 __ mov(edx, Operand(esp, 1 * kPointerSize)); // 1 ~ return address |
3431 // edx is function, eax is map. | 3431 // edx is function, eax is map. |
3432 | 3432 |
3433 // Look up the function and the map in the instanceof cache. | 3433 // Look up the function and the map in the instanceof cache. |
3434 Label miss; | 3434 NearLabel miss; |
3435 ExternalReference roots_address = ExternalReference::roots_address(); | 3435 ExternalReference roots_address = ExternalReference::roots_address(); |
3436 __ mov(ecx, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); | 3436 __ mov(ecx, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); |
3437 __ cmp(edx, Operand::StaticArray(ecx, times_pointer_size, roots_address)); | 3437 __ cmp(edx, Operand::StaticArray(ecx, times_pointer_size, roots_address)); |
3438 __ j(not_equal, &miss); | 3438 __ j(not_equal, &miss); |
3439 __ mov(ecx, Immediate(Heap::kInstanceofCacheMapRootIndex)); | 3439 __ mov(ecx, Immediate(Heap::kInstanceofCacheMapRootIndex)); |
3440 __ cmp(eax, Operand::StaticArray(ecx, times_pointer_size, roots_address)); | 3440 __ cmp(eax, Operand::StaticArray(ecx, times_pointer_size, roots_address)); |
3441 __ j(not_equal, &miss); | 3441 __ j(not_equal, &miss); |
3442 __ mov(ecx, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); | 3442 __ mov(ecx, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); |
3443 __ mov(eax, Operand::StaticArray(ecx, times_pointer_size, roots_address)); | 3443 __ mov(eax, Operand::StaticArray(ecx, times_pointer_size, roots_address)); |
3444 __ ret(2 * kPointerSize); | 3444 __ ret(2 * kPointerSize); |
(...skipping 11 matching lines...) Expand all Loading... |
3456 // edx is function. | 3456 // edx is function. |
3457 // ebx is function prototype. | 3457 // ebx is function prototype. |
3458 __ mov(ecx, Immediate(Heap::kInstanceofCacheMapRootIndex)); | 3458 __ mov(ecx, Immediate(Heap::kInstanceofCacheMapRootIndex)); |
3459 __ mov(Operand::StaticArray(ecx, times_pointer_size, roots_address), eax); | 3459 __ mov(Operand::StaticArray(ecx, times_pointer_size, roots_address), eax); |
3460 __ mov(ecx, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); | 3460 __ mov(ecx, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); |
3461 __ mov(Operand::StaticArray(ecx, times_pointer_size, roots_address), edx); | 3461 __ mov(Operand::StaticArray(ecx, times_pointer_size, roots_address), edx); |
3462 | 3462 |
3463 __ mov(ecx, FieldOperand(eax, Map::kPrototypeOffset)); | 3463 __ mov(ecx, FieldOperand(eax, Map::kPrototypeOffset)); |
3464 | 3464 |
3465 // Loop through the prototype chain looking for the function prototype. | 3465 // Loop through the prototype chain looking for the function prototype. |
3466 Label loop, is_instance, is_not_instance; | 3466 NearLabel loop, is_instance, is_not_instance; |
3467 __ bind(&loop); | 3467 __ bind(&loop); |
3468 __ cmp(ecx, Operand(ebx)); | 3468 __ cmp(ecx, Operand(ebx)); |
3469 __ j(equal, &is_instance); | 3469 __ j(equal, &is_instance); |
3470 __ cmp(Operand(ecx), Immediate(Factory::null_value())); | 3470 __ cmp(Operand(ecx), Immediate(Factory::null_value())); |
3471 __ j(equal, &is_not_instance); | 3471 __ j(equal, &is_not_instance); |
3472 __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset)); | 3472 __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset)); |
3473 __ mov(ecx, FieldOperand(ecx, Map::kPrototypeOffset)); | 3473 __ mov(ecx, FieldOperand(ecx, Map::kPrototypeOffset)); |
3474 __ jmp(&loop); | 3474 __ jmp(&loop); |
3475 | 3475 |
3476 __ bind(&is_instance); | 3476 __ bind(&is_instance); |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3786 GenerateConvertArgument(masm, 1 * kPointerSize, edx, ebx, ecx, edi, | 3786 GenerateConvertArgument(masm, 1 * kPointerSize, edx, ebx, ecx, edi, |
3787 &call_builtin); | 3787 &call_builtin); |
3788 builtin_id = Builtins::STRING_ADD_LEFT; | 3788 builtin_id = Builtins::STRING_ADD_LEFT; |
3789 } | 3789 } |
3790 } | 3790 } |
3791 | 3791 |
3792 // Both arguments are strings. | 3792 // Both arguments are strings. |
3793 // eax: first string | 3793 // eax: first string |
3794 // edx: second string | 3794 // edx: second string |
3795 // Check if either of the strings are empty. In that case return the other. | 3795 // Check if either of the strings are empty. In that case return the other. |
3796 Label second_not_zero_length, both_not_zero_length; | 3796 NearLabel second_not_zero_length, both_not_zero_length; |
3797 __ mov(ecx, FieldOperand(edx, String::kLengthOffset)); | 3797 __ mov(ecx, FieldOperand(edx, String::kLengthOffset)); |
3798 STATIC_ASSERT(kSmiTag == 0); | 3798 STATIC_ASSERT(kSmiTag == 0); |
3799 __ test(ecx, Operand(ecx)); | 3799 __ test(ecx, Operand(ecx)); |
3800 __ j(not_zero, &second_not_zero_length); | 3800 __ j(not_zero, &second_not_zero_length); |
3801 // Second string is empty, result is first string which is already in eax. | 3801 // Second string is empty, result is first string which is already in eax. |
3802 __ IncrementCounter(&Counters::string_add_native, 1); | 3802 __ IncrementCounter(&Counters::string_add_native, 1); |
3803 __ ret(2 * kPointerSize); | 3803 __ ret(2 * kPointerSize); |
3804 __ bind(&second_not_zero_length); | 3804 __ bind(&second_not_zero_length); |
3805 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); | 3805 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); |
3806 STATIC_ASSERT(kSmiTag == 0); | 3806 STATIC_ASSERT(kSmiTag == 0); |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4072 __ bind(&done); | 4072 __ bind(&done); |
4073 } | 4073 } |
4074 | 4074 |
4075 | 4075 |
4076 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, | 4076 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, |
4077 Register dest, | 4077 Register dest, |
4078 Register src, | 4078 Register src, |
4079 Register count, | 4079 Register count, |
4080 Register scratch, | 4080 Register scratch, |
4081 bool ascii) { | 4081 bool ascii) { |
4082 Label loop; | 4082 NearLabel loop; |
4083 __ bind(&loop); | 4083 __ bind(&loop); |
4084 // This loop just copies one character at a time, as it is only used for very | 4084 // This loop just copies one character at a time, as it is only used for very |
4085 // short strings. | 4085 // short strings. |
4086 if (ascii) { | 4086 if (ascii) { |
4087 __ mov_b(scratch, Operand(src, 0)); | 4087 __ mov_b(scratch, Operand(src, 0)); |
4088 __ mov_b(Operand(dest, 0), scratch); | 4088 __ mov_b(Operand(dest, 0), scratch); |
4089 __ add(Operand(src), Immediate(1)); | 4089 __ add(Operand(src), Immediate(1)); |
4090 __ add(Operand(dest), Immediate(1)); | 4090 __ add(Operand(dest), Immediate(1)); |
4091 } else { | 4091 } else { |
4092 __ mov_w(scratch, Operand(src, 0)); | 4092 __ mov_w(scratch, Operand(src, 0)); |
(...skipping 26 matching lines...) Expand all Loading... |
4119 Label done; | 4119 Label done; |
4120 __ test(count, Operand(count)); | 4120 __ test(count, Operand(count)); |
4121 __ j(zero, &done); | 4121 __ j(zero, &done); |
4122 | 4122 |
4123 // Make count the number of bytes to copy. | 4123 // Make count the number of bytes to copy. |
4124 if (!ascii) { | 4124 if (!ascii) { |
4125 __ shl(count, 1); | 4125 __ shl(count, 1); |
4126 } | 4126 } |
4127 | 4127 |
4128 // Don't enter the rep movs if there are less than 4 bytes to copy. | 4128 // Don't enter the rep movs if there are less than 4 bytes to copy. |
4129 Label last_bytes; | 4129 NearLabel last_bytes; |
4130 __ test(count, Immediate(~3)); | 4130 __ test(count, Immediate(~3)); |
4131 __ j(zero, &last_bytes); | 4131 __ j(zero, &last_bytes); |
4132 | 4132 |
4133 // Copy from edi to esi using rep movs instruction. | 4133 // Copy from edi to esi using rep movs instruction. |
4134 __ mov(scratch, count); | 4134 __ mov(scratch, count); |
4135 __ sar(count, 2); // Number of doublewords to copy. | 4135 __ sar(count, 2); // Number of doublewords to copy. |
4136 __ cld(); | 4136 __ cld(); |
4137 __ rep_movs(); | 4137 __ rep_movs(); |
4138 | 4138 |
4139 // Find number of bytes left. | 4139 // Find number of bytes left. |
4140 __ mov(count, scratch); | 4140 __ mov(count, scratch); |
4141 __ and_(count, 3); | 4141 __ and_(count, 3); |
4142 | 4142 |
4143 // Check if there are more bytes to copy. | 4143 // Check if there are more bytes to copy. |
4144 __ bind(&last_bytes); | 4144 __ bind(&last_bytes); |
4145 __ test(count, Operand(count)); | 4145 __ test(count, Operand(count)); |
4146 __ j(zero, &done); | 4146 __ j(zero, &done); |
4147 | 4147 |
4148 // Copy remaining characters. | 4148 // Copy remaining characters. |
4149 Label loop; | 4149 NearLabel loop; |
4150 __ bind(&loop); | 4150 __ bind(&loop); |
4151 __ mov_b(scratch, Operand(src, 0)); | 4151 __ mov_b(scratch, Operand(src, 0)); |
4152 __ mov_b(Operand(dest, 0), scratch); | 4152 __ mov_b(Operand(dest, 0), scratch); |
4153 __ add(Operand(src), Immediate(1)); | 4153 __ add(Operand(src), Immediate(1)); |
4154 __ add(Operand(dest), Immediate(1)); | 4154 __ add(Operand(dest), Immediate(1)); |
4155 __ sub(Operand(count), Immediate(1)); | 4155 __ sub(Operand(count), Immediate(1)); |
4156 __ j(not_zero, &loop); | 4156 __ j(not_zero, &loop); |
4157 | 4157 |
4158 __ bind(&done); | 4158 __ bind(&done); |
4159 } | 4159 } |
4160 | 4160 |
4161 | 4161 |
4162 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, | 4162 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, |
4163 Register c1, | 4163 Register c1, |
4164 Register c2, | 4164 Register c2, |
4165 Register scratch1, | 4165 Register scratch1, |
4166 Register scratch2, | 4166 Register scratch2, |
4167 Register scratch3, | 4167 Register scratch3, |
4168 Label* not_probed, | 4168 Label* not_probed, |
4169 Label* not_found) { | 4169 Label* not_found) { |
4170 // Register scratch3 is the general scratch register in this function. | 4170 // Register scratch3 is the general scratch register in this function. |
4171 Register scratch = scratch3; | 4171 Register scratch = scratch3; |
4172 | 4172 |
4173 // Make sure that both characters are not digits as such strings has a | 4173 // Make sure that both characters are not digits as such strings has a |
4174 // different hash algorithm. Don't try to look for these in the symbol table. | 4174 // different hash algorithm. Don't try to look for these in the symbol table. |
4175 Label not_array_index; | 4175 NearLabel not_array_index; |
4176 __ mov(scratch, c1); | 4176 __ mov(scratch, c1); |
4177 __ sub(Operand(scratch), Immediate(static_cast<int>('0'))); | 4177 __ sub(Operand(scratch), Immediate(static_cast<int>('0'))); |
4178 __ cmp(Operand(scratch), Immediate(static_cast<int>('9' - '0'))); | 4178 __ cmp(Operand(scratch), Immediate(static_cast<int>('9' - '0'))); |
4179 __ j(above, ¬_array_index); | 4179 __ j(above, ¬_array_index); |
4180 __ mov(scratch, c2); | 4180 __ mov(scratch, c2); |
4181 __ sub(Operand(scratch), Immediate(static_cast<int>('0'))); | 4181 __ sub(Operand(scratch), Immediate(static_cast<int>('0'))); |
4182 __ cmp(Operand(scratch), Immediate(static_cast<int>('9' - '0'))); | 4182 __ cmp(Operand(scratch), Immediate(static_cast<int>('9' - '0'))); |
4183 __ j(below_equal, not_probed); | 4183 __ j(below_equal, not_probed); |
4184 | 4184 |
4185 __ bind(¬_array_index); | 4185 __ bind(¬_array_index); |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4323 // hash ^= hash >> 11; | 4323 // hash ^= hash >> 11; |
4324 __ mov(scratch, hash); | 4324 __ mov(scratch, hash); |
4325 __ sar(scratch, 11); | 4325 __ sar(scratch, 11); |
4326 __ xor_(hash, Operand(scratch)); | 4326 __ xor_(hash, Operand(scratch)); |
4327 // hash += hash << 15; | 4327 // hash += hash << 15; |
4328 __ mov(scratch, hash); | 4328 __ mov(scratch, hash); |
4329 __ shl(scratch, 15); | 4329 __ shl(scratch, 15); |
4330 __ add(hash, Operand(scratch)); | 4330 __ add(hash, Operand(scratch)); |
4331 | 4331 |
4332 // if (hash == 0) hash = 27; | 4332 // if (hash == 0) hash = 27; |
4333 Label hash_not_zero; | 4333 NearLabel hash_not_zero; |
4334 __ test(hash, Operand(hash)); | 4334 __ test(hash, Operand(hash)); |
4335 __ j(not_zero, &hash_not_zero); | 4335 __ j(not_zero, &hash_not_zero); |
4336 __ mov(hash, Immediate(27)); | 4336 __ mov(hash, Immediate(27)); |
4337 __ bind(&hash_not_zero); | 4337 __ bind(&hash_not_zero); |
4338 } | 4338 } |
4339 | 4339 |
4340 | 4340 |
4341 void SubStringStub::Generate(MacroAssembler* masm) { | 4341 void SubStringStub::Generate(MacroAssembler* masm) { |
4342 Label runtime; | 4342 Label runtime; |
4343 | 4343 |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4492 Register scratch1, | 4492 Register scratch1, |
4493 Register scratch2, | 4493 Register scratch2, |
4494 Register scratch3) { | 4494 Register scratch3) { |
4495 Label result_not_equal; | 4495 Label result_not_equal; |
4496 Label result_greater; | 4496 Label result_greater; |
4497 Label compare_lengths; | 4497 Label compare_lengths; |
4498 | 4498 |
4499 __ IncrementCounter(&Counters::string_compare_native, 1); | 4499 __ IncrementCounter(&Counters::string_compare_native, 1); |
4500 | 4500 |
4501 // Find minimum length. | 4501 // Find minimum length. |
4502 Label left_shorter; | 4502 NearLabel left_shorter; |
4503 __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); | 4503 __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); |
4504 __ mov(scratch3, scratch1); | 4504 __ mov(scratch3, scratch1); |
4505 __ sub(scratch3, FieldOperand(right, String::kLengthOffset)); | 4505 __ sub(scratch3, FieldOperand(right, String::kLengthOffset)); |
4506 | 4506 |
4507 Register length_delta = scratch3; | 4507 Register length_delta = scratch3; |
4508 | 4508 |
4509 __ j(less_equal, &left_shorter); | 4509 __ j(less_equal, &left_shorter); |
4510 // Right string is shorter. Change scratch1 to be length of right string. | 4510 // Right string is shorter. Change scratch1 to be length of right string. |
4511 __ sub(scratch1, Operand(length_delta)); | 4511 __ sub(scratch1, Operand(length_delta)); |
4512 __ bind(&left_shorter); | 4512 __ bind(&left_shorter); |
(...skipping 15 matching lines...) Expand all Loading... |
4528 __ lea(right, | 4528 __ lea(right, |
4529 FieldOperand(right, | 4529 FieldOperand(right, |
4530 min_length, times_1, | 4530 min_length, times_1, |
4531 SeqAsciiString::kHeaderSize)); | 4531 SeqAsciiString::kHeaderSize)); |
4532 __ neg(min_length); | 4532 __ neg(min_length); |
4533 | 4533 |
4534 Register index = min_length; // index = -min_length; | 4534 Register index = min_length; // index = -min_length; |
4535 | 4535 |
4536 { | 4536 { |
4537 // Compare loop. | 4537 // Compare loop. |
4538 Label loop; | 4538 NearLabel loop; |
4539 __ bind(&loop); | 4539 __ bind(&loop); |
4540 // Compare characters. | 4540 // Compare characters. |
4541 __ mov_b(scratch2, Operand(left, index, times_1, 0)); | 4541 __ mov_b(scratch2, Operand(left, index, times_1, 0)); |
4542 __ cmpb(scratch2, Operand(right, index, times_1, 0)); | 4542 __ cmpb(scratch2, Operand(right, index, times_1, 0)); |
4543 __ j(not_equal, &result_not_equal); | 4543 __ j(not_equal, &result_not_equal); |
4544 __ add(Operand(index), Immediate(1)); | 4544 __ add(Operand(index), Immediate(1)); |
4545 __ j(not_zero, &loop); | 4545 __ j(not_zero, &loop); |
4546 } | 4546 } |
4547 | 4547 |
4548 // Compare lengths - strings up to min-length are equal. | 4548 // Compare lengths - strings up to min-length are equal. |
(...skipping 25 matching lines...) Expand all Loading... |
4574 Label runtime; | 4574 Label runtime; |
4575 | 4575 |
4576 // Stack frame on entry. | 4576 // Stack frame on entry. |
4577 // esp[0]: return address | 4577 // esp[0]: return address |
4578 // esp[4]: right string | 4578 // esp[4]: right string |
4579 // esp[8]: left string | 4579 // esp[8]: left string |
4580 | 4580 |
4581 __ mov(edx, Operand(esp, 2 * kPointerSize)); // left | 4581 __ mov(edx, Operand(esp, 2 * kPointerSize)); // left |
4582 __ mov(eax, Operand(esp, 1 * kPointerSize)); // right | 4582 __ mov(eax, Operand(esp, 1 * kPointerSize)); // right |
4583 | 4583 |
4584 Label not_same; | 4584 NearLabel not_same; |
4585 __ cmp(edx, Operand(eax)); | 4585 __ cmp(edx, Operand(eax)); |
4586 __ j(not_equal, ¬_same); | 4586 __ j(not_equal, ¬_same); |
4587 STATIC_ASSERT(EQUAL == 0); | 4587 STATIC_ASSERT(EQUAL == 0); |
4588 STATIC_ASSERT(kSmiTag == 0); | 4588 STATIC_ASSERT(kSmiTag == 0); |
4589 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 4589 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
4590 __ IncrementCounter(&Counters::string_compare_native, 1); | 4590 __ IncrementCounter(&Counters::string_compare_native, 1); |
4591 __ ret(2 * kPointerSize); | 4591 __ ret(2 * kPointerSize); |
4592 | 4592 |
4593 __ bind(¬_same); | 4593 __ bind(¬_same); |
4594 | 4594 |
(...skipping 11 matching lines...) Expand all Loading... |
4606 // tagged as a small integer. | 4606 // tagged as a small integer. |
4607 __ bind(&runtime); | 4607 __ bind(&runtime); |
4608 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 4608 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
4609 } | 4609 } |
4610 | 4610 |
4611 #undef __ | 4611 #undef __ |
4612 | 4612 |
4613 } } // namespace v8::internal | 4613 } } // namespace v8::internal |
4614 | 4614 |
4615 #endif // V8_TARGET_ARCH_IA32 | 4615 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |