Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(121)

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 3388004: Add support for near labels.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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, &not_smi); 2529 __ j(not_zero, &not_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(&not_smi); 2533 __ bind(&not_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
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, &not_identical); 2624 __ j(not_equal, &not_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, &not_identical); 2651 __ j(above_equal, &not_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
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(&not_identical); 2689 __ bind(&not_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
2727 __ mov(eax, ebx); 2727 __ mov(eax, ebx);
2728 __ ret(0); 2728 __ ret(0);
2729 2729
2730 __ bind(&not_smis); 2730 __ bind(&not_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
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
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, &not_both_objects); 2868 __ j(not_zero, &not_both_objects);
2869 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); 2869 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
2870 __ j(below, &not_both_objects); 2870 __ j(below, &not_both_objects);
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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, &not_array_index); 4179 __ j(above, &not_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(&not_array_index); 4185 __ bind(&not_array_index);
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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, &not_same); 4586 __ j(not_equal, &not_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(&not_same); 4593 __ bind(&not_same);
4594 4594
(...skipping 11 matching lines...) Expand all
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698