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

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

Issue 6928060: Merge Label and NearLabel (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: address comments Created 9 years, 7 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
« no previous file with comments | « src/x64/builtins-x64.cc ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 22 matching lines...) Expand all
33 #include "code-stubs.h" 33 #include "code-stubs.h"
34 #include "regexp-macro-assembler.h" 34 #include "regexp-macro-assembler.h"
35 35
36 namespace v8 { 36 namespace v8 {
37 namespace internal { 37 namespace internal {
38 38
39 #define __ ACCESS_MASM(masm) 39 #define __ ACCESS_MASM(masm)
40 40
41 void ToNumberStub::Generate(MacroAssembler* masm) { 41 void ToNumberStub::Generate(MacroAssembler* masm) {
42 // The ToNumber stub takes one argument in eax. 42 // The ToNumber stub takes one argument in eax.
43 NearLabel check_heap_number, call_builtin; 43 Label check_heap_number, call_builtin;
44 __ SmiTest(rax); 44 __ SmiTest(rax);
45 __ j(not_zero, &check_heap_number); 45 __ j(not_zero, &check_heap_number, Label::kNear);
46 __ Ret(); 46 __ Ret();
47 47
48 __ bind(&check_heap_number); 48 __ bind(&check_heap_number);
49 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 49 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
50 Heap::kHeapNumberMapRootIndex); 50 Heap::kHeapNumberMapRootIndex);
51 __ j(not_equal, &call_builtin); 51 __ j(not_equal, &call_builtin, Label::kNear);
52 __ Ret(); 52 __ Ret();
53 53
54 __ bind(&call_builtin); 54 __ bind(&call_builtin);
55 __ pop(rcx); // Pop return address. 55 __ pop(rcx); // Pop return address.
56 __ push(rax); 56 __ push(rax);
57 __ push(rcx); // Push return address. 57 __ push(rcx); // Push return address.
58 __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION); 58 __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
59 } 59 }
60 60
61 61
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 225
226 // Return and remove the on-stack parameters. 226 // Return and remove the on-stack parameters.
227 __ ret(3 * kPointerSize); 227 __ ret(3 * kPointerSize);
228 228
229 __ bind(&slow_case); 229 __ bind(&slow_case);
230 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); 230 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1);
231 } 231 }
232 232
233 233
234 void ToBooleanStub::Generate(MacroAssembler* masm) { 234 void ToBooleanStub::Generate(MacroAssembler* masm) {
235 NearLabel false_result, true_result, not_string; 235 Label false_result, true_result, not_string;
236 __ movq(rax, Operand(rsp, 1 * kPointerSize)); 236 __ movq(rax, Operand(rsp, 1 * kPointerSize));
237 237
238 // 'null' => false. 238 // 'null' => false.
239 __ CompareRoot(rax, Heap::kNullValueRootIndex); 239 __ CompareRoot(rax, Heap::kNullValueRootIndex);
240 __ j(equal, &false_result); 240 __ j(equal, &false_result, Label::kNear);
241 241
242 // Get the map and type of the heap object. 242 // Get the map and type of the heap object.
243 // We don't use CmpObjectType because we manipulate the type field. 243 // We don't use CmpObjectType because we manipulate the type field.
244 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); 244 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
245 __ movzxbq(rcx, FieldOperand(rdx, Map::kInstanceTypeOffset)); 245 __ movzxbq(rcx, FieldOperand(rdx, Map::kInstanceTypeOffset));
246 246
247 // Undetectable => false. 247 // Undetectable => false.
248 __ movzxbq(rbx, FieldOperand(rdx, Map::kBitFieldOffset)); 248 __ movzxbq(rbx, FieldOperand(rdx, Map::kBitFieldOffset));
249 __ and_(rbx, Immediate(1 << Map::kIsUndetectable)); 249 __ and_(rbx, Immediate(1 << Map::kIsUndetectable));
250 __ j(not_zero, &false_result); 250 __ j(not_zero, &false_result, Label::kNear);
251 251
252 // JavaScript object => true. 252 // JavaScript object => true.
253 __ cmpq(rcx, Immediate(FIRST_JS_OBJECT_TYPE)); 253 __ cmpq(rcx, Immediate(FIRST_JS_OBJECT_TYPE));
254 __ j(above_equal, &true_result); 254 __ j(above_equal, &true_result, Label::kNear);
255 255
256 // String value => false iff empty. 256 // String value => false iff empty.
257 __ cmpq(rcx, Immediate(FIRST_NONSTRING_TYPE)); 257 __ cmpq(rcx, Immediate(FIRST_NONSTRING_TYPE));
258 __ j(above_equal, &not_string); 258 __ j(above_equal, &not_string, Label::kNear);
259 __ movq(rdx, FieldOperand(rax, String::kLengthOffset)); 259 __ movq(rdx, FieldOperand(rax, String::kLengthOffset));
260 __ SmiTest(rdx); 260 __ SmiTest(rdx);
261 __ j(zero, &false_result); 261 __ j(zero, &false_result, Label::kNear);
262 __ jmp(&true_result); 262 __ jmp(&true_result, Label::kNear);
263 263
264 __ bind(&not_string); 264 __ bind(&not_string);
265 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); 265 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex);
266 __ j(not_equal, &true_result); 266 __ j(not_equal, &true_result, Label::kNear);
267 // HeapNumber => false iff +0, -0, or NaN. 267 // HeapNumber => false iff +0, -0, or NaN.
268 // These three cases set the zero flag when compared to zero using ucomisd. 268 // These three cases set the zero flag when compared to zero using ucomisd.
269 __ xorps(xmm0, xmm0); 269 __ xorps(xmm0, xmm0);
270 __ ucomisd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); 270 __ ucomisd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
271 __ j(zero, &false_result); 271 __ j(zero, &false_result, Label::kNear);
272 // Fall through to |true_result|. 272 // Fall through to |true_result|.
273 273
274 // Return 1/0 for true/false in rax. 274 // Return 1/0 for true/false in rax.
275 __ bind(&true_result); 275 __ bind(&true_result);
276 __ Set(rax, 1); 276 __ Set(rax, 1);
277 __ ret(1 * kPointerSize); 277 __ ret(1 * kPointerSize);
278 __ bind(&false_result); 278 __ bind(&false_result);
279 __ Set(rax, 0); 279 __ Set(rax, 0);
280 __ ret(1 * kPointerSize); 280 __ ret(1 * kPointerSize);
281 } 281 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 void IntegerConvert(MacroAssembler* masm, 327 void IntegerConvert(MacroAssembler* masm,
328 Register result, 328 Register result,
329 Register source) { 329 Register source) {
330 // Result may be rcx. If result and source are the same register, source will 330 // Result may be rcx. If result and source are the same register, source will
331 // be overwritten. 331 // be overwritten.
332 ASSERT(!result.is(rdi) && !result.is(rbx)); 332 ASSERT(!result.is(rdi) && !result.is(rbx));
333 // TODO(lrn): When type info reaches here, if value is a 32-bit integer, use 333 // TODO(lrn): When type info reaches here, if value is a 32-bit integer, use
334 // cvttsd2si (32-bit version) directly. 334 // cvttsd2si (32-bit version) directly.
335 Register double_exponent = rbx; 335 Register double_exponent = rbx;
336 Register double_value = rdi; 336 Register double_value = rdi;
337 NearLabel done, exponent_63_plus; 337 Label done, exponent_63_plus;
338 // Get double and extract exponent. 338 // Get double and extract exponent.
339 __ movq(double_value, FieldOperand(source, HeapNumber::kValueOffset)); 339 __ movq(double_value, FieldOperand(source, HeapNumber::kValueOffset));
340 // Clear result preemptively, in case we need to return zero. 340 // Clear result preemptively, in case we need to return zero.
341 __ xorl(result, result); 341 __ xorl(result, result);
342 __ movq(xmm0, double_value); // Save copy in xmm0 in case we need it there. 342 __ movq(xmm0, double_value); // Save copy in xmm0 in case we need it there.
343 // Double to remove sign bit, shift exponent down to least significant bits. 343 // Double to remove sign bit, shift exponent down to least significant bits.
344 // and subtract bias to get the unshifted, unbiased exponent. 344 // and subtract bias to get the unshifted, unbiased exponent.
345 __ lea(double_exponent, Operand(double_value, double_value, times_1, 0)); 345 __ lea(double_exponent, Operand(double_value, double_value, times_1, 0));
346 __ shr(double_exponent, Immediate(64 - HeapNumber::kExponentBits)); 346 __ shr(double_exponent, Immediate(64 - HeapNumber::kExponentBits));
347 __ subl(double_exponent, Immediate(HeapNumber::kExponentBias)); 347 __ subl(double_exponent, Immediate(HeapNumber::kExponentBias));
348 // Check whether the exponent is too big for a 63 bit unsigned integer. 348 // Check whether the exponent is too big for a 63 bit unsigned integer.
349 __ cmpl(double_exponent, Immediate(63)); 349 __ cmpl(double_exponent, Immediate(63));
350 __ j(above_equal, &exponent_63_plus); 350 __ j(above_equal, &exponent_63_plus, Label::kNear);
351 // Handle exponent range 0..62. 351 // Handle exponent range 0..62.
352 __ cvttsd2siq(result, xmm0); 352 __ cvttsd2siq(result, xmm0);
353 __ jmp(&done); 353 __ jmp(&done, Label::kNear);
354 354
355 __ bind(&exponent_63_plus); 355 __ bind(&exponent_63_plus);
356 // Exponent negative or 63+. 356 // Exponent negative or 63+.
357 __ cmpl(double_exponent, Immediate(83)); 357 __ cmpl(double_exponent, Immediate(83));
358 // If exponent negative or above 83, number contains no significant bits in 358 // If exponent negative or above 83, number contains no significant bits in
359 // the range 0..2^31, so result is zero, and rcx already holds zero. 359 // the range 0..2^31, so result is zero, and rcx already holds zero.
360 __ j(above, &done); 360 __ j(above, &done, Label::kNear);
361 361
362 // Exponent in rage 63..83. 362 // Exponent in rage 63..83.
363 // Mantissa * 2^exponent contains bits in the range 2^0..2^31, namely 363 // Mantissa * 2^exponent contains bits in the range 2^0..2^31, namely
364 // the least significant exponent-52 bits. 364 // the least significant exponent-52 bits.
365 365
366 // Negate low bits of mantissa if value is negative. 366 // Negate low bits of mantissa if value is negative.
367 __ addq(double_value, double_value); // Move sign bit to carry. 367 __ addq(double_value, double_value); // Move sign bit to carry.
368 __ sbbl(result, result); // And convert carry to -1 in result register. 368 __ sbbl(result, result); // And convert carry to -1 in result register.
369 // if scratch2 is negative, do (scratch2-1)^-1, otherwise (scratch2-0)^0. 369 // if scratch2 is negative, do (scratch2-1)^-1, otherwise (scratch2-0)^0.
370 __ addl(double_value, result); 370 __ addl(double_value, result);
(...skipping 779 matching lines...) Expand 10 before | Expand all | Expand 10 after
1150 void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) { 1150 void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
1151 Label call_runtime; 1151 Label call_runtime;
1152 1152
1153 if (op_ == Token::ADD) { 1153 if (op_ == Token::ADD) {
1154 // Handle string addition here, because it is the only operation 1154 // Handle string addition here, because it is the only operation
1155 // that does not do a ToNumber conversion on the operands. 1155 // that does not do a ToNumber conversion on the operands.
1156 GenerateStringAddCode(masm); 1156 GenerateStringAddCode(masm);
1157 } 1157 }
1158 1158
1159 // Convert oddball arguments to numbers. 1159 // Convert oddball arguments to numbers.
1160 NearLabel check, done; 1160 Label check, done;
1161 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); 1161 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex);
1162 __ j(not_equal, &check); 1162 __ j(not_equal, &check, Label::kNear);
1163 if (Token::IsBitOp(op_)) { 1163 if (Token::IsBitOp(op_)) {
1164 __ xor_(rdx, rdx); 1164 __ xor_(rdx, rdx);
1165 } else { 1165 } else {
1166 __ LoadRoot(rdx, Heap::kNanValueRootIndex); 1166 __ LoadRoot(rdx, Heap::kNanValueRootIndex);
1167 } 1167 }
1168 __ jmp(&done); 1168 __ jmp(&done, Label::kNear);
1169 __ bind(&check); 1169 __ bind(&check);
1170 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 1170 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
1171 __ j(not_equal, &done); 1171 __ j(not_equal, &done, Label::kNear);
1172 if (Token::IsBitOp(op_)) { 1172 if (Token::IsBitOp(op_)) {
1173 __ xor_(rax, rax); 1173 __ xor_(rax, rax);
1174 } else { 1174 } else {
1175 __ LoadRoot(rax, Heap::kNanValueRootIndex); 1175 __ LoadRoot(rax, Heap::kNanValueRootIndex);
1176 } 1176 }
1177 __ bind(&done); 1177 __ bind(&done);
1178 1178
1179 GenerateHeapNumberStub(masm); 1179 GenerateHeapNumberStub(masm);
1180 } 1180 }
1181 1181
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1270 // xmm1: untagged double input argument 1270 // xmm1: untagged double input argument
1271 // Output: 1271 // Output:
1272 // xmm1: untagged double result. 1272 // xmm1: untagged double result.
1273 1273
1274 Label runtime_call; 1274 Label runtime_call;
1275 Label runtime_call_clear_stack; 1275 Label runtime_call_clear_stack;
1276 Label skip_cache; 1276 Label skip_cache;
1277 const bool tagged = (argument_type_ == TAGGED); 1277 const bool tagged = (argument_type_ == TAGGED);
1278 if (tagged) { 1278 if (tagged) {
1279 NearLabel input_not_smi; 1279 NearLabel input_not_smi;
1280 NearLabel loaded; 1280 Label loaded;
1281 // Test that rax is a number. 1281 // Test that rax is a number.
1282 __ movq(rax, Operand(rsp, kPointerSize)); 1282 __ movq(rax, Operand(rsp, kPointerSize));
1283 __ JumpIfNotSmi(rax, &input_not_smi); 1283 __ JumpIfNotSmi(rax, &input_not_smi);
1284 // Input is a smi. Untag and load it onto the FPU stack. 1284 // Input is a smi. Untag and load it onto the FPU stack.
1285 // Then load the bits of the double into rbx. 1285 // Then load the bits of the double into rbx.
1286 __ SmiToInteger32(rax, rax); 1286 __ SmiToInteger32(rax, rax);
1287 __ subq(rsp, Immediate(kDoubleSize)); 1287 __ subq(rsp, Immediate(kDoubleSize));
1288 __ cvtlsi2sd(xmm1, rax); 1288 __ cvtlsi2sd(xmm1, rax);
1289 __ movsd(Operand(rsp, 0), xmm1); 1289 __ movsd(Operand(rsp, 0), xmm1);
1290 __ movq(rbx, xmm1); 1290 __ movq(rbx, xmm1);
1291 __ movq(rdx, xmm1); 1291 __ movq(rdx, xmm1);
1292 __ fld_d(Operand(rsp, 0)); 1292 __ fld_d(Operand(rsp, 0));
1293 __ addq(rsp, Immediate(kDoubleSize)); 1293 __ addq(rsp, Immediate(kDoubleSize));
1294 __ jmp(&loaded); 1294 __ jmp(&loaded, Label::kNear);
1295 1295
1296 __ bind(&input_not_smi); 1296 __ bind(&input_not_smi);
1297 // Check if input is a HeapNumber. 1297 // Check if input is a HeapNumber.
1298 __ LoadRoot(rbx, Heap::kHeapNumberMapRootIndex); 1298 __ LoadRoot(rbx, Heap::kHeapNumberMapRootIndex);
1299 __ cmpq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 1299 __ cmpq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
1300 __ j(not_equal, &runtime_call); 1300 __ j(not_equal, &runtime_call);
1301 // Input is a HeapNumber. Push it on the FPU stack and load its 1301 // Input is a HeapNumber. Push it on the FPU stack and load its
1302 // bits into rbx. 1302 // bits into rbx.
1303 __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset)); 1303 __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset));
1304 __ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset)); 1304 __ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset));
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1359 CHECK_EQ(16, static_cast<int>(elem2_start - elem_start)); 1359 CHECK_EQ(16, static_cast<int>(elem2_start - elem_start));
1360 CHECK_EQ(0, static_cast<int>(elem_in0 - elem_start)); 1360 CHECK_EQ(0, static_cast<int>(elem_in0 - elem_start));
1361 CHECK_EQ(kIntSize, static_cast<int>(elem_in1 - elem_start)); 1361 CHECK_EQ(kIntSize, static_cast<int>(elem_in1 - elem_start));
1362 CHECK_EQ(2 * kIntSize, static_cast<int>(elem_out - elem_start)); 1362 CHECK_EQ(2 * kIntSize, static_cast<int>(elem_out - elem_start));
1363 } 1363 }
1364 #endif 1364 #endif
1365 // Find the address of the rcx'th entry in the cache, i.e., &rax[rcx*16]. 1365 // Find the address of the rcx'th entry in the cache, i.e., &rax[rcx*16].
1366 __ addl(rcx, rcx); 1366 __ addl(rcx, rcx);
1367 __ lea(rcx, Operand(rax, rcx, times_8, 0)); 1367 __ lea(rcx, Operand(rax, rcx, times_8, 0));
1368 // Check if cache matches: Double value is stored in uint32_t[2] array. 1368 // Check if cache matches: Double value is stored in uint32_t[2] array.
1369 NearLabel cache_miss; 1369 Label cache_miss;
1370 __ cmpq(rbx, Operand(rcx, 0)); 1370 __ cmpq(rbx, Operand(rcx, 0));
1371 __ j(not_equal, &cache_miss); 1371 __ j(not_equal, &cache_miss, Label::kNear);
1372 // Cache hit! 1372 // Cache hit!
1373 __ movq(rax, Operand(rcx, 2 * kIntSize)); 1373 __ movq(rax, Operand(rcx, 2 * kIntSize));
1374 if (tagged) { 1374 if (tagged) {
1375 __ fstp(0); // Clear FPU stack. 1375 __ fstp(0); // Clear FPU stack.
1376 __ ret(kPointerSize); 1376 __ ret(kPointerSize);
1377 } else { // UNTAGGED. 1377 } else { // UNTAGGED.
1378 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); 1378 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
1379 __ Ret(); 1379 __ Ret();
1380 } 1380 }
1381 1381
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1469 __ movq(rdi, rbx); 1469 __ movq(rdi, rbx);
1470 // Move exponent and sign bits to low bits. 1470 // Move exponent and sign bits to low bits.
1471 __ shr(rdi, Immediate(HeapNumber::kMantissaBits)); 1471 __ shr(rdi, Immediate(HeapNumber::kMantissaBits));
1472 // Remove sign bit. 1472 // Remove sign bit.
1473 __ andl(rdi, Immediate((1 << HeapNumber::kExponentBits) - 1)); 1473 __ andl(rdi, Immediate((1 << HeapNumber::kExponentBits) - 1));
1474 int supported_exponent_limit = (63 + HeapNumber::kExponentBias); 1474 int supported_exponent_limit = (63 + HeapNumber::kExponentBias);
1475 __ cmpl(rdi, Immediate(supported_exponent_limit)); 1475 __ cmpl(rdi, Immediate(supported_exponent_limit));
1476 __ j(below, &in_range); 1476 __ j(below, &in_range);
1477 // Check for infinity and NaN. Both return NaN for sin. 1477 // Check for infinity and NaN. Both return NaN for sin.
1478 __ cmpl(rdi, Immediate(0x7ff)); 1478 __ cmpl(rdi, Immediate(0x7ff));
1479 NearLabel non_nan_result; 1479 Label non_nan_result;
1480 __ j(not_equal, &non_nan_result); 1480 __ j(not_equal, &non_nan_result, Label::kNear);
1481 // Input is +/-Infinity or NaN. Result is NaN. 1481 // Input is +/-Infinity or NaN. Result is NaN.
1482 __ fstp(0); 1482 __ fstp(0);
1483 __ LoadRoot(kScratchRegister, Heap::kNanValueRootIndex); 1483 __ LoadRoot(kScratchRegister, Heap::kNanValueRootIndex);
1484 __ fld_d(FieldOperand(kScratchRegister, HeapNumber::kValueOffset)); 1484 __ fld_d(FieldOperand(kScratchRegister, HeapNumber::kValueOffset));
1485 __ jmp(&done); 1485 __ jmp(&done);
1486 1486
1487 __ bind(&non_nan_result); 1487 __ bind(&non_nan_result);
1488 1488
1489 // Use fpmod to restrict argument to the range +/-2*PI. 1489 // Use fpmod to restrict argument to the range +/-2*PI.
1490 __ movq(rdi, rax); // Save rax before using fnstsw_ax. 1490 __ movq(rdi, rax); // Save rax before using fnstsw_ax.
1491 __ fldpi(); 1491 __ fldpi();
1492 __ fadd(0); 1492 __ fadd(0);
1493 __ fld(1); 1493 __ fld(1);
1494 // FPU Stack: input, 2*pi, input. 1494 // FPU Stack: input, 2*pi, input.
1495 { 1495 {
1496 Label no_exceptions; 1496 Label no_exceptions;
1497 __ fwait(); 1497 __ fwait();
1498 __ fnstsw_ax(); 1498 __ fnstsw_ax();
1499 // Clear if Illegal Operand or Zero Division exceptions are set. 1499 // Clear if Illegal Operand or Zero Division exceptions are set.
1500 __ testl(rax, Immediate(5)); // #IO and #ZD flags of FPU status word. 1500 __ testl(rax, Immediate(5)); // #IO and #ZD flags of FPU status word.
1501 __ j(zero, &no_exceptions); 1501 __ j(zero, &no_exceptions);
1502 __ fnclex(); 1502 __ fnclex();
1503 __ bind(&no_exceptions); 1503 __ bind(&no_exceptions);
1504 } 1504 }
1505 1505
1506 // Compute st(0) % st(1) 1506 // Compute st(0) % st(1)
1507 { 1507 {
1508 NearLabel partial_remainder_loop; 1508 Label partial_remainder_loop;
1509 __ bind(&partial_remainder_loop); 1509 __ bind(&partial_remainder_loop);
1510 __ fprem1(); 1510 __ fprem1();
1511 __ fwait(); 1511 __ fwait();
1512 __ fnstsw_ax(); 1512 __ fnstsw_ax();
1513 __ testl(rax, Immediate(0x400)); // Check C2 bit of FPU status word. 1513 __ testl(rax, Immediate(0x400)); // Check C2 bit of FPU status word.
1514 // If C2 is set, computation only has partial result. Loop to 1514 // If C2 is set, computation only has partial result. Loop to
1515 // continue computation. 1515 // continue computation.
1516 __ j(not_zero, &partial_remainder_loop); 1516 __ j(not_zero, &partial_remainder_loop);
1517 } 1517 }
1518 // FPU Stack: input, 2*pi, input % 2*pi 1518 // FPU Stack: input, 2*pi, input % 2*pi
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1691 Register scratch2, 1691 Register scratch2,
1692 Register scratch3, 1692 Register scratch3,
1693 Label* on_success, 1693 Label* on_success,
1694 Label* on_not_smis) { 1694 Label* on_not_smis) {
1695 Register heap_number_map = scratch3; 1695 Register heap_number_map = scratch3;
1696 Register smi_result = scratch1; 1696 Register smi_result = scratch1;
1697 Label done; 1697 Label done;
1698 1698
1699 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 1699 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
1700 1700
1701 NearLabel first_smi, check_second; 1701 NearLabel first_smi;
1702 __ JumpIfSmi(first, &first_smi); 1702 __ JumpIfSmi(first, &first_smi);
1703 __ cmpq(FieldOperand(first, HeapObject::kMapOffset), heap_number_map); 1703 __ cmpq(FieldOperand(first, HeapObject::kMapOffset), heap_number_map);
1704 __ j(not_equal, on_not_smis); 1704 __ j(not_equal, on_not_smis);
1705 // Convert HeapNumber to smi if possible. 1705 // Convert HeapNumber to smi if possible.
1706 __ movsd(xmm0, FieldOperand(first, HeapNumber::kValueOffset)); 1706 __ movsd(xmm0, FieldOperand(first, HeapNumber::kValueOffset));
1707 __ movq(scratch2, xmm0); 1707 __ movq(scratch2, xmm0);
1708 __ cvttsd2siq(smi_result, xmm0); 1708 __ cvttsd2siq(smi_result, xmm0);
1709 // Check if conversion was successful by converting back and 1709 // Check if conversion was successful by converting back and
1710 // comparing to the original double's bits. 1710 // comparing to the original double's bits.
1711 __ cvtlsi2sd(xmm1, smi_result); 1711 __ cvtlsi2sd(xmm1, smi_result);
1712 __ movq(kScratchRegister, xmm1); 1712 __ movq(kScratchRegister, xmm1);
1713 __ cmpq(scratch2, kScratchRegister); 1713 __ cmpq(scratch2, kScratchRegister);
1714 __ j(not_equal, on_not_smis); 1714 __ j(not_equal, on_not_smis);
1715 __ Integer32ToSmi(first, smi_result); 1715 __ Integer32ToSmi(first, smi_result);
1716 1716
1717 __ bind(&check_second);
1718 __ JumpIfSmi(second, (on_success != NULL) ? on_success : &done); 1717 __ JumpIfSmi(second, (on_success != NULL) ? on_success : &done);
1719 __ bind(&first_smi); 1718 __ bind(&first_smi);
1720 if (FLAG_debug_code) { 1719 if (FLAG_debug_code) {
1721 // Second should be non-smi if we get here. 1720 // Second should be non-smi if we get here.
1722 __ AbortIfSmi(second); 1721 __ AbortIfSmi(second);
1723 } 1722 }
1724 __ cmpq(FieldOperand(second, HeapObject::kMapOffset), heap_number_map); 1723 __ cmpq(FieldOperand(second, HeapObject::kMapOffset), heap_number_map);
1725 __ j(not_equal, on_not_smis); 1724 __ j(not_equal, on_not_smis);
1726 // Convert second to smi, if possible. 1725 // Convert second to smi, if possible.
1727 __ movsd(xmm0, FieldOperand(second, HeapNumber::kValueOffset)); 1726 __ movsd(xmm0, FieldOperand(second, HeapNumber::kValueOffset));
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1778 // Optimized version of pow if exponent is a smi. 1777 // Optimized version of pow if exponent is a smi.
1779 // xmm0 contains the base. 1778 // xmm0 contains the base.
1780 __ bind(&powi); 1779 __ bind(&powi);
1781 __ SmiToInteger32(rax, rax); 1780 __ SmiToInteger32(rax, rax);
1782 1781
1783 // Save exponent in base as we need to check if exponent is negative later. 1782 // Save exponent in base as we need to check if exponent is negative later.
1784 // We know that base and exponent are in different registers. 1783 // We know that base and exponent are in different registers.
1785 __ movq(rdx, rax); 1784 __ movq(rdx, rax);
1786 1785
1787 // Get absolute value of exponent. 1786 // Get absolute value of exponent.
1788 NearLabel no_neg; 1787 Label no_neg;
1789 __ cmpl(rax, Immediate(0)); 1788 __ cmpl(rax, Immediate(0));
1790 __ j(greater_equal, &no_neg); 1789 __ j(greater_equal, &no_neg, Label::kNear);
1791 __ negl(rax); 1790 __ negl(rax);
1792 __ bind(&no_neg); 1791 __ bind(&no_neg);
1793 1792
1794 // Load xmm1 with 1. 1793 // Load xmm1 with 1.
1795 __ movaps(xmm1, xmm3); 1794 __ movaps(xmm1, xmm3);
1796 NearLabel while_true; 1795 Label while_true;
1797 NearLabel no_multiply; 1796 Label no_multiply;
1798 1797
1799 __ bind(&while_true); 1798 __ bind(&while_true);
1800 __ shrl(rax, Immediate(1)); 1799 __ shrl(rax, Immediate(1));
1801 __ j(not_carry, &no_multiply); 1800 __ j(not_carry, &no_multiply, Label::kNear);
1802 __ mulsd(xmm1, xmm0); 1801 __ mulsd(xmm1, xmm0);
1803 __ bind(&no_multiply); 1802 __ bind(&no_multiply);
1804 __ mulsd(xmm0, xmm0); 1803 __ mulsd(xmm0, xmm0);
1805 __ j(not_zero, &while_true); 1804 __ j(not_zero, &while_true);
1806 1805
1807 // Base has the original value of the exponent - if the exponent is 1806 // Base has the original value of the exponent - if the exponent is
1808 // negative return 1/result. 1807 // negative return 1/result.
1809 __ testl(rdx, rdx); 1808 __ testl(rdx, rdx);
1810 __ j(positive, &allocate_return); 1809 __ j(positive, &allocate_return);
1811 // Special case if xmm1 has reached infinity. 1810 // Special case if xmm1 has reached infinity.
(...skipping 10 matching lines...) Expand all
1822 __ bind(&exponent_nonsmi); 1821 __ bind(&exponent_nonsmi);
1823 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 1822 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
1824 Heap::kHeapNumberMapRootIndex); 1823 Heap::kHeapNumberMapRootIndex);
1825 __ j(not_equal, &call_runtime); 1824 __ j(not_equal, &call_runtime);
1826 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); 1825 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
1827 // Test if exponent is nan. 1826 // Test if exponent is nan.
1828 __ ucomisd(xmm1, xmm1); 1827 __ ucomisd(xmm1, xmm1);
1829 __ j(parity_even, &call_runtime); 1828 __ j(parity_even, &call_runtime);
1830 1829
1831 NearLabel base_not_smi; 1830 NearLabel base_not_smi;
1832 NearLabel handle_special_cases; 1831 Label handle_special_cases;
1833 __ JumpIfNotSmi(rdx, &base_not_smi); 1832 __ JumpIfNotSmi(rdx, &base_not_smi);
1834 __ SmiToInteger32(rdx, rdx); 1833 __ SmiToInteger32(rdx, rdx);
1835 __ cvtlsi2sd(xmm0, rdx); 1834 __ cvtlsi2sd(xmm0, rdx);
1836 __ jmp(&handle_special_cases); 1835 __ jmp(&handle_special_cases, Label::kNear);
1837 1836
1838 __ bind(&base_not_smi); 1837 __ bind(&base_not_smi);
1839 __ CompareRoot(FieldOperand(rdx, HeapObject::kMapOffset), 1838 __ CompareRoot(FieldOperand(rdx, HeapObject::kMapOffset),
1840 Heap::kHeapNumberMapRootIndex); 1839 Heap::kHeapNumberMapRootIndex);
1841 __ j(not_equal, &call_runtime); 1840 __ j(not_equal, &call_runtime);
1842 __ movl(rcx, FieldOperand(rdx, HeapNumber::kExponentOffset)); 1841 __ movl(rcx, FieldOperand(rdx, HeapNumber::kExponentOffset));
1843 __ andl(rcx, Immediate(HeapNumber::kExponentMask)); 1842 __ andl(rcx, Immediate(HeapNumber::kExponentMask));
1844 __ cmpl(rcx, Immediate(HeapNumber::kExponentMask)); 1843 __ cmpl(rcx, Immediate(HeapNumber::kExponentMask));
1845 // base is NaN or +/-Infinity 1844 // base is NaN or +/-Infinity
1846 __ j(greater_equal, &call_runtime); 1845 __ j(greater_equal, &call_runtime);
1847 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); 1846 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
1848 1847
1849 // base is in xmm0 and exponent is in xmm1. 1848 // base is in xmm0 and exponent is in xmm1.
1850 __ bind(&handle_special_cases); 1849 __ bind(&handle_special_cases);
1851 NearLabel not_minus_half; 1850 Label not_minus_half;
1852 // Test for -0.5. 1851 // Test for -0.5.
1853 // Load xmm2 with -0.5. 1852 // Load xmm2 with -0.5.
1854 __ movq(rcx, V8_UINT64_C(0xBFE0000000000000), RelocInfo::NONE); 1853 __ movq(rcx, V8_UINT64_C(0xBFE0000000000000), RelocInfo::NONE);
1855 __ movq(xmm2, rcx); 1854 __ movq(xmm2, rcx);
1856 // xmm2 now has -0.5. 1855 // xmm2 now has -0.5.
1857 __ ucomisd(xmm2, xmm1); 1856 __ ucomisd(xmm2, xmm1);
1858 __ j(not_equal, &not_minus_half); 1857 __ j(not_equal, &not_minus_half, Label::kNear);
1859 1858
1860 // Calculates reciprocal of square root. 1859 // Calculates reciprocal of square root.
1861 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. 1860 // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
1862 __ xorps(xmm1, xmm1); 1861 __ xorps(xmm1, xmm1);
1863 __ addsd(xmm1, xmm0); 1862 __ addsd(xmm1, xmm0);
1864 __ sqrtsd(xmm1, xmm1); 1863 __ sqrtsd(xmm1, xmm1);
1865 __ divsd(xmm3, xmm1); 1864 __ divsd(xmm3, xmm1);
1866 __ movaps(xmm1, xmm3); 1865 __ movaps(xmm1, xmm3);
1867 __ jmp(&allocate_return); 1866 __ jmp(&allocate_return);
1868 1867
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
2167 // Check that the last match info has space for the capture registers and the 2166 // Check that the last match info has space for the capture registers and the
2168 // additional information. Ensure no overflow in add. 2167 // additional information. Ensure no overflow in add.
2169 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); 2168 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset);
2170 __ SmiToInteger32(rdi, FieldOperand(rbx, FixedArray::kLengthOffset)); 2169 __ SmiToInteger32(rdi, FieldOperand(rbx, FixedArray::kLengthOffset));
2171 __ addl(rdx, Immediate(RegExpImpl::kLastMatchOverhead)); 2170 __ addl(rdx, Immediate(RegExpImpl::kLastMatchOverhead));
2172 __ cmpl(rdx, rdi); 2171 __ cmpl(rdx, rdi);
2173 __ j(greater, &runtime); 2172 __ j(greater, &runtime);
2174 2173
2175 // rax: RegExp data (FixedArray) 2174 // rax: RegExp data (FixedArray)
2176 // Check the representation and encoding of the subject string. 2175 // Check the representation and encoding of the subject string.
2177 NearLabel seq_ascii_string, seq_two_byte_string, check_code; 2176 Label seq_ascii_string, seq_two_byte_string, check_code;
2178 __ movq(rdi, Operand(rsp, kSubjectOffset)); 2177 __ movq(rdi, Operand(rsp, kSubjectOffset));
2179 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); 2178 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
2180 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 2179 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
2181 // First check for flat two byte string. 2180 // First check for flat two byte string.
2182 __ andb(rbx, Immediate( 2181 __ andb(rbx, Immediate(
2183 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask)); 2182 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask));
2184 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); 2183 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
2185 __ j(zero, &seq_two_byte_string); 2184 __ j(zero, &seq_two_byte_string, Label::kNear);
2186 // Any other flat string must be a flat ascii string. 2185 // Any other flat string must be a flat ascii string.
2187 __ testb(rbx, Immediate(kIsNotStringMask | kStringRepresentationMask)); 2186 __ testb(rbx, Immediate(kIsNotStringMask | kStringRepresentationMask));
2188 __ j(zero, &seq_ascii_string); 2187 __ j(zero, &seq_ascii_string, Label::kNear);
2189 2188
2190 // Check for flat cons string. 2189 // Check for flat cons string.
2191 // A flat cons string is a cons string where the second part is the empty 2190 // A flat cons string is a cons string where the second part is the empty
2192 // string. In that case the subject string is just the first part of the cons 2191 // string. In that case the subject string is just the first part of the cons
2193 // string. Also in this case the first part of the cons string is known to be 2192 // string. Also in this case the first part of the cons string is known to be
2194 // a sequential string or an external string. 2193 // a sequential string or an external string.
2195 STATIC_ASSERT(kExternalStringTag !=0); 2194 STATIC_ASSERT(kExternalStringTag !=0);
2196 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0); 2195 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0);
2197 __ testb(rbx, Immediate(kIsNotStringMask | kExternalStringTag)); 2196 __ testb(rbx, Immediate(kIsNotStringMask | kExternalStringTag));
2198 __ j(not_zero, &runtime); 2197 __ j(not_zero, &runtime);
2199 // String is a cons string. 2198 // String is a cons string.
2200 __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset), 2199 __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset),
2201 Heap::kEmptyStringRootIndex); 2200 Heap::kEmptyStringRootIndex);
2202 __ j(not_equal, &runtime); 2201 __ j(not_equal, &runtime);
2203 __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); 2202 __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset));
2204 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); 2203 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
2205 // String is a cons string with empty second part. 2204 // String is a cons string with empty second part.
2206 // rdi: first part of cons string. 2205 // rdi: first part of cons string.
2207 // rbx: map of first part of cons string. 2206 // rbx: map of first part of cons string.
2208 // Is first part a flat two byte string? 2207 // Is first part a flat two byte string?
2209 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), 2208 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset),
2210 Immediate(kStringRepresentationMask | kStringEncodingMask)); 2209 Immediate(kStringRepresentationMask | kStringEncodingMask));
2211 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); 2210 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
2212 __ j(zero, &seq_two_byte_string); 2211 __ j(zero, &seq_two_byte_string, Label::kNear);
2213 // Any other flat string must be ascii. 2212 // Any other flat string must be ascii.
2214 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), 2213 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset),
2215 Immediate(kStringRepresentationMask)); 2214 Immediate(kStringRepresentationMask));
2216 __ j(not_zero, &runtime); 2215 __ j(not_zero, &runtime);
2217 2216
2218 __ bind(&seq_ascii_string); 2217 __ bind(&seq_ascii_string);
2219 // rdi: subject string (sequential ascii) 2218 // rdi: subject string (sequential ascii)
2220 // rax: RegExp data (FixedArray) 2219 // rax: RegExp data (FixedArray)
2221 __ movq(r11, FieldOperand(rax, JSRegExp::kDataAsciiCodeOffset)); 2220 __ movq(r11, FieldOperand(rax, JSRegExp::kDataAsciiCodeOffset));
2222 __ Set(rcx, 1); // Type is ascii. 2221 __ Set(rcx, 1); // Type is ascii.
2223 __ jmp(&check_code); 2222 __ jmp(&check_code, Label::kNear);
2224 2223
2225 __ bind(&seq_two_byte_string); 2224 __ bind(&seq_two_byte_string);
2226 // rdi: subject string (flat two-byte) 2225 // rdi: subject string (flat two-byte)
2227 // rax: RegExp data (FixedArray) 2226 // rax: RegExp data (FixedArray)
2228 __ movq(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); 2227 __ movq(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset));
2229 __ Set(rcx, 0); // Type is two byte. 2228 __ Set(rcx, 0); // Type is two byte.
2230 2229
2231 __ bind(&check_code); 2230 __ bind(&check_code);
2232 // Check that the irregexp code has been generated for the actual string 2231 // Check that the irregexp code has been generated for the actual string
2233 // encoding. If it has, the field contains a code object otherwise it contains 2232 // encoding. If it has, the field contains a code object otherwise it contains
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
2299 #endif 2298 #endif
2300 2299
2301 // Keep track on aliasing between argX defined above and the registers used. 2300 // Keep track on aliasing between argX defined above and the registers used.
2302 // rdi: subject string 2301 // rdi: subject string
2303 // rbx: previous index 2302 // rbx: previous index
2304 // rcx: encoding of subject string (1 if ascii 0 if two_byte); 2303 // rcx: encoding of subject string (1 if ascii 0 if two_byte);
2305 // r11: code 2304 // r11: code
2306 2305
2307 // Argument 4: End of string data 2306 // Argument 4: End of string data
2308 // Argument 3: Start of string data 2307 // Argument 3: Start of string data
2309 NearLabel setup_two_byte, setup_rest; 2308 Label setup_two_byte, setup_rest;
2310 __ testb(rcx, rcx); // Last use of rcx as encoding of subject string. 2309 __ testb(rcx, rcx); // Last use of rcx as encoding of subject string.
2311 __ j(zero, &setup_two_byte); 2310 __ j(zero, &setup_two_byte, Label::kNear);
2312 __ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset)); 2311 __ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset));
2313 __ lea(arg4, FieldOperand(rdi, rcx, times_1, SeqAsciiString::kHeaderSize)); 2312 __ lea(arg4, FieldOperand(rdi, rcx, times_1, SeqAsciiString::kHeaderSize));
2314 __ lea(arg3, FieldOperand(rdi, rbx, times_1, SeqAsciiString::kHeaderSize)); 2313 __ lea(arg3, FieldOperand(rdi, rbx, times_1, SeqAsciiString::kHeaderSize));
2315 __ jmp(&setup_rest); 2314 __ jmp(&setup_rest, Label::kNear);
2316 __ bind(&setup_two_byte); 2315 __ bind(&setup_two_byte);
2317 __ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset)); 2316 __ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset));
2318 __ lea(arg4, FieldOperand(rdi, rcx, times_2, SeqTwoByteString::kHeaderSize)); 2317 __ lea(arg4, FieldOperand(rdi, rcx, times_2, SeqTwoByteString::kHeaderSize));
2319 __ lea(arg3, FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize)); 2318 __ lea(arg3, FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize));
2320 2319
2321 __ bind(&setup_rest); 2320 __ bind(&setup_rest);
2322 // Argument 2: Previous index. 2321 // Argument 2: Previous index.
2323 __ movq(arg2, rbx); 2322 __ movq(arg2, rbx);
2324 2323
2325 // Argument 1: Subject string. 2324 // Argument 1: Subject string.
2326 #ifdef _WIN64 2325 #ifdef _WIN64
2327 __ movq(arg1, rdi); 2326 __ movq(arg1, rdi);
2328 #else 2327 #else
2329 // Already there in AMD64 calling convention. 2328 // Already there in AMD64 calling convention.
2330 ASSERT(arg1.is(rdi)); 2329 ASSERT(arg1.is(rdi));
2331 #endif 2330 #endif
2332 2331
2333 // Locate the code entry and call it. 2332 // Locate the code entry and call it.
2334 __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag)); 2333 __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag));
2335 __ call(r11); 2334 __ call(r11);
2336 2335
2337 __ LeaveApiExitFrame(); 2336 __ LeaveApiExitFrame();
2338 2337
2339 // Check the result. 2338 // Check the result.
2340 NearLabel success; 2339 Label success;
2341 Label exception; 2340 Label exception;
2342 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::SUCCESS)); 2341 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::SUCCESS));
2343 __ j(equal, &success); 2342 __ j(equal, &success, Label::kNear);
2344 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION)); 2343 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION));
2345 __ j(equal, &exception); 2344 __ j(equal, &exception);
2346 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE)); 2345 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE));
2347 // If none of the above, it can only be retry. 2346 // If none of the above, it can only be retry.
2348 // Handle that in the runtime system. 2347 // Handle that in the runtime system.
2349 __ j(not_equal, &runtime); 2348 __ j(not_equal, &runtime);
2350 2349
2351 // For failure return null. 2350 // For failure return null.
2352 __ LoadRoot(rax, Heap::kNullValueRootIndex); 2351 __ LoadRoot(rax, Heap::kNullValueRootIndex);
2353 __ ret(4 * kPointerSize); 2352 __ ret(4 * kPointerSize);
(...skipping 28 matching lines...) Expand all
2382 __ movq(rcx, rbx); 2381 __ movq(rcx, rbx);
2383 __ RecordWrite(rcx, RegExpImpl::kLastInputOffset, rax, rdi); 2382 __ RecordWrite(rcx, RegExpImpl::kLastInputOffset, rax, rdi);
2384 2383
2385 // Get the static offsets vector filled by the native regexp code. 2384 // Get the static offsets vector filled by the native regexp code.
2386 __ LoadAddress(rcx, 2385 __ LoadAddress(rcx,
2387 ExternalReference::address_of_static_offsets_vector(isolate)); 2386 ExternalReference::address_of_static_offsets_vector(isolate));
2388 2387
2389 // rbx: last_match_info backing store (FixedArray) 2388 // rbx: last_match_info backing store (FixedArray)
2390 // rcx: offsets vector 2389 // rcx: offsets vector
2391 // rdx: number of capture registers 2390 // rdx: number of capture registers
2392 NearLabel next_capture, done; 2391 Label next_capture, done;
2393 // Capture register counter starts from number of capture registers and 2392 // Capture register counter starts from number of capture registers and
2394 // counts down until wraping after zero. 2393 // counts down until wraping after zero.
2395 __ bind(&next_capture); 2394 __ bind(&next_capture);
2396 __ subq(rdx, Immediate(1)); 2395 __ subq(rdx, Immediate(1));
2397 __ j(negative, &done); 2396 __ j(negative, &done, Label::kNear);
2398 // Read the value from the static offsets vector buffer and make it a smi. 2397 // Read the value from the static offsets vector buffer and make it a smi.
2399 __ movl(rdi, Operand(rcx, rdx, times_int_size, 0)); 2398 __ movl(rdi, Operand(rcx, rdx, times_int_size, 0));
2400 __ Integer32ToSmi(rdi, rdi); 2399 __ Integer32ToSmi(rdi, rdi);
2401 // Store the smi value in the last match info. 2400 // Store the smi value in the last match info.
2402 __ movq(FieldOperand(rbx, 2401 __ movq(FieldOperand(rbx,
2403 rdx, 2402 rdx,
2404 times_pointer_size, 2403 times_pointer_size,
2405 RegExpImpl::kFirstCaptureOffset), 2404 RegExpImpl::kFirstCaptureOffset),
2406 rdi); 2405 rdi);
2407 __ jmp(&next_capture); 2406 __ jmp(&next_capture);
(...skipping 12 matching lines...) Expand all
2420 Isolate::k_pending_exception_address, isolate); 2419 Isolate::k_pending_exception_address, isolate);
2421 Operand pending_exception_operand = 2420 Operand pending_exception_operand =
2422 masm->ExternalOperand(pending_exception_address, rbx); 2421 masm->ExternalOperand(pending_exception_address, rbx);
2423 __ movq(rax, pending_exception_operand); 2422 __ movq(rax, pending_exception_operand);
2424 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); 2423 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
2425 __ cmpq(rax, rdx); 2424 __ cmpq(rax, rdx);
2426 __ j(equal, &runtime); 2425 __ j(equal, &runtime);
2427 __ movq(pending_exception_operand, rdx); 2426 __ movq(pending_exception_operand, rdx);
2428 2427
2429 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); 2428 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex);
2430 NearLabel termination_exception; 2429 Label termination_exception;
2431 __ j(equal, &termination_exception); 2430 __ j(equal, &termination_exception, Label::kNear);
2432 __ Throw(rax); 2431 __ Throw(rax);
2433 2432
2434 __ bind(&termination_exception); 2433 __ bind(&termination_exception);
2435 __ ThrowUncatchable(TERMINATION, rax); 2434 __ ThrowUncatchable(TERMINATION, rax);
2436 2435
2437 // Do the runtime call to execute the regexp. 2436 // Do the runtime call to execute the regexp.
2438 __ bind(&runtime); 2437 __ bind(&runtime);
2439 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); 2438 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
2440 #endif // V8_INTERPRETED_REGEXP 2439 #endif // V8_INTERPRETED_REGEXP
2441 } 2440 }
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
2664 __ bind(&ok); 2663 __ bind(&ok);
2665 } 2664 }
2666 2665
2667 // The compare stub returns a positive, negative, or zero 64-bit integer 2666 // The compare stub returns a positive, negative, or zero 64-bit integer
2668 // value in rax, corresponding to result of comparing the two inputs. 2667 // value in rax, corresponding to result of comparing the two inputs.
2669 // NOTICE! This code is only reached after a smi-fast-case check, so 2668 // NOTICE! This code is only reached after a smi-fast-case check, so
2670 // it is certain that at least one operand isn't a smi. 2669 // it is certain that at least one operand isn't a smi.
2671 2670
2672 // Two identical objects are equal unless they are both NaN or undefined. 2671 // Two identical objects are equal unless they are both NaN or undefined.
2673 { 2672 {
2674 NearLabel not_identical; 2673 Label not_identical;
2675 __ cmpq(rax, rdx); 2674 __ cmpq(rax, rdx);
2676 __ j(not_equal, &not_identical); 2675 __ j(not_equal, &not_identical, Label::kNear);
2677 2676
2678 if (cc_ != equal) { 2677 if (cc_ != equal) {
2679 // Check for undefined. undefined OP undefined is false even though 2678 // Check for undefined. undefined OP undefined is false even though
2680 // undefined == undefined. 2679 // undefined == undefined.
2681 NearLabel check_for_nan; 2680 Label check_for_nan;
2682 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); 2681 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex);
2683 __ j(not_equal, &check_for_nan); 2682 __ j(not_equal, &check_for_nan, Label::kNear);
2684 __ Set(rax, NegativeComparisonResult(cc_)); 2683 __ Set(rax, NegativeComparisonResult(cc_));
2685 __ ret(0); 2684 __ ret(0);
2686 __ bind(&check_for_nan); 2685 __ bind(&check_for_nan);
2687 } 2686 }
2688 2687
2689 // Test for NaN. Sadly, we can't just compare to FACTORY->nan_value(), 2688 // Test for NaN. Sadly, we can't just compare to FACTORY->nan_value(),
2690 // so we do the second best thing - test it ourselves. 2689 // so we do the second best thing - test it ourselves.
2691 // Note: if cc_ != equal, never_nan_nan_ is not used. 2690 // Note: if cc_ != equal, never_nan_nan_ is not used.
2692 // We cannot set rax to EQUAL until just before return because 2691 // We cannot set rax to EQUAL until just before return because
2693 // rax must be unchanged on jump to not_identical. 2692 // rax must be unchanged on jump to not_identical.
2694 if (never_nan_nan_ && (cc_ == equal)) { 2693 if (never_nan_nan_ && (cc_ == equal)) {
2695 __ Set(rax, EQUAL); 2694 __ Set(rax, EQUAL);
2696 __ ret(0); 2695 __ ret(0);
2697 } else { 2696 } else {
2698 NearLabel heap_number; 2697 Label heap_number;
2699 // If it's not a heap number, then return equal for (in)equality operator. 2698 // If it's not a heap number, then return equal for (in)equality operator.
2700 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), 2699 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
2701 factory->heap_number_map()); 2700 factory->heap_number_map());
2702 __ j(equal, &heap_number); 2701 __ j(equal, &heap_number, Label::kNear);
2703 if (cc_ != equal) { 2702 if (cc_ != equal) {
2704 // Call runtime on identical JSObjects. Otherwise return equal. 2703 // Call runtime on identical JSObjects. Otherwise return equal.
2705 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx); 2704 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx);
2706 __ j(above_equal, &not_identical); 2705 __ j(above_equal, &not_identical, Label::kNear);
2707 } 2706 }
2708 __ Set(rax, EQUAL); 2707 __ Set(rax, EQUAL);
2709 __ ret(0); 2708 __ ret(0);
2710 2709
2711 __ bind(&heap_number); 2710 __ bind(&heap_number);
2712 // It is a heap number, so return equal if it's not NaN. 2711 // It is a heap number, so return equal if it's not NaN.
2713 // For NaN, return 1 for every condition except greater and 2712 // For NaN, return 1 for every condition except greater and
2714 // greater-equal. Return -1 for them, so the comparison yields 2713 // greater-equal. Return -1 for them, so the comparison yields
2715 // false for all conditions except not-equal. 2714 // false for all conditions except not-equal.
2716 __ Set(rax, EQUAL); 2715 __ Set(rax, EQUAL);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2752 2751
2753 __ bind(&not_smis); 2752 __ bind(&not_smis);
2754 } 2753 }
2755 2754
2756 // If either operand is a JSObject or an oddball value, then they are not 2755 // If either operand is a JSObject or an oddball value, then they are not
2757 // equal since their pointers are different 2756 // equal since their pointers are different
2758 // There is no test for undetectability in strict equality. 2757 // There is no test for undetectability in strict equality.
2759 2758
2760 // If the first object is a JS object, we have done pointer comparison. 2759 // If the first object is a JS object, we have done pointer comparison.
2761 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 2760 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
2762 NearLabel first_non_object; 2761 Label first_non_object;
2763 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx); 2762 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx);
2764 __ j(below, &first_non_object); 2763 __ j(below, &first_non_object, Label::kNear);
2765 // Return non-zero (eax (not rax) is not zero) 2764 // Return non-zero (eax (not rax) is not zero)
2766 Label return_not_equal; 2765 Label return_not_equal;
2767 STATIC_ASSERT(kHeapObjectTag != 0); 2766 STATIC_ASSERT(kHeapObjectTag != 0);
2768 __ bind(&return_not_equal); 2767 __ bind(&return_not_equal);
2769 __ ret(0); 2768 __ ret(0);
2770 2769
2771 __ bind(&first_non_object); 2770 __ bind(&first_non_object);
2772 // Check for oddballs: true, false, null, undefined. 2771 // Check for oddballs: true, false, null, undefined.
2773 __ CmpInstanceType(rcx, ODDBALL_TYPE); 2772 __ CmpInstanceType(rcx, ODDBALL_TYPE);
2774 __ j(equal, &return_not_equal); 2773 __ j(equal, &return_not_equal);
2775 2774
2776 __ CmpObjectType(rdx, FIRST_JS_OBJECT_TYPE, rcx); 2775 __ CmpObjectType(rdx, FIRST_JS_OBJECT_TYPE, rcx);
2777 __ j(above_equal, &return_not_equal); 2776 __ j(above_equal, &return_not_equal);
2778 2777
2779 // Check for oddballs: true, false, null, undefined. 2778 // Check for oddballs: true, false, null, undefined.
2780 __ CmpInstanceType(rcx, ODDBALL_TYPE); 2779 __ CmpInstanceType(rcx, ODDBALL_TYPE);
2781 __ j(equal, &return_not_equal); 2780 __ j(equal, &return_not_equal);
2782 2781
2783 // Fall through to the general case. 2782 // Fall through to the general case.
2784 } 2783 }
2785 __ bind(&slow); 2784 __ bind(&slow);
2786 } 2785 }
2787 2786
2788 // Generate the number comparison code. 2787 // Generate the number comparison code.
2789 if (include_number_compare_) { 2788 if (include_number_compare_) {
2790 Label non_number_comparison; 2789 Label non_number_comparison;
2791 NearLabel unordered; 2790 Label unordered;
2792 FloatingPointHelper::LoadSSE2UnknownOperands(masm, &non_number_comparison); 2791 FloatingPointHelper::LoadSSE2UnknownOperands(masm, &non_number_comparison);
2793 __ xorl(rax, rax); 2792 __ xorl(rax, rax);
2794 __ xorl(rcx, rcx); 2793 __ xorl(rcx, rcx);
2795 __ ucomisd(xmm0, xmm1); 2794 __ ucomisd(xmm0, xmm1);
2796 2795
2797 // Don't base result on EFLAGS when a NaN is involved. 2796 // Don't base result on EFLAGS when a NaN is involved.
2798 __ j(parity_even, &unordered); 2797 __ j(parity_even, &unordered, Label::kNear);
2799 // Return a result of -1, 0, or 1, based on EFLAGS. 2798 // Return a result of -1, 0, or 1, based on EFLAGS.
2800 __ setcc(above, rax); 2799 __ setcc(above, rax);
2801 __ setcc(below, rcx); 2800 __ setcc(below, rcx);
2802 __ subq(rax, rcx); 2801 __ subq(rax, rcx);
2803 __ ret(0); 2802 __ ret(0);
2804 2803
2805 // If one of the numbers was NaN, then the result is always false. 2804 // If one of the numbers was NaN, then the result is always false.
2806 // The cc is never not-equal. 2805 // The cc is never not-equal.
2807 __ bind(&unordered); 2806 __ bind(&unordered);
2808 ASSERT(cc_ != not_equal); 2807 ASSERT(cc_ != not_equal);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2853 2852
2854 #ifdef DEBUG 2853 #ifdef DEBUG
2855 __ Abort("Unexpected fall-through from string comparison"); 2854 __ Abort("Unexpected fall-through from string comparison");
2856 #endif 2855 #endif
2857 2856
2858 __ bind(&check_unequal_objects); 2857 __ bind(&check_unequal_objects);
2859 if (cc_ == equal && !strict_) { 2858 if (cc_ == equal && !strict_) {
2860 // Not strict equality. Objects are unequal if 2859 // Not strict equality. Objects are unequal if
2861 // they are both JSObjects and not undetectable, 2860 // they are both JSObjects and not undetectable,
2862 // and their pointers are different. 2861 // and their pointers are different.
2863 NearLabel not_both_objects, return_unequal; 2862 Label not_both_objects, return_unequal;
2864 // At most one is a smi, so we can test for smi by adding the two. 2863 // At most one is a smi, so we can test for smi by adding the two.
2865 // A smi plus a heap object has the low bit set, a heap object plus 2864 // A smi plus a heap object has the low bit set, a heap object plus
2866 // a heap object has the low bit clear. 2865 // a heap object has the low bit clear.
2867 STATIC_ASSERT(kSmiTag == 0); 2866 STATIC_ASSERT(kSmiTag == 0);
2868 STATIC_ASSERT(kSmiTagMask == 1); 2867 STATIC_ASSERT(kSmiTagMask == 1);
2869 __ lea(rcx, Operand(rax, rdx, times_1, 0)); 2868 __ lea(rcx, Operand(rax, rdx, times_1, 0));
2870 __ testb(rcx, Immediate(kSmiTagMask)); 2869 __ testb(rcx, Immediate(kSmiTagMask));
2871 __ j(not_zero, &not_both_objects); 2870 __ j(not_zero, &not_both_objects, Label::kNear);
2872 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); 2871 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx);
2873 __ j(below, &not_both_objects); 2872 __ j(below, &not_both_objects, Label::kNear);
2874 __ CmpObjectType(rdx, FIRST_JS_OBJECT_TYPE, rcx); 2873 __ CmpObjectType(rdx, FIRST_JS_OBJECT_TYPE, rcx);
2875 __ j(below, &not_both_objects); 2874 __ j(below, &not_both_objects, Label::kNear);
2876 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2875 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2877 Immediate(1 << Map::kIsUndetectable)); 2876 Immediate(1 << Map::kIsUndetectable));
2878 __ j(zero, &return_unequal); 2877 __ j(zero, &return_unequal, Label::kNear);
2879 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), 2878 __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
2880 Immediate(1 << Map::kIsUndetectable)); 2879 Immediate(1 << Map::kIsUndetectable));
2881 __ j(zero, &return_unequal); 2880 __ j(zero, &return_unequal, Label::kNear);
2882 // The objects are both undetectable, so they both compare as the value 2881 // The objects are both undetectable, so they both compare as the value
2883 // undefined, and are equal. 2882 // undefined, and are equal.
2884 __ Set(rax, EQUAL); 2883 __ Set(rax, EQUAL);
2885 __ bind(&return_unequal); 2884 __ bind(&return_unequal);
2886 // Return non-equal by returning the non-zero object pointer in rax, 2885 // Return non-equal by returning the non-zero object pointer in rax,
2887 // or return equal if we fell through to here. 2886 // or return equal if we fell through to here.
2888 __ ret(0); 2887 __ ret(0);
2889 __ bind(&not_both_objects); 2888 __ bind(&not_both_objects);
2890 } 2889 }
2891 2890
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
3101 __ testl(rcx, Immediate(kFailureTagMask)); 3100 __ testl(rcx, Immediate(kFailureTagMask));
3102 __ j(zero, &failure_returned); 3101 __ j(zero, &failure_returned);
3103 3102
3104 // Exit the JavaScript to C++ exit frame. 3103 // Exit the JavaScript to C++ exit frame.
3105 __ LeaveExitFrame(save_doubles_); 3104 __ LeaveExitFrame(save_doubles_);
3106 __ ret(0); 3105 __ ret(0);
3107 3106
3108 // Handling of failure. 3107 // Handling of failure.
3109 __ bind(&failure_returned); 3108 __ bind(&failure_returned);
3110 3109
3111 NearLabel retry; 3110 Label retry;
3112 // If the returned exception is RETRY_AFTER_GC continue at retry label 3111 // If the returned exception is RETRY_AFTER_GC continue at retry label
3113 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); 3112 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
3114 __ testl(rax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); 3113 __ testl(rax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
3115 __ j(zero, &retry); 3114 __ j(zero, &retry, Label::kNear);
3116 3115
3117 // Special handling of out of memory exceptions. 3116 // Special handling of out of memory exceptions.
3118 __ movq(kScratchRegister, Failure::OutOfMemoryException(), RelocInfo::NONE); 3117 __ movq(kScratchRegister, Failure::OutOfMemoryException(), RelocInfo::NONE);
3119 __ cmpq(rax, kScratchRegister); 3118 __ cmpq(rax, kScratchRegister);
3120 __ j(equal, throw_out_of_memory_exception); 3119 __ j(equal, throw_out_of_memory_exception);
3121 3120
3122 // Retrieve the pending exception and clear the variable. 3121 // Retrieve the pending exception and clear the variable.
3123 ExternalReference pending_exception_address( 3122 ExternalReference pending_exception_address(
3124 Isolate::k_pending_exception_address, masm->isolate()); 3123 Isolate::k_pending_exception_address, masm->isolate());
3125 Operand pending_exception_operand = 3124 Operand pending_exception_operand =
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
3406 __ j(above, &slow); 3405 __ j(above, &slow);
3407 3406
3408 // Get the prototype of the function. 3407 // Get the prototype of the function.
3409 __ movq(rdx, Operand(rsp, 1 * kPointerSize + extra_stack_space)); 3408 __ movq(rdx, Operand(rsp, 1 * kPointerSize + extra_stack_space));
3410 // rdx is function, rax is map. 3409 // rdx is function, rax is map.
3411 3410
3412 // If there is a call site cache don't look in the global cache, but do the 3411 // If there is a call site cache don't look in the global cache, but do the
3413 // real lookup and update the call site cache. 3412 // real lookup and update the call site cache.
3414 if (!HasCallSiteInlineCheck()) { 3413 if (!HasCallSiteInlineCheck()) {
3415 // Look up the function and the map in the instanceof cache. 3414 // Look up the function and the map in the instanceof cache.
3416 NearLabel miss; 3415 Label miss;
3417 __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); 3416 __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
3418 __ j(not_equal, &miss); 3417 __ j(not_equal, &miss, Label::kNear);
3419 __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex); 3418 __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex);
3420 __ j(not_equal, &miss); 3419 __ j(not_equal, &miss, Label::kNear);
3421 __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); 3420 __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
3422 __ ret(2 * kPointerSize); 3421 __ ret(2 * kPointerSize);
3423 __ bind(&miss); 3422 __ bind(&miss);
3424 } 3423 }
3425 3424
3426 __ TryGetFunctionPrototype(rdx, rbx, &slow); 3425 __ TryGetFunctionPrototype(rdx, rbx, &slow);
3427 3426
3428 // Check that the function prototype is a JS object. 3427 // Check that the function prototype is a JS object.
3429 __ JumpIfSmi(rbx, &slow); 3428 __ JumpIfSmi(rbx, &slow);
3430 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, kScratchRegister); 3429 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, kScratchRegister);
(...skipping 15 matching lines...) Expand all
3446 if (FLAG_debug_code) { 3445 if (FLAG_debug_code) {
3447 __ movl(rdi, Immediate(kWordBeforeMapCheckValue)); 3446 __ movl(rdi, Immediate(kWordBeforeMapCheckValue));
3448 __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi); 3447 __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi);
3449 __ Assert(equal, "InstanceofStub unexpected call site cache (check)."); 3448 __ Assert(equal, "InstanceofStub unexpected call site cache (check).");
3450 } 3449 }
3451 } 3450 }
3452 3451
3453 __ movq(rcx, FieldOperand(rax, Map::kPrototypeOffset)); 3452 __ movq(rcx, FieldOperand(rax, Map::kPrototypeOffset));
3454 3453
3455 // Loop through the prototype chain looking for the function prototype. 3454 // Loop through the prototype chain looking for the function prototype.
3456 NearLabel loop, is_instance, is_not_instance; 3455 Label loop, is_instance, is_not_instance;
3457 __ LoadRoot(kScratchRegister, Heap::kNullValueRootIndex); 3456 __ LoadRoot(kScratchRegister, Heap::kNullValueRootIndex);
3458 __ bind(&loop); 3457 __ bind(&loop);
3459 __ cmpq(rcx, rbx); 3458 __ cmpq(rcx, rbx);
3460 __ j(equal, &is_instance); 3459 __ j(equal, &is_instance, Label::kNear);
3461 __ cmpq(rcx, kScratchRegister); 3460 __ cmpq(rcx, kScratchRegister);
3462 // The code at is_not_instance assumes that kScratchRegister contains a 3461 // The code at is_not_instance assumes that kScratchRegister contains a
3463 // non-zero GCable value (the null object in this case). 3462 // non-zero GCable value (the null object in this case).
3464 __ j(equal, &is_not_instance); 3463 __ j(equal, &is_not_instance, Label::kNear);
3465 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); 3464 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
3466 __ movq(rcx, FieldOperand(rcx, Map::kPrototypeOffset)); 3465 __ movq(rcx, FieldOperand(rcx, Map::kPrototypeOffset));
3467 __ jmp(&loop); 3466 __ jmp(&loop);
3468 3467
3469 __ bind(&is_instance); 3468 __ bind(&is_instance);
3470 if (!HasCallSiteInlineCheck()) { 3469 if (!HasCallSiteInlineCheck()) {
3471 __ xorl(rax, rax); 3470 __ xorl(rax, rax);
3472 // Store bitwise zero in the cache. This is a Smi in GC terms. 3471 // Store bitwise zero in the cache. This is a Smi in GC terms.
3473 STATIC_ASSERT(kSmiTag == 0); 3472 STATIC_ASSERT(kSmiTag == 0);
3474 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); 3473 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
3819 GenerateConvertArgument(masm, 1 * kPointerSize, rdx, rbx, rcx, rdi, 3818 GenerateConvertArgument(masm, 1 * kPointerSize, rdx, rbx, rcx, rdi,
3820 &call_builtin); 3819 &call_builtin);
3821 builtin_id = Builtins::STRING_ADD_LEFT; 3820 builtin_id = Builtins::STRING_ADD_LEFT;
3822 } 3821 }
3823 } 3822 }
3824 3823
3825 // Both arguments are strings. 3824 // Both arguments are strings.
3826 // rax: first string 3825 // rax: first string
3827 // rdx: second string 3826 // rdx: second string
3828 // Check if either of the strings are empty. In that case return the other. 3827 // Check if either of the strings are empty. In that case return the other.
3829 NearLabel second_not_zero_length, both_not_zero_length; 3828 Label second_not_zero_length, both_not_zero_length;
3830 __ movq(rcx, FieldOperand(rdx, String::kLengthOffset)); 3829 __ movq(rcx, FieldOperand(rdx, String::kLengthOffset));
3831 __ SmiTest(rcx); 3830 __ SmiTest(rcx);
3832 __ j(not_zero, &second_not_zero_length); 3831 __ j(not_zero, &second_not_zero_length, Label::kNear);
3833 // Second string is empty, result is first string which is already in rax. 3832 // Second string is empty, result is first string which is already in rax.
3834 Counters* counters = masm->isolate()->counters(); 3833 Counters* counters = masm->isolate()->counters();
3835 __ IncrementCounter(counters->string_add_native(), 1); 3834 __ IncrementCounter(counters->string_add_native(), 1);
3836 __ ret(2 * kPointerSize); 3835 __ ret(2 * kPointerSize);
3837 __ bind(&second_not_zero_length); 3836 __ bind(&second_not_zero_length);
3838 __ movq(rbx, FieldOperand(rax, String::kLengthOffset)); 3837 __ movq(rbx, FieldOperand(rax, String::kLengthOffset));
3839 __ SmiTest(rbx); 3838 __ SmiTest(rbx);
3840 __ j(not_zero, &both_not_zero_length); 3839 __ j(not_zero, &both_not_zero_length, Label::kNear);
3841 // First string is empty, result is second string which is in rdx. 3840 // First string is empty, result is second string which is in rdx.
3842 __ movq(rax, rdx); 3841 __ movq(rax, rdx);
3843 __ IncrementCounter(counters->string_add_native(), 1); 3842 __ IncrementCounter(counters->string_add_native(), 1);
3844 __ ret(2 * kPointerSize); 3843 __ ret(2 * kPointerSize);
3845 3844
3846 // Both strings are non-empty. 3845 // Both strings are non-empty.
3847 // rax: first string 3846 // rax: first string
3848 // rbx: length of first string 3847 // rbx: length of first string
3849 // rcx: length of second string 3848 // rcx: length of second string
3850 // rdx: second string 3849 // rdx: second string
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
4124 bool ascii) { 4123 bool ascii) {
4125 // Copy characters using rep movs of doublewords. Align destination on 4 byte 4124 // Copy characters using rep movs of doublewords. Align destination on 4 byte
4126 // boundary before starting rep movs. Copy remaining characters after running 4125 // boundary before starting rep movs. Copy remaining characters after running
4127 // rep movs. 4126 // rep movs.
4128 // Count is positive int32, dest and src are character pointers. 4127 // Count is positive int32, dest and src are character pointers.
4129 ASSERT(dest.is(rdi)); // rep movs destination 4128 ASSERT(dest.is(rdi)); // rep movs destination
4130 ASSERT(src.is(rsi)); // rep movs source 4129 ASSERT(src.is(rsi)); // rep movs source
4131 ASSERT(count.is(rcx)); // rep movs count 4130 ASSERT(count.is(rcx)); // rep movs count
4132 4131
4133 // Nothing to do for zero characters. 4132 // Nothing to do for zero characters.
4134 NearLabel done; 4133 Label done;
4135 __ testl(count, count); 4134 __ testl(count, count);
4136 __ j(zero, &done); 4135 __ j(zero, &done, Label::kNear);
4137 4136
4138 // Make count the number of bytes to copy. 4137 // Make count the number of bytes to copy.
4139 if (!ascii) { 4138 if (!ascii) {
4140 STATIC_ASSERT(2 == sizeof(uc16)); 4139 STATIC_ASSERT(2 == sizeof(uc16));
4141 __ addl(count, count); 4140 __ addl(count, count);
4142 } 4141 }
4143 4142
4144 // Don't enter the rep movs if there are less than 4 bytes to copy. 4143 // Don't enter the rep movs if there are less than 4 bytes to copy.
4145 NearLabel last_bytes; 4144 Label last_bytes;
4146 __ testl(count, Immediate(~7)); 4145 __ testl(count, Immediate(~7));
4147 __ j(zero, &last_bytes); 4146 __ j(zero, &last_bytes, Label::kNear);
4148 4147
4149 // Copy from edi to esi using rep movs instruction. 4148 // Copy from edi to esi using rep movs instruction.
4150 __ movl(kScratchRegister, count); 4149 __ movl(kScratchRegister, count);
4151 __ shr(count, Immediate(3)); // Number of doublewords to copy. 4150 __ shr(count, Immediate(3)); // Number of doublewords to copy.
4152 __ repmovsq(); 4151 __ repmovsq();
4153 4152
4154 // Find number of bytes left. 4153 // Find number of bytes left.
4155 __ movl(count, kScratchRegister); 4154 __ movl(count, kScratchRegister);
4156 __ and_(count, Immediate(7)); 4155 __ and_(count, Immediate(7));
4157 4156
4158 // Check if there are more bytes to copy. 4157 // Check if there are more bytes to copy.
4159 __ bind(&last_bytes); 4158 __ bind(&last_bytes);
4160 __ testl(count, count); 4159 __ testl(count, count);
4161 __ j(zero, &done); 4160 __ j(zero, &done, Label::kNear);
4162 4161
4163 // Copy remaining characters. 4162 // Copy remaining characters.
4164 Label loop; 4163 Label loop;
4165 __ bind(&loop); 4164 __ bind(&loop);
4166 __ movb(kScratchRegister, Operand(src, 0)); 4165 __ movb(kScratchRegister, Operand(src, 0));
4167 __ movb(Operand(dest, 0), kScratchRegister); 4166 __ movb(Operand(dest, 0), kScratchRegister);
4168 __ incq(src); 4167 __ incq(src);
4169 __ incq(dest); 4168 __ incq(dest);
4170 __ decl(count); 4169 __ decl(count);
4171 __ j(not_zero, &loop); 4170 __ j(not_zero, &loop);
4172 4171
4173 __ bind(&done); 4172 __ bind(&done);
4174 } 4173 }
4175 4174
4176 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, 4175 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
4177 Register c1, 4176 Register c1,
4178 Register c2, 4177 Register c2,
4179 Register scratch1, 4178 Register scratch1,
4180 Register scratch2, 4179 Register scratch2,
4181 Register scratch3, 4180 Register scratch3,
4182 Register scratch4, 4181 Register scratch4,
4183 Label* not_found) { 4182 Label* not_found) {
4184 // Register scratch3 is the general scratch register in this function. 4183 // Register scratch3 is the general scratch register in this function.
4185 Register scratch = scratch3; 4184 Register scratch = scratch3;
4186 4185
4187 // Make sure that both characters are not digits as such strings has a 4186 // Make sure that both characters are not digits as such strings has a
4188 // different hash algorithm. Don't try to look for these in the symbol table. 4187 // different hash algorithm. Don't try to look for these in the symbol table.
4189 NearLabel not_array_index; 4188 Label not_array_index;
4190 __ leal(scratch, Operand(c1, -'0')); 4189 __ leal(scratch, Operand(c1, -'0'));
4191 __ cmpl(scratch, Immediate(static_cast<int>('9' - '0'))); 4190 __ cmpl(scratch, Immediate(static_cast<int>('9' - '0')));
4192 __ j(above, &not_array_index); 4191 __ j(above, &not_array_index, Label::kNear);
4193 __ leal(scratch, Operand(c2, -'0')); 4192 __ leal(scratch, Operand(c2, -'0'));
4194 __ cmpl(scratch, Immediate(static_cast<int>('9' - '0'))); 4193 __ cmpl(scratch, Immediate(static_cast<int>('9' - '0')));
4195 __ j(below_equal, not_found); 4194 __ j(below_equal, not_found);
4196 4195
4197 __ bind(&not_array_index); 4196 __ bind(&not_array_index);
4198 // Calculate the two character string hash. 4197 // Calculate the two character string hash.
4199 Register hash = scratch1; 4198 Register hash = scratch1;
4200 GenerateHashInit(masm, hash, c1, scratch); 4199 GenerateHashInit(masm, hash, c1, scratch);
4201 GenerateHashAddCharacter(masm, hash, c2, scratch); 4200 GenerateHashAddCharacter(masm, hash, c2, scratch);
4202 GenerateHashGetHash(masm, hash, scratch); 4201 GenerateHashGetHash(masm, hash, scratch);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
4244 // Load the entry from the symbol table. 4243 // Load the entry from the symbol table.
4245 Register candidate = scratch; // Scratch register contains candidate. 4244 Register candidate = scratch; // Scratch register contains candidate.
4246 STATIC_ASSERT(SymbolTable::kEntrySize == 1); 4245 STATIC_ASSERT(SymbolTable::kEntrySize == 1);
4247 __ movq(candidate, 4246 __ movq(candidate,
4248 FieldOperand(symbol_table, 4247 FieldOperand(symbol_table,
4249 scratch, 4248 scratch,
4250 times_pointer_size, 4249 times_pointer_size,
4251 SymbolTable::kElementsStartOffset)); 4250 SymbolTable::kElementsStartOffset));
4252 4251
4253 // If entry is undefined no string with this hash can be found. 4252 // If entry is undefined no string with this hash can be found.
4254 NearLabel is_string; 4253 Label is_string;
4255 __ CmpObjectType(candidate, ODDBALL_TYPE, map); 4254 __ CmpObjectType(candidate, ODDBALL_TYPE, map);
4256 __ j(not_equal, &is_string); 4255 __ j(not_equal, &is_string, Label::kNear);
4257 4256
4258 __ CompareRoot(candidate, Heap::kUndefinedValueRootIndex); 4257 __ CompareRoot(candidate, Heap::kUndefinedValueRootIndex);
4259 __ j(equal, not_found); 4258 __ j(equal, not_found);
4260 // Must be null (deleted entry). 4259 // Must be null (deleted entry).
4261 __ jmp(&next_probe[i]); 4260 __ jmp(&next_probe[i]);
4262 4261
4263 __ bind(&is_string); 4262 __ bind(&is_string);
4264 4263
4265 // If length is not 2 the string is not a candidate. 4264 // If length is not 2 the string is not a candidate.
4266 __ SmiCompare(FieldOperand(candidate, String::kLengthOffset), 4265 __ SmiCompare(FieldOperand(candidate, String::kLengthOffset),
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
4567 STATIC_ASSERT(String::kMaxLength < 0x7fffffff); 4566 STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
4568 4567
4569 // Find minimum length and length difference. 4568 // Find minimum length and length difference.
4570 __ movq(scratch1, FieldOperand(left, String::kLengthOffset)); 4569 __ movq(scratch1, FieldOperand(left, String::kLengthOffset));
4571 __ movq(scratch4, scratch1); 4570 __ movq(scratch4, scratch1);
4572 __ SmiSub(scratch4, 4571 __ SmiSub(scratch4,
4573 scratch4, 4572 scratch4,
4574 FieldOperand(right, String::kLengthOffset)); 4573 FieldOperand(right, String::kLengthOffset));
4575 // Register scratch4 now holds left.length - right.length. 4574 // Register scratch4 now holds left.length - right.length.
4576 const Register length_difference = scratch4; 4575 const Register length_difference = scratch4;
4577 NearLabel left_shorter; 4576 Label left_shorter;
4578 __ j(less, &left_shorter); 4577 __ j(less, &left_shorter, Label::kNear);
4579 // The right string isn't longer that the left one. 4578 // The right string isn't longer that the left one.
4580 // Get the right string's length by subtracting the (non-negative) difference 4579 // Get the right string's length by subtracting the (non-negative) difference
4581 // from the left string's length. 4580 // from the left string's length.
4582 __ SmiSub(scratch1, scratch1, length_difference); 4581 __ SmiSub(scratch1, scratch1, length_difference);
4583 __ bind(&left_shorter); 4582 __ bind(&left_shorter);
4584 // Register scratch1 now holds Min(left.length, right.length). 4583 // Register scratch1 now holds Min(left.length, right.length).
4585 const Register min_length = scratch1; 4584 const Register min_length = scratch1;
4586 4585
4587 NearLabel compare_lengths; 4586 Label compare_lengths;
4588 // If min-length is zero, go directly to comparing lengths. 4587 // If min-length is zero, go directly to comparing lengths.
4589 __ SmiTest(min_length); 4588 __ SmiTest(min_length);
4590 __ j(zero, &compare_lengths); 4589 __ j(zero, &compare_lengths, Label::kNear);
4591 4590
4592 __ SmiToInteger32(min_length, min_length); 4591 __ SmiToInteger32(min_length, min_length);
4593 4592
4594 // Registers scratch2 and scratch3 are free. 4593 // Registers scratch2 and scratch3 are free.
4595 NearLabel result_not_equal; 4594 Label result_not_equal;
4596 Label loop; 4595 Label loop;
4597 { 4596 {
4598 // Check characters 0 .. min_length - 1 in a loop. 4597 // Check characters 0 .. min_length - 1 in a loop.
4599 // Use scratch3 as loop index, min_length as limit and scratch2 4598 // Use scratch3 as loop index, min_length as limit and scratch2
4600 // for computation. 4599 // for computation.
4601 const Register index = scratch3; 4600 const Register index = scratch3;
4602 __ Set(index, 0); // Index into strings. 4601 __ Set(index, 0); // Index into strings.
4603 __ bind(&loop); 4602 __ bind(&loop);
4604 // Compare characters. 4603 // Compare characters.
4605 // TODO(lrn): Could we load more than one character at a time? 4604 // TODO(lrn): Could we load more than one character at a time?
4606 __ movb(scratch2, FieldOperand(left, 4605 __ movb(scratch2, FieldOperand(left,
4607 index, 4606 index,
4608 times_1, 4607 times_1,
4609 SeqAsciiString::kHeaderSize)); 4608 SeqAsciiString::kHeaderSize));
4610 // Increment index and use -1 modifier on next load to give 4609 // Increment index and use -1 modifier on next load to give
4611 // the previous load extra time to complete. 4610 // the previous load extra time to complete.
4612 __ addl(index, Immediate(1)); 4611 __ addl(index, Immediate(1));
4613 __ cmpb(scratch2, FieldOperand(right, 4612 __ cmpb(scratch2, FieldOperand(right,
4614 index, 4613 index,
4615 times_1, 4614 times_1,
4616 SeqAsciiString::kHeaderSize - 1)); 4615 SeqAsciiString::kHeaderSize - 1));
4617 __ j(not_equal, &result_not_equal); 4616 __ j(not_equal, &result_not_equal, Label::kNear);
4618 __ cmpl(index, min_length); 4617 __ cmpl(index, min_length);
4619 __ j(not_equal, &loop); 4618 __ j(not_equal, &loop);
4620 } 4619 }
4621 // Completed loop without finding different characters. 4620 // Completed loop without finding different characters.
4622 // Compare lengths (precomputed). 4621 // Compare lengths (precomputed).
4623 __ bind(&compare_lengths); 4622 __ bind(&compare_lengths);
4624 __ SmiTest(length_difference); 4623 __ SmiTest(length_difference);
4625 __ j(not_zero, &result_not_equal); 4624 __ j(not_zero, &result_not_equal, Label::kNear);
4626 4625
4627 // Result is EQUAL. 4626 // Result is EQUAL.
4628 __ Move(rax, Smi::FromInt(EQUAL)); 4627 __ Move(rax, Smi::FromInt(EQUAL));
4629 __ ret(0); 4628 __ ret(0);
4630 4629
4631 NearLabel result_greater; 4630 Label result_greater;
4632 __ bind(&result_not_equal); 4631 __ bind(&result_not_equal);
4633 // Unequal comparison of left to right, either character or length. 4632 // Unequal comparison of left to right, either character or length.
4634 __ j(greater, &result_greater); 4633 __ j(greater, &result_greater, Label::kNear);
4635 4634
4636 // Result is LESS. 4635 // Result is LESS.
4637 __ Move(rax, Smi::FromInt(LESS)); 4636 __ Move(rax, Smi::FromInt(LESS));
4638 __ ret(0); 4637 __ ret(0);
4639 4638
4640 // Result is GREATER. 4639 // Result is GREATER.
4641 __ bind(&result_greater); 4640 __ bind(&result_greater);
4642 __ Move(rax, Smi::FromInt(GREATER)); 4641 __ Move(rax, Smi::FromInt(GREATER));
4643 __ ret(0); 4642 __ ret(0);
4644 } 4643 }
4645 4644
4646 4645
4647 void StringCompareStub::Generate(MacroAssembler* masm) { 4646 void StringCompareStub::Generate(MacroAssembler* masm) {
4648 Label runtime; 4647 Label runtime;
4649 4648
4650 // Stack frame on entry. 4649 // Stack frame on entry.
4651 // rsp[0]: return address 4650 // rsp[0]: return address
4652 // rsp[8]: right string 4651 // rsp[8]: right string
4653 // rsp[16]: left string 4652 // rsp[16]: left string
4654 4653
4655 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // left 4654 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // left
4656 __ movq(rax, Operand(rsp, 1 * kPointerSize)); // right 4655 __ movq(rax, Operand(rsp, 1 * kPointerSize)); // right
4657 4656
4658 // Check for identity. 4657 // Check for identity.
4659 NearLabel not_same; 4658 Label not_same;
4660 __ cmpq(rdx, rax); 4659 __ cmpq(rdx, rax);
4661 __ j(not_equal, &not_same); 4660 __ j(not_equal, &not_same, Label::kNear);
4662 __ Move(rax, Smi::FromInt(EQUAL)); 4661 __ Move(rax, Smi::FromInt(EQUAL));
4663 Counters* counters = masm->isolate()->counters(); 4662 Counters* counters = masm->isolate()->counters();
4664 __ IncrementCounter(counters->string_compare_native(), 1); 4663 __ IncrementCounter(counters->string_compare_native(), 1);
4665 __ ret(2 * kPointerSize); 4664 __ ret(2 * kPointerSize);
4666 4665
4667 __ bind(&not_same); 4666 __ bind(&not_same);
4668 4667
4669 // Check that both are sequential ASCII strings. 4668 // Check that both are sequential ASCII strings.
4670 __ JumpIfNotBothSequentialAsciiStrings(rdx, rax, rcx, rbx, &runtime); 4669 __ JumpIfNotBothSequentialAsciiStrings(rdx, rax, rcx, rbx, &runtime);
4671 4670
(...skipping 14 matching lines...) Expand all
4686 4685
4687 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { 4686 void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
4688 ASSERT(state_ == CompareIC::SMIS); 4687 ASSERT(state_ == CompareIC::SMIS);
4689 NearLabel miss; 4688 NearLabel miss;
4690 __ JumpIfNotBothSmi(rdx, rax, &miss); 4689 __ JumpIfNotBothSmi(rdx, rax, &miss);
4691 4690
4692 if (GetCondition() == equal) { 4691 if (GetCondition() == equal) {
4693 // For equality we do not care about the sign of the result. 4692 // For equality we do not care about the sign of the result.
4694 __ subq(rax, rdx); 4693 __ subq(rax, rdx);
4695 } else { 4694 } else {
4696 NearLabel done; 4695 Label done;
4697 __ subq(rdx, rax); 4696 __ subq(rdx, rax);
4698 __ j(no_overflow, &done); 4697 __ j(no_overflow, &done, Label::kNear);
4699 // Correct sign of result in case of overflow. 4698 // Correct sign of result in case of overflow.
4700 __ SmiNot(rdx, rdx); 4699 __ SmiNot(rdx, rdx);
4701 __ bind(&done); 4700 __ bind(&done);
4702 __ movq(rax, rdx); 4701 __ movq(rax, rdx);
4703 } 4702 }
4704 __ ret(0); 4703 __ ret(0);
4705 4704
4706 __ bind(&miss); 4705 __ bind(&miss);
4707 GenerateMiss(masm); 4706 GenerateMiss(masm);
4708 } 4707 }
4709 4708
4710 4709
4711 void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) { 4710 void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
4712 ASSERT(state_ == CompareIC::HEAP_NUMBERS); 4711 ASSERT(state_ == CompareIC::HEAP_NUMBERS);
4713 4712
4714 NearLabel generic_stub; 4713 Label generic_stub;
4715 NearLabel unordered; 4714 Label unordered;
4716 NearLabel miss; 4715 Label miss;
4717 Condition either_smi = masm->CheckEitherSmi(rax, rdx); 4716 Condition either_smi = masm->CheckEitherSmi(rax, rdx);
4718 __ j(either_smi, &generic_stub); 4717 __ j(either_smi, &generic_stub, Label::kNear);
4719 4718
4720 __ CmpObjectType(rax, HEAP_NUMBER_TYPE, rcx); 4719 __ CmpObjectType(rax, HEAP_NUMBER_TYPE, rcx);
4721 __ j(not_equal, &miss); 4720 __ j(not_equal, &miss, Label::kNear);
4722 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx); 4721 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx);
4723 __ j(not_equal, &miss); 4722 __ j(not_equal, &miss, Label::kNear);
4724 4723
4725 // Load left and right operand 4724 // Load left and right operand
4726 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); 4725 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
4727 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); 4726 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
4728 4727
4729 // Compare operands 4728 // Compare operands
4730 __ ucomisd(xmm0, xmm1); 4729 __ ucomisd(xmm0, xmm1);
4731 4730
4732 // Don't base result on EFLAGS when a NaN is involved. 4731 // Don't base result on EFLAGS when a NaN is involved.
4733 __ j(parity_even, &unordered); 4732 __ j(parity_even, &unordered, Label::kNear);
4734 4733
4735 // Return a result of -1, 0, or 1, based on EFLAGS. 4734 // Return a result of -1, 0, or 1, based on EFLAGS.
4736 // Performing mov, because xor would destroy the flag register. 4735 // Performing mov, because xor would destroy the flag register.
4737 __ movl(rax, Immediate(0)); 4736 __ movl(rax, Immediate(0));
4738 __ movl(rcx, Immediate(0)); 4737 __ movl(rcx, Immediate(0));
4739 __ setcc(above, rax); // Add one to zero if carry clear and not equal. 4738 __ setcc(above, rax); // Add one to zero if carry clear and not equal.
4740 __ sbbq(rax, rcx); // Subtract one if below (aka. carry set). 4739 __ sbbq(rax, rcx); // Subtract one if below (aka. carry set).
4741 __ ret(0); 4740 __ ret(0);
4742 4741
4743 __ bind(&unordered); 4742 __ bind(&unordered);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
4820 __ push(tmp1); 4819 __ push(tmp1);
4821 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); 4820 __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
4822 4821
4823 __ bind(&miss); 4822 __ bind(&miss);
4824 GenerateMiss(masm); 4823 GenerateMiss(masm);
4825 } 4824 }
4826 4825
4827 4826
4828 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { 4827 void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
4829 ASSERT(state_ == CompareIC::OBJECTS); 4828 ASSERT(state_ == CompareIC::OBJECTS);
4830 NearLabel miss; 4829 Label miss;
4831 Condition either_smi = masm->CheckEitherSmi(rdx, rax); 4830 Condition either_smi = masm->CheckEitherSmi(rdx, rax);
4832 __ j(either_smi, &miss); 4831 __ j(either_smi, &miss, Label::kNear);
4833 4832
4834 __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx); 4833 __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx);
4835 __ j(not_equal, &miss, not_taken); 4834 __ j(not_equal, &miss, not_taken, Label::kNear);
4836 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); 4835 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
4837 __ j(not_equal, &miss, not_taken); 4836 __ j(not_equal, &miss, not_taken, Label::kNear);
4838 4837
4839 ASSERT(GetCondition() == equal); 4838 ASSERT(GetCondition() == equal);
4840 __ subq(rax, rdx); 4839 __ subq(rax, rdx);
4841 __ ret(0); 4840 __ ret(0);
4842 4841
4843 __ bind(&miss); 4842 __ bind(&miss);
4844 GenerateMiss(masm); 4843 GenerateMiss(masm);
4845 } 4844 }
4846 4845
4847 4846
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
5071 __ Drop(1); 5070 __ Drop(1);
5072 __ ret(2 * kPointerSize); 5071 __ ret(2 * kPointerSize);
5073 } 5072 }
5074 5073
5075 5074
5076 #undef __ 5075 #undef __
5077 5076
5078 } } // namespace v8::internal 5077 } } // namespace v8::internal
5079 5078
5080 #endif // V8_TARGET_ARCH_X64 5079 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/builtins-x64.cc ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698