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