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

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

Issue 7060010: Merge bleeding edge into the GC branch up to 7948. The asserts (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: 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/code-stubs-x64.h ('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 // undefined -> false
239 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
240 __ j(equal, &false_result);
241
242 // Boolean -> its value
243 __ CompareRoot(rax, Heap::kFalseValueRootIndex);
244 __ j(equal, &false_result);
245 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
246 __ j(equal, &true_result);
247
248 // Smis: 0 -> false, all other -> true
249 __ Cmp(rax, Smi::FromInt(0));
250 __ j(equal, &false_result);
251 Condition is_smi = __ CheckSmi(rax);
252 __ j(is_smi, &true_result);
253
238 // 'null' => false. 254 // 'null' => false.
239 __ CompareRoot(rax, Heap::kNullValueRootIndex); 255 __ CompareRoot(rax, Heap::kNullValueRootIndex);
240 __ j(equal, &false_result); 256 __ j(equal, &false_result, Label::kNear);
241 257
242 // Get the map and type of the heap object. 258 // Get the map and type of the heap object.
243 // We don't use CmpObjectType because we manipulate the type field. 259 // We don't use CmpObjectType because we manipulate the type field.
244 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); 260 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
245 __ movzxbq(rcx, FieldOperand(rdx, Map::kInstanceTypeOffset)); 261 __ movzxbq(rcx, FieldOperand(rdx, Map::kInstanceTypeOffset));
246 262
247 // Undetectable => false. 263 // Undetectable => false.
248 __ movzxbq(rbx, FieldOperand(rdx, Map::kBitFieldOffset)); 264 __ movzxbq(rbx, FieldOperand(rdx, Map::kBitFieldOffset));
249 __ and_(rbx, Immediate(1 << Map::kIsUndetectable)); 265 __ and_(rbx, Immediate(1 << Map::kIsUndetectable));
250 __ j(not_zero, &false_result); 266 __ j(not_zero, &false_result, Label::kNear);
251 267
252 // JavaScript object => true. 268 // JavaScript object => true.
253 __ cmpq(rcx, Immediate(FIRST_JS_OBJECT_TYPE)); 269 __ cmpq(rcx, Immediate(FIRST_JS_OBJECT_TYPE));
254 __ j(above_equal, &true_result); 270 __ j(above_equal, &true_result, Label::kNear);
255 271
256 // String value => false iff empty. 272 // String value => false iff empty.
257 __ cmpq(rcx, Immediate(FIRST_NONSTRING_TYPE)); 273 __ cmpq(rcx, Immediate(FIRST_NONSTRING_TYPE));
258 __ j(above_equal, &not_string); 274 __ j(above_equal, &not_string, Label::kNear);
259 __ movq(rdx, FieldOperand(rax, String::kLengthOffset)); 275 __ movq(rdx, FieldOperand(rax, String::kLengthOffset));
260 __ SmiTest(rdx); 276 __ SmiTest(rdx);
261 __ j(zero, &false_result); 277 __ j(zero, &false_result, Label::kNear);
262 __ jmp(&true_result); 278 __ jmp(&true_result, Label::kNear);
263 279
264 __ bind(&not_string); 280 __ bind(&not_string);
265 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); 281 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex);
266 __ j(not_equal, &true_result); 282 __ j(not_equal, &true_result, Label::kNear);
267 // HeapNumber => false iff +0, -0, or NaN. 283 // HeapNumber => false iff +0, -0, or NaN.
268 // These three cases set the zero flag when compared to zero using ucomisd. 284 // These three cases set the zero flag when compared to zero using ucomisd.
269 __ xorps(xmm0, xmm0); 285 __ xorps(xmm0, xmm0);
270 __ ucomisd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); 286 __ ucomisd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
271 __ j(zero, &false_result); 287 __ j(zero, &false_result, Label::kNear);
272 // Fall through to |true_result|. 288 // Fall through to |true_result|.
273 289
274 // Return 1/0 for true/false in rax. 290 // Return 1/0 for true/false in rax.
275 __ bind(&true_result); 291 __ bind(&true_result);
276 __ Set(rax, 1); 292 __ Set(rax, 1);
277 __ ret(1 * kPointerSize); 293 __ ret(1 * kPointerSize);
278 __ bind(&false_result); 294 __ bind(&false_result);
279 __ Set(rax, 0); 295 __ Set(rax, 0);
280 __ ret(1 * kPointerSize); 296 __ ret(1 * kPointerSize);
281 } 297 }
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 void IntegerConvert(MacroAssembler* masm, 387 void IntegerConvert(MacroAssembler* masm,
372 Register result, 388 Register result,
373 Register source) { 389 Register source) {
374 // Result may be rcx. If result and source are the same register, source will 390 // Result may be rcx. If result and source are the same register, source will
375 // be overwritten. 391 // be overwritten.
376 ASSERT(!result.is(rdi) && !result.is(rbx)); 392 ASSERT(!result.is(rdi) && !result.is(rbx));
377 // TODO(lrn): When type info reaches here, if value is a 32-bit integer, use 393 // TODO(lrn): When type info reaches here, if value is a 32-bit integer, use
378 // cvttsd2si (32-bit version) directly. 394 // cvttsd2si (32-bit version) directly.
379 Register double_exponent = rbx; 395 Register double_exponent = rbx;
380 Register double_value = rdi; 396 Register double_value = rdi;
381 NearLabel done, exponent_63_plus; 397 Label done, exponent_63_plus;
382 // Get double and extract exponent. 398 // Get double and extract exponent.
383 __ movq(double_value, FieldOperand(source, HeapNumber::kValueOffset)); 399 __ movq(double_value, FieldOperand(source, HeapNumber::kValueOffset));
384 // Clear result preemptively, in case we need to return zero. 400 // Clear result preemptively, in case we need to return zero.
385 __ xorl(result, result); 401 __ xorl(result, result);
386 __ movq(xmm0, double_value); // Save copy in xmm0 in case we need it there. 402 __ movq(xmm0, double_value); // Save copy in xmm0 in case we need it there.
387 // Double to remove sign bit, shift exponent down to least significant bits. 403 // Double to remove sign bit, shift exponent down to least significant bits.
388 // and subtract bias to get the unshifted, unbiased exponent. 404 // and subtract bias to get the unshifted, unbiased exponent.
389 __ lea(double_exponent, Operand(double_value, double_value, times_1, 0)); 405 __ lea(double_exponent, Operand(double_value, double_value, times_1, 0));
390 __ shr(double_exponent, Immediate(64 - HeapNumber::kExponentBits)); 406 __ shr(double_exponent, Immediate(64 - HeapNumber::kExponentBits));
391 __ subl(double_exponent, Immediate(HeapNumber::kExponentBias)); 407 __ subl(double_exponent, Immediate(HeapNumber::kExponentBias));
392 // Check whether the exponent is too big for a 63 bit unsigned integer. 408 // Check whether the exponent is too big for a 63 bit unsigned integer.
393 __ cmpl(double_exponent, Immediate(63)); 409 __ cmpl(double_exponent, Immediate(63));
394 __ j(above_equal, &exponent_63_plus); 410 __ j(above_equal, &exponent_63_plus, Label::kNear);
395 // Handle exponent range 0..62. 411 // Handle exponent range 0..62.
396 __ cvttsd2siq(result, xmm0); 412 __ cvttsd2siq(result, xmm0);
397 __ jmp(&done); 413 __ jmp(&done, Label::kNear);
398 414
399 __ bind(&exponent_63_plus); 415 __ bind(&exponent_63_plus);
400 // Exponent negative or 63+. 416 // Exponent negative or 63+.
401 __ cmpl(double_exponent, Immediate(83)); 417 __ cmpl(double_exponent, Immediate(83));
402 // If exponent negative or above 83, number contains no significant bits in 418 // If exponent negative or above 83, number contains no significant bits in
403 // the range 0..2^31, so result is zero, and rcx already holds zero. 419 // the range 0..2^31, so result is zero, and rcx already holds zero.
404 __ j(above, &done); 420 __ j(above, &done, Label::kNear);
405 421
406 // Exponent in rage 63..83. 422 // Exponent in rage 63..83.
407 // Mantissa * 2^exponent contains bits in the range 2^0..2^31, namely 423 // Mantissa * 2^exponent contains bits in the range 2^0..2^31, namely
408 // the least significant exponent-52 bits. 424 // the least significant exponent-52 bits.
409 425
410 // Negate low bits of mantissa if value is negative. 426 // Negate low bits of mantissa if value is negative.
411 __ addq(double_value, double_value); // Move sign bit to carry. 427 __ addq(double_value, double_value); // Move sign bit to carry.
412 __ sbbl(result, result); // And convert carry to -1 in result register. 428 __ sbbl(result, result); // And convert carry to -1 in result register.
413 // if scratch2 is negative, do (scratch2-1)^-1, otherwise (scratch2-0)^0. 429 // if scratch2 is negative, do (scratch2-1)^-1, otherwise (scratch2-0)^0.
414 __ addl(double_value, result); 430 __ addl(double_value, result);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 case Token::BIT_NOT: 506 case Token::BIT_NOT:
491 GenerateSmiStubBitNot(masm); 507 GenerateSmiStubBitNot(masm);
492 break; 508 break;
493 default: 509 default:
494 UNREACHABLE(); 510 UNREACHABLE();
495 } 511 }
496 } 512 }
497 513
498 514
499 void TypeRecordingUnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) { 515 void TypeRecordingUnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
500 NearLabel non_smi;
501 Label slow; 516 Label slow;
502 GenerateSmiCodeSub(masm, &non_smi, &slow); 517 GenerateSmiCodeSub(masm, &slow, &slow, Label::kNear, Label::kNear);
503 __ bind(&non_smi);
504 __ bind(&slow); 518 __ bind(&slow);
505 GenerateTypeTransition(masm); 519 GenerateTypeTransition(masm);
506 } 520 }
507 521
508 522
509 void TypeRecordingUnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) { 523 void TypeRecordingUnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
510 NearLabel non_smi; 524 Label non_smi;
511 GenerateSmiCodeBitNot(masm, &non_smi); 525 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
512 __ bind(&non_smi); 526 __ bind(&non_smi);
513 GenerateTypeTransition(masm); 527 GenerateTypeTransition(masm);
514 } 528 }
515 529
516 530
517 void TypeRecordingUnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm, 531 void TypeRecordingUnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
518 NearLabel* non_smi, 532 Label* non_smi,
519 Label* slow) { 533 Label* slow,
520 NearLabel done; 534 Label::Distance non_smi_near,
521 __ JumpIfNotSmi(rax, non_smi); 535 Label::Distance slow_near) {
522 __ SmiNeg(rax, rax, &done); 536 Label done;
523 __ jmp(slow); 537 __ JumpIfNotSmi(rax, non_smi, non_smi_near);
538 __ SmiNeg(rax, rax, &done, Label::kNear);
539 __ jmp(slow, slow_near);
524 __ bind(&done); 540 __ bind(&done);
525 __ ret(0); 541 __ ret(0);
526 } 542 }
527 543
528 544
529 void TypeRecordingUnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm, 545 void TypeRecordingUnaryOpStub::GenerateSmiCodeBitNot(
530 NearLabel* non_smi) { 546 MacroAssembler* masm,
531 __ JumpIfNotSmi(rax, non_smi); 547 Label* non_smi,
548 Label::Distance non_smi_near) {
549 __ JumpIfNotSmi(rax, non_smi, non_smi_near);
532 __ SmiNot(rax, rax); 550 __ SmiNot(rax, rax);
533 __ ret(0); 551 __ ret(0);
534 } 552 }
535 553
536 554
537 // TODO(svenpanne): Use virtual functions instead of switch. 555 // TODO(svenpanne): Use virtual functions instead of switch.
538 void TypeRecordingUnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { 556 void TypeRecordingUnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
539 switch (op_) { 557 switch (op_) {
540 case Token::SUB: 558 case Token::SUB:
541 GenerateHeapNumberStubSub(masm); 559 GenerateHeapNumberStubSub(masm);
542 break; 560 break;
543 case Token::BIT_NOT: 561 case Token::BIT_NOT:
544 GenerateHeapNumberStubBitNot(masm); 562 GenerateHeapNumberStubBitNot(masm);
545 break; 563 break;
546 default: 564 default:
547 UNREACHABLE(); 565 UNREACHABLE();
548 } 566 }
549 } 567 }
550 568
551 569
552 void TypeRecordingUnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) { 570 void TypeRecordingUnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
553 NearLabel non_smi; 571 Label non_smi, slow, call_builtin;
554 Label slow; 572 GenerateSmiCodeSub(masm, &non_smi, &call_builtin, Label::kNear);
555 GenerateSmiCodeSub(masm, &non_smi, &slow);
556 __ bind(&non_smi); 573 __ bind(&non_smi);
557 GenerateHeapNumberCodeSub(masm, &slow); 574 GenerateHeapNumberCodeSub(masm, &slow);
558 __ bind(&slow); 575 __ bind(&slow);
559 GenerateTypeTransition(masm); 576 GenerateTypeTransition(masm);
577 __ bind(&call_builtin);
578 GenerateGenericCodeFallback(masm);
560 } 579 }
561 580
562 581
563 void TypeRecordingUnaryOpStub::GenerateHeapNumberStubBitNot( 582 void TypeRecordingUnaryOpStub::GenerateHeapNumberStubBitNot(
564 MacroAssembler* masm) { 583 MacroAssembler* masm) {
565 NearLabel non_smi; 584 Label non_smi, slow;
566 Label slow; 585 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
567 GenerateSmiCodeBitNot(masm, &non_smi);
568 __ bind(&non_smi); 586 __ bind(&non_smi);
569 GenerateHeapNumberCodeBitNot(masm, &slow); 587 GenerateHeapNumberCodeBitNot(masm, &slow);
570 __ bind(&slow); 588 __ bind(&slow);
571 GenerateTypeTransition(masm); 589 GenerateTypeTransition(masm);
572 } 590 }
573 591
574 592
575 void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm, 593 void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
576 Label* slow) { 594 Label* slow) {
577 // Check if the operand is a heap number. 595 // Check if the operand is a heap number.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 case Token::BIT_NOT: 658 case Token::BIT_NOT:
641 GenerateGenericStubBitNot(masm); 659 GenerateGenericStubBitNot(masm);
642 break; 660 break;
643 default: 661 default:
644 UNREACHABLE(); 662 UNREACHABLE();
645 } 663 }
646 } 664 }
647 665
648 666
649 void TypeRecordingUnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) { 667 void TypeRecordingUnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
650 NearLabel non_smi; 668 Label non_smi, slow;
651 Label slow; 669 GenerateSmiCodeSub(masm, &non_smi, &slow, Label::kNear);
652 GenerateSmiCodeSub(masm, &non_smi, &slow);
653 __ bind(&non_smi); 670 __ bind(&non_smi);
654 GenerateHeapNumberCodeSub(masm, &slow); 671 GenerateHeapNumberCodeSub(masm, &slow);
655 __ bind(&slow); 672 __ bind(&slow);
656 GenerateGenericCodeFallback(masm); 673 GenerateGenericCodeFallback(masm);
657 } 674 }
658 675
659 676
660 void TypeRecordingUnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) { 677 void TypeRecordingUnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
661 NearLabel non_smi; 678 Label non_smi, slow;
662 Label slow; 679 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
663 GenerateSmiCodeBitNot(masm, &non_smi);
664 __ bind(&non_smi); 680 __ bind(&non_smi);
665 GenerateHeapNumberCodeBitNot(masm, &slow); 681 GenerateHeapNumberCodeBitNot(masm, &slow);
666 __ bind(&slow); 682 __ bind(&slow);
667 GenerateGenericCodeFallback(masm); 683 GenerateGenericCodeFallback(masm);
668 } 684 }
669 685
670 686
671 void TypeRecordingUnaryOpStub::GenerateGenericCodeFallback( 687 void TypeRecordingUnaryOpStub::GenerateGenericCodeFallback(
672 MacroAssembler* masm) { 688 MacroAssembler* masm) {
673 // Handle the slow case by jumping to the JavaScript builtin. 689 // Handle the slow case by jumping to the JavaScript builtin.
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 // No fall-through from this generated code. 1066 // No fall-through from this generated code.
1051 if (FLAG_debug_code) { 1067 if (FLAG_debug_code) {
1052 __ Abort("Unexpected fall-through in " 1068 __ Abort("Unexpected fall-through in "
1053 "TypeRecordingBinaryStub::GenerateFloatingPointCode."); 1069 "TypeRecordingBinaryStub::GenerateFloatingPointCode.");
1054 } 1070 }
1055 } 1071 }
1056 1072
1057 1073
1058 void TypeRecordingBinaryOpStub::GenerateStringAddCode(MacroAssembler* masm) { 1074 void TypeRecordingBinaryOpStub::GenerateStringAddCode(MacroAssembler* masm) {
1059 ASSERT(op_ == Token::ADD); 1075 ASSERT(op_ == Token::ADD);
1060 NearLabel left_not_string, call_runtime; 1076 Label left_not_string, call_runtime;
1061 1077
1062 // Registers containing left and right operands respectively. 1078 // Registers containing left and right operands respectively.
1063 Register left = rdx; 1079 Register left = rdx;
1064 Register right = rax; 1080 Register right = rax;
1065 1081
1066 // Test if left operand is a string. 1082 // Test if left operand is a string.
1067 __ JumpIfSmi(left, &left_not_string); 1083 __ JumpIfSmi(left, &left_not_string, Label::kNear);
1068 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, rcx); 1084 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, rcx);
1069 __ j(above_equal, &left_not_string); 1085 __ j(above_equal, &left_not_string, Label::kNear);
1070 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); 1086 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB);
1071 GenerateRegisterArgsPush(masm); 1087 GenerateRegisterArgsPush(masm);
1072 __ TailCallStub(&string_add_left_stub); 1088 __ TailCallStub(&string_add_left_stub);
1073 1089
1074 // Left operand is not a string, test right. 1090 // Left operand is not a string, test right.
1075 __ bind(&left_not_string); 1091 __ bind(&left_not_string);
1076 __ JumpIfSmi(right, &call_runtime); 1092 __ JumpIfSmi(right, &call_runtime, Label::kNear);
1077 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, rcx); 1093 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, rcx);
1078 __ j(above_equal, &call_runtime); 1094 __ j(above_equal, &call_runtime, Label::kNear);
1079 1095
1080 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); 1096 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB);
1081 GenerateRegisterArgsPush(masm); 1097 GenerateRegisterArgsPush(masm);
1082 __ TailCallStub(&string_add_right_stub); 1098 __ TailCallStub(&string_add_right_stub);
1083 1099
1084 // Neither argument is a string. 1100 // Neither argument is a string.
1085 __ bind(&call_runtime); 1101 __ bind(&call_runtime);
1086 } 1102 }
1087 1103
1088 1104
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1194 void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) { 1210 void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
1195 Label call_runtime; 1211 Label call_runtime;
1196 1212
1197 if (op_ == Token::ADD) { 1213 if (op_ == Token::ADD) {
1198 // Handle string addition here, because it is the only operation 1214 // Handle string addition here, because it is the only operation
1199 // that does not do a ToNumber conversion on the operands. 1215 // that does not do a ToNumber conversion on the operands.
1200 GenerateStringAddCode(masm); 1216 GenerateStringAddCode(masm);
1201 } 1217 }
1202 1218
1203 // Convert oddball arguments to numbers. 1219 // Convert oddball arguments to numbers.
1204 NearLabel check, done; 1220 Label check, done;
1205 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); 1221 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex);
1206 __ j(not_equal, &check); 1222 __ j(not_equal, &check, Label::kNear);
1207 if (Token::IsBitOp(op_)) { 1223 if (Token::IsBitOp(op_)) {
1208 __ xor_(rdx, rdx); 1224 __ xor_(rdx, rdx);
1209 } else { 1225 } else {
1210 __ LoadRoot(rdx, Heap::kNanValueRootIndex); 1226 __ LoadRoot(rdx, Heap::kNanValueRootIndex);
1211 } 1227 }
1212 __ jmp(&done); 1228 __ jmp(&done, Label::kNear);
1213 __ bind(&check); 1229 __ bind(&check);
1214 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 1230 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
1215 __ j(not_equal, &done); 1231 __ j(not_equal, &done, Label::kNear);
1216 if (Token::IsBitOp(op_)) { 1232 if (Token::IsBitOp(op_)) {
1217 __ xor_(rax, rax); 1233 __ xor_(rax, rax);
1218 } else { 1234 } else {
1219 __ LoadRoot(rax, Heap::kNanValueRootIndex); 1235 __ LoadRoot(rax, Heap::kNanValueRootIndex);
1220 } 1236 }
1221 __ bind(&done); 1237 __ bind(&done);
1222 1238
1223 GenerateHeapNumberStub(masm); 1239 GenerateHeapNumberStub(masm);
1224 } 1240 }
1225 1241
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1313 // rsp[0]: return address. 1329 // rsp[0]: return address.
1314 // xmm1: untagged double input argument 1330 // xmm1: untagged double input argument
1315 // Output: 1331 // Output:
1316 // xmm1: untagged double result. 1332 // xmm1: untagged double result.
1317 1333
1318 Label runtime_call; 1334 Label runtime_call;
1319 Label runtime_call_clear_stack; 1335 Label runtime_call_clear_stack;
1320 Label skip_cache; 1336 Label skip_cache;
1321 const bool tagged = (argument_type_ == TAGGED); 1337 const bool tagged = (argument_type_ == TAGGED);
1322 if (tagged) { 1338 if (tagged) {
1323 NearLabel input_not_smi; 1339 Label input_not_smi, loaded;
1324 NearLabel loaded;
1325 // Test that rax is a number. 1340 // Test that rax is a number.
1326 __ movq(rax, Operand(rsp, kPointerSize)); 1341 __ movq(rax, Operand(rsp, kPointerSize));
1327 __ JumpIfNotSmi(rax, &input_not_smi); 1342 __ JumpIfNotSmi(rax, &input_not_smi, Label::kNear);
1328 // Input is a smi. Untag and load it onto the FPU stack. 1343 // Input is a smi. Untag and load it onto the FPU stack.
1329 // Then load the bits of the double into rbx. 1344 // Then load the bits of the double into rbx.
1330 __ SmiToInteger32(rax, rax); 1345 __ SmiToInteger32(rax, rax);
1331 __ subq(rsp, Immediate(kDoubleSize)); 1346 __ subq(rsp, Immediate(kDoubleSize));
1332 __ cvtlsi2sd(xmm1, rax); 1347 __ cvtlsi2sd(xmm1, rax);
1333 __ movsd(Operand(rsp, 0), xmm1); 1348 __ movsd(Operand(rsp, 0), xmm1);
1334 __ movq(rbx, xmm1); 1349 __ movq(rbx, xmm1);
1335 __ movq(rdx, xmm1); 1350 __ movq(rdx, xmm1);
1336 __ fld_d(Operand(rsp, 0)); 1351 __ fld_d(Operand(rsp, 0));
1337 __ addq(rsp, Immediate(kDoubleSize)); 1352 __ addq(rsp, Immediate(kDoubleSize));
1338 __ jmp(&loaded); 1353 __ jmp(&loaded, Label::kNear);
1339 1354
1340 __ bind(&input_not_smi); 1355 __ bind(&input_not_smi);
1341 // Check if input is a HeapNumber. 1356 // Check if input is a HeapNumber.
1342 __ LoadRoot(rbx, Heap::kHeapNumberMapRootIndex); 1357 __ LoadRoot(rbx, Heap::kHeapNumberMapRootIndex);
1343 __ cmpq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 1358 __ cmpq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
1344 __ j(not_equal, &runtime_call); 1359 __ j(not_equal, &runtime_call);
1345 // Input is a HeapNumber. Push it on the FPU stack and load its 1360 // Input is a HeapNumber. Push it on the FPU stack and load its
1346 // bits into rbx. 1361 // bits into rbx.
1347 __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset)); 1362 __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset));
1348 __ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset)); 1363 __ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset));
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1403 CHECK_EQ(16, static_cast<int>(elem2_start - elem_start)); 1418 CHECK_EQ(16, static_cast<int>(elem2_start - elem_start));
1404 CHECK_EQ(0, static_cast<int>(elem_in0 - elem_start)); 1419 CHECK_EQ(0, static_cast<int>(elem_in0 - elem_start));
1405 CHECK_EQ(kIntSize, static_cast<int>(elem_in1 - elem_start)); 1420 CHECK_EQ(kIntSize, static_cast<int>(elem_in1 - elem_start));
1406 CHECK_EQ(2 * kIntSize, static_cast<int>(elem_out - elem_start)); 1421 CHECK_EQ(2 * kIntSize, static_cast<int>(elem_out - elem_start));
1407 } 1422 }
1408 #endif 1423 #endif
1409 // Find the address of the rcx'th entry in the cache, i.e., &rax[rcx*16]. 1424 // Find the address of the rcx'th entry in the cache, i.e., &rax[rcx*16].
1410 __ addl(rcx, rcx); 1425 __ addl(rcx, rcx);
1411 __ lea(rcx, Operand(rax, rcx, times_8, 0)); 1426 __ lea(rcx, Operand(rax, rcx, times_8, 0));
1412 // Check if cache matches: Double value is stored in uint32_t[2] array. 1427 // Check if cache matches: Double value is stored in uint32_t[2] array.
1413 NearLabel cache_miss; 1428 Label cache_miss;
1414 __ cmpq(rbx, Operand(rcx, 0)); 1429 __ cmpq(rbx, Operand(rcx, 0));
1415 __ j(not_equal, &cache_miss); 1430 __ j(not_equal, &cache_miss, Label::kNear);
1416 // Cache hit! 1431 // Cache hit!
1417 __ movq(rax, Operand(rcx, 2 * kIntSize)); 1432 __ movq(rax, Operand(rcx, 2 * kIntSize));
1418 if (tagged) { 1433 if (tagged) {
1419 __ fstp(0); // Clear FPU stack. 1434 __ fstp(0); // Clear FPU stack.
1420 __ ret(kPointerSize); 1435 __ ret(kPointerSize);
1421 } else { // UNTAGGED. 1436 } else { // UNTAGGED.
1422 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); 1437 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
1423 __ Ret(); 1438 __ Ret();
1424 } 1439 }
1425 1440
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1513 __ movq(rdi, rbx); 1528 __ movq(rdi, rbx);
1514 // Move exponent and sign bits to low bits. 1529 // Move exponent and sign bits to low bits.
1515 __ shr(rdi, Immediate(HeapNumber::kMantissaBits)); 1530 __ shr(rdi, Immediate(HeapNumber::kMantissaBits));
1516 // Remove sign bit. 1531 // Remove sign bit.
1517 __ andl(rdi, Immediate((1 << HeapNumber::kExponentBits) - 1)); 1532 __ andl(rdi, Immediate((1 << HeapNumber::kExponentBits) - 1));
1518 int supported_exponent_limit = (63 + HeapNumber::kExponentBias); 1533 int supported_exponent_limit = (63 + HeapNumber::kExponentBias);
1519 __ cmpl(rdi, Immediate(supported_exponent_limit)); 1534 __ cmpl(rdi, Immediate(supported_exponent_limit));
1520 __ j(below, &in_range); 1535 __ j(below, &in_range);
1521 // Check for infinity and NaN. Both return NaN for sin. 1536 // Check for infinity and NaN. Both return NaN for sin.
1522 __ cmpl(rdi, Immediate(0x7ff)); 1537 __ cmpl(rdi, Immediate(0x7ff));
1523 NearLabel non_nan_result; 1538 Label non_nan_result;
1524 __ j(not_equal, &non_nan_result); 1539 __ j(not_equal, &non_nan_result, Label::kNear);
1525 // Input is +/-Infinity or NaN. Result is NaN. 1540 // Input is +/-Infinity or NaN. Result is NaN.
1526 __ fstp(0); 1541 __ fstp(0);
1527 __ LoadRoot(kScratchRegister, Heap::kNanValueRootIndex); 1542 __ LoadRoot(kScratchRegister, Heap::kNanValueRootIndex);
1528 __ fld_d(FieldOperand(kScratchRegister, HeapNumber::kValueOffset)); 1543 __ fld_d(FieldOperand(kScratchRegister, HeapNumber::kValueOffset));
1529 __ jmp(&done); 1544 __ jmp(&done);
1530 1545
1531 __ bind(&non_nan_result); 1546 __ bind(&non_nan_result);
1532 1547
1533 // Use fpmod to restrict argument to the range +/-2*PI. 1548 // Use fpmod to restrict argument to the range +/-2*PI.
1534 __ movq(rdi, rax); // Save rax before using fnstsw_ax. 1549 __ movq(rdi, rax); // Save rax before using fnstsw_ax.
1535 __ fldpi(); 1550 __ fldpi();
1536 __ fadd(0); 1551 __ fadd(0);
1537 __ fld(1); 1552 __ fld(1);
1538 // FPU Stack: input, 2*pi, input. 1553 // FPU Stack: input, 2*pi, input.
1539 { 1554 {
1540 Label no_exceptions; 1555 Label no_exceptions;
1541 __ fwait(); 1556 __ fwait();
1542 __ fnstsw_ax(); 1557 __ fnstsw_ax();
1543 // Clear if Illegal Operand or Zero Division exceptions are set. 1558 // Clear if Illegal Operand or Zero Division exceptions are set.
1544 __ testl(rax, Immediate(5)); // #IO and #ZD flags of FPU status word. 1559 __ testl(rax, Immediate(5)); // #IO and #ZD flags of FPU status word.
1545 __ j(zero, &no_exceptions); 1560 __ j(zero, &no_exceptions);
1546 __ fnclex(); 1561 __ fnclex();
1547 __ bind(&no_exceptions); 1562 __ bind(&no_exceptions);
1548 } 1563 }
1549 1564
1550 // Compute st(0) % st(1) 1565 // Compute st(0) % st(1)
1551 { 1566 {
1552 NearLabel partial_remainder_loop; 1567 Label partial_remainder_loop;
1553 __ bind(&partial_remainder_loop); 1568 __ bind(&partial_remainder_loop);
1554 __ fprem1(); 1569 __ fprem1();
1555 __ fwait(); 1570 __ fwait();
1556 __ fnstsw_ax(); 1571 __ fnstsw_ax();
1557 __ testl(rax, Immediate(0x400)); // Check C2 bit of FPU status word. 1572 __ testl(rax, Immediate(0x400)); // Check C2 bit of FPU status word.
1558 // If C2 is set, computation only has partial result. Loop to 1573 // If C2 is set, computation only has partial result. Loop to
1559 // continue computation. 1574 // continue computation.
1560 __ j(not_zero, &partial_remainder_loop); 1575 __ j(not_zero, &partial_remainder_loop);
1561 } 1576 }
1562 // FPU Stack: input, 2*pi, input % 2*pi 1577 // FPU Stack: input, 2*pi, input % 2*pi
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1735 Register scratch2, 1750 Register scratch2,
1736 Register scratch3, 1751 Register scratch3,
1737 Label* on_success, 1752 Label* on_success,
1738 Label* on_not_smis) { 1753 Label* on_not_smis) {
1739 Register heap_number_map = scratch3; 1754 Register heap_number_map = scratch3;
1740 Register smi_result = scratch1; 1755 Register smi_result = scratch1;
1741 Label done; 1756 Label done;
1742 1757
1743 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 1758 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
1744 1759
1745 NearLabel first_smi, check_second; 1760 Label first_smi;
1746 __ JumpIfSmi(first, &first_smi); 1761 __ JumpIfSmi(first, &first_smi, Label::kNear);
1747 __ cmpq(FieldOperand(first, HeapObject::kMapOffset), heap_number_map); 1762 __ cmpq(FieldOperand(first, HeapObject::kMapOffset), heap_number_map);
1748 __ j(not_equal, on_not_smis); 1763 __ j(not_equal, on_not_smis);
1749 // Convert HeapNumber to smi if possible. 1764 // Convert HeapNumber to smi if possible.
1750 __ movsd(xmm0, FieldOperand(first, HeapNumber::kValueOffset)); 1765 __ movsd(xmm0, FieldOperand(first, HeapNumber::kValueOffset));
1751 __ movq(scratch2, xmm0); 1766 __ movq(scratch2, xmm0);
1752 __ cvttsd2siq(smi_result, xmm0); 1767 __ cvttsd2siq(smi_result, xmm0);
1753 // Check if conversion was successful by converting back and 1768 // Check if conversion was successful by converting back and
1754 // comparing to the original double's bits. 1769 // comparing to the original double's bits.
1755 __ cvtlsi2sd(xmm1, smi_result); 1770 __ cvtlsi2sd(xmm1, smi_result);
1756 __ movq(kScratchRegister, xmm1); 1771 __ movq(kScratchRegister, xmm1);
1757 __ cmpq(scratch2, kScratchRegister); 1772 __ cmpq(scratch2, kScratchRegister);
1758 __ j(not_equal, on_not_smis); 1773 __ j(not_equal, on_not_smis);
1759 __ Integer32ToSmi(first, smi_result); 1774 __ Integer32ToSmi(first, smi_result);
1760 1775
1761 __ bind(&check_second);
1762 __ JumpIfSmi(second, (on_success != NULL) ? on_success : &done); 1776 __ JumpIfSmi(second, (on_success != NULL) ? on_success : &done);
1763 __ bind(&first_smi); 1777 __ bind(&first_smi);
1764 if (FLAG_debug_code) { 1778 if (FLAG_debug_code) {
1765 // Second should be non-smi if we get here. 1779 // Second should be non-smi if we get here.
1766 __ AbortIfSmi(second); 1780 __ AbortIfSmi(second);
1767 } 1781 }
1768 __ cmpq(FieldOperand(second, HeapObject::kMapOffset), heap_number_map); 1782 __ cmpq(FieldOperand(second, HeapObject::kMapOffset), heap_number_map);
1769 __ j(not_equal, on_not_smis); 1783 __ j(not_equal, on_not_smis);
1770 // Convert second to smi, if possible. 1784 // Convert second to smi, if possible.
1771 __ movsd(xmm0, FieldOperand(second, HeapNumber::kValueOffset)); 1785 __ movsd(xmm0, FieldOperand(second, HeapNumber::kValueOffset));
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1822 // Optimized version of pow if exponent is a smi. 1836 // Optimized version of pow if exponent is a smi.
1823 // xmm0 contains the base. 1837 // xmm0 contains the base.
1824 __ bind(&powi); 1838 __ bind(&powi);
1825 __ SmiToInteger32(rax, rax); 1839 __ SmiToInteger32(rax, rax);
1826 1840
1827 // Save exponent in base as we need to check if exponent is negative later. 1841 // Save exponent in base as we need to check if exponent is negative later.
1828 // We know that base and exponent are in different registers. 1842 // We know that base and exponent are in different registers.
1829 __ movq(rdx, rax); 1843 __ movq(rdx, rax);
1830 1844
1831 // Get absolute value of exponent. 1845 // Get absolute value of exponent.
1832 NearLabel no_neg; 1846 Label no_neg;
1833 __ cmpl(rax, Immediate(0)); 1847 __ cmpl(rax, Immediate(0));
1834 __ j(greater_equal, &no_neg); 1848 __ j(greater_equal, &no_neg, Label::kNear);
1835 __ negl(rax); 1849 __ negl(rax);
1836 __ bind(&no_neg); 1850 __ bind(&no_neg);
1837 1851
1838 // Load xmm1 with 1. 1852 // Load xmm1 with 1.
1839 __ movaps(xmm1, xmm3); 1853 __ movaps(xmm1, xmm3);
1840 NearLabel while_true; 1854 Label while_true;
1841 NearLabel no_multiply; 1855 Label no_multiply;
1842 1856
1843 __ bind(&while_true); 1857 __ bind(&while_true);
1844 __ shrl(rax, Immediate(1)); 1858 __ shrl(rax, Immediate(1));
1845 __ j(not_carry, &no_multiply); 1859 __ j(not_carry, &no_multiply, Label::kNear);
1846 __ mulsd(xmm1, xmm0); 1860 __ mulsd(xmm1, xmm0);
1847 __ bind(&no_multiply); 1861 __ bind(&no_multiply);
1848 __ mulsd(xmm0, xmm0); 1862 __ mulsd(xmm0, xmm0);
1849 __ j(not_zero, &while_true); 1863 __ j(not_zero, &while_true);
1850 1864
1851 // Base has the original value of the exponent - if the exponent is 1865 // Base has the original value of the exponent - if the exponent is
1852 // negative return 1/result. 1866 // negative return 1/result.
1853 __ testl(rdx, rdx); 1867 __ testl(rdx, rdx);
1854 __ j(positive, &allocate_return); 1868 __ j(positive, &allocate_return);
1855 // Special case if xmm1 has reached infinity. 1869 // Special case if xmm1 has reached infinity.
1856 __ divsd(xmm3, xmm1); 1870 __ divsd(xmm3, xmm1);
1857 __ movaps(xmm1, xmm3); 1871 __ movaps(xmm1, xmm3);
1858 __ xorps(xmm0, xmm0); 1872 __ xorps(xmm0, xmm0);
1859 __ ucomisd(xmm0, xmm1); 1873 __ ucomisd(xmm0, xmm1);
1860 __ j(equal, &call_runtime); 1874 __ j(equal, &call_runtime);
1861 1875
1862 __ jmp(&allocate_return); 1876 __ jmp(&allocate_return);
1863 1877
1864 // Exponent (or both) is a heapnumber - no matter what we should now work 1878 // Exponent (or both) is a heapnumber - no matter what we should now work
1865 // on doubles. 1879 // on doubles.
1866 __ bind(&exponent_nonsmi); 1880 __ bind(&exponent_nonsmi);
1867 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 1881 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
1868 Heap::kHeapNumberMapRootIndex); 1882 Heap::kHeapNumberMapRootIndex);
1869 __ j(not_equal, &call_runtime); 1883 __ j(not_equal, &call_runtime);
1870 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); 1884 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
1871 // Test if exponent is nan. 1885 // Test if exponent is nan.
1872 __ ucomisd(xmm1, xmm1); 1886 __ ucomisd(xmm1, xmm1);
1873 __ j(parity_even, &call_runtime); 1887 __ j(parity_even, &call_runtime);
1874 1888
1875 NearLabel base_not_smi; 1889 Label base_not_smi, handle_special_cases;
1876 NearLabel handle_special_cases; 1890 __ JumpIfNotSmi(rdx, &base_not_smi, Label::kNear);
1877 __ JumpIfNotSmi(rdx, &base_not_smi);
1878 __ SmiToInteger32(rdx, rdx); 1891 __ SmiToInteger32(rdx, rdx);
1879 __ cvtlsi2sd(xmm0, rdx); 1892 __ cvtlsi2sd(xmm0, rdx);
1880 __ jmp(&handle_special_cases); 1893 __ jmp(&handle_special_cases, Label::kNear);
1881 1894
1882 __ bind(&base_not_smi); 1895 __ bind(&base_not_smi);
1883 __ CompareRoot(FieldOperand(rdx, HeapObject::kMapOffset), 1896 __ CompareRoot(FieldOperand(rdx, HeapObject::kMapOffset),
1884 Heap::kHeapNumberMapRootIndex); 1897 Heap::kHeapNumberMapRootIndex);
1885 __ j(not_equal, &call_runtime); 1898 __ j(not_equal, &call_runtime);
1886 __ movl(rcx, FieldOperand(rdx, HeapNumber::kExponentOffset)); 1899 __ movl(rcx, FieldOperand(rdx, HeapNumber::kExponentOffset));
1887 __ andl(rcx, Immediate(HeapNumber::kExponentMask)); 1900 __ andl(rcx, Immediate(HeapNumber::kExponentMask));
1888 __ cmpl(rcx, Immediate(HeapNumber::kExponentMask)); 1901 __ cmpl(rcx, Immediate(HeapNumber::kExponentMask));
1889 // base is NaN or +/-Infinity 1902 // base is NaN or +/-Infinity
1890 __ j(greater_equal, &call_runtime); 1903 __ j(greater_equal, &call_runtime);
1891 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); 1904 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
1892 1905
1893 // base is in xmm0 and exponent is in xmm1. 1906 // base is in xmm0 and exponent is in xmm1.
1894 __ bind(&handle_special_cases); 1907 __ bind(&handle_special_cases);
1895 NearLabel not_minus_half; 1908 Label not_minus_half;
1896 // Test for -0.5. 1909 // Test for -0.5.
1897 // Load xmm2 with -0.5. 1910 // Load xmm2 with -0.5.
1898 __ movq(rcx, V8_UINT64_C(0xBFE0000000000000), RelocInfo::NONE); 1911 __ movq(rcx, V8_UINT64_C(0xBFE0000000000000), RelocInfo::NONE);
1899 __ movq(xmm2, rcx); 1912 __ movq(xmm2, rcx);
1900 // xmm2 now has -0.5. 1913 // xmm2 now has -0.5.
1901 __ ucomisd(xmm2, xmm1); 1914 __ ucomisd(xmm2, xmm1);
1902 __ j(not_equal, &not_minus_half); 1915 __ j(not_equal, &not_minus_half, Label::kNear);
1903 1916
1904 // Calculates reciprocal of square root. 1917 // Calculates reciprocal of square root.
1905 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. 1918 // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
1906 __ xorps(xmm1, xmm1); 1919 __ xorps(xmm1, xmm1);
1907 __ addsd(xmm1, xmm0); 1920 __ addsd(xmm1, xmm0);
1908 __ sqrtsd(xmm1, xmm1); 1921 __ sqrtsd(xmm1, xmm1);
1909 __ divsd(xmm3, xmm1); 1922 __ divsd(xmm3, xmm1);
1910 __ movaps(xmm1, xmm3); 1923 __ movaps(xmm1, xmm3);
1911 __ jmp(&allocate_return); 1924 __ jmp(&allocate_return);
1912 1925
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
2211 // Check that the last match info has space for the capture registers and the 2224 // Check that the last match info has space for the capture registers and the
2212 // additional information. Ensure no overflow in add. 2225 // additional information. Ensure no overflow in add.
2213 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); 2226 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset);
2214 __ SmiToInteger32(rdi, FieldOperand(rbx, FixedArray::kLengthOffset)); 2227 __ SmiToInteger32(rdi, FieldOperand(rbx, FixedArray::kLengthOffset));
2215 __ addl(rdx, Immediate(RegExpImpl::kLastMatchOverhead)); 2228 __ addl(rdx, Immediate(RegExpImpl::kLastMatchOverhead));
2216 __ cmpl(rdx, rdi); 2229 __ cmpl(rdx, rdi);
2217 __ j(greater, &runtime); 2230 __ j(greater, &runtime);
2218 2231
2219 // rax: RegExp data (FixedArray) 2232 // rax: RegExp data (FixedArray)
2220 // Check the representation and encoding of the subject string. 2233 // Check the representation and encoding of the subject string.
2221 NearLabel seq_ascii_string, seq_two_byte_string, check_code; 2234 Label seq_ascii_string, seq_two_byte_string, check_code;
2222 __ movq(rdi, Operand(rsp, kSubjectOffset)); 2235 __ movq(rdi, Operand(rsp, kSubjectOffset));
2223 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); 2236 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
2224 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 2237 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
2225 // First check for flat two byte string. 2238 // First check for flat two byte string.
2226 __ andb(rbx, Immediate( 2239 __ andb(rbx, Immediate(
2227 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask)); 2240 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask));
2228 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); 2241 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
2229 __ j(zero, &seq_two_byte_string); 2242 __ j(zero, &seq_two_byte_string, Label::kNear);
2230 // Any other flat string must be a flat ascii string. 2243 // Any other flat string must be a flat ascii string.
2231 __ testb(rbx, Immediate(kIsNotStringMask | kStringRepresentationMask)); 2244 __ testb(rbx, Immediate(kIsNotStringMask | kStringRepresentationMask));
2232 __ j(zero, &seq_ascii_string); 2245 __ j(zero, &seq_ascii_string, Label::kNear);
2233 2246
2234 // Check for flat cons string. 2247 // Check for flat cons string.
2235 // A flat cons string is a cons string where the second part is the empty 2248 // A flat cons string is a cons string where the second part is the empty
2236 // string. In that case the subject string is just the first part of the cons 2249 // string. In that case the subject string is just the first part of the cons
2237 // string. Also in this case the first part of the cons string is known to be 2250 // string. Also in this case the first part of the cons string is known to be
2238 // a sequential string or an external string. 2251 // a sequential string or an external string.
2239 STATIC_ASSERT(kExternalStringTag !=0); 2252 STATIC_ASSERT(kExternalStringTag !=0);
2240 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0); 2253 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0);
2241 __ testb(rbx, Immediate(kIsNotStringMask | kExternalStringTag)); 2254 __ testb(rbx, Immediate(kIsNotStringMask | kExternalStringTag));
2242 __ j(not_zero, &runtime); 2255 __ j(not_zero, &runtime);
2243 // String is a cons string. 2256 // String is a cons string.
2244 __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset), 2257 __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset),
2245 Heap::kEmptyStringRootIndex); 2258 Heap::kEmptyStringRootIndex);
2246 __ j(not_equal, &runtime); 2259 __ j(not_equal, &runtime);
2247 __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); 2260 __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset));
2248 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); 2261 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
2249 // String is a cons string with empty second part. 2262 // String is a cons string with empty second part.
2250 // rdi: first part of cons string. 2263 // rdi: first part of cons string.
2251 // rbx: map of first part of cons string. 2264 // rbx: map of first part of cons string.
2252 // Is first part a flat two byte string? 2265 // Is first part a flat two byte string?
2253 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), 2266 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset),
2254 Immediate(kStringRepresentationMask | kStringEncodingMask)); 2267 Immediate(kStringRepresentationMask | kStringEncodingMask));
2255 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); 2268 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
2256 __ j(zero, &seq_two_byte_string); 2269 __ j(zero, &seq_two_byte_string, Label::kNear);
2257 // Any other flat string must be ascii. 2270 // Any other flat string must be ascii.
2258 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), 2271 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset),
2259 Immediate(kStringRepresentationMask)); 2272 Immediate(kStringRepresentationMask));
2260 __ j(not_zero, &runtime); 2273 __ j(not_zero, &runtime);
2261 2274
2262 __ bind(&seq_ascii_string); 2275 __ bind(&seq_ascii_string);
2263 // rdi: subject string (sequential ascii) 2276 // rdi: subject string (sequential ascii)
2264 // rax: RegExp data (FixedArray) 2277 // rax: RegExp data (FixedArray)
2265 __ movq(r11, FieldOperand(rax, JSRegExp::kDataAsciiCodeOffset)); 2278 __ movq(r11, FieldOperand(rax, JSRegExp::kDataAsciiCodeOffset));
2266 __ Set(rcx, 1); // Type is ascii. 2279 __ Set(rcx, 1); // Type is ascii.
2267 __ jmp(&check_code); 2280 __ jmp(&check_code, Label::kNear);
2268 2281
2269 __ bind(&seq_two_byte_string); 2282 __ bind(&seq_two_byte_string);
2270 // rdi: subject string (flat two-byte) 2283 // rdi: subject string (flat two-byte)
2271 // rax: RegExp data (FixedArray) 2284 // rax: RegExp data (FixedArray)
2272 __ movq(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); 2285 __ movq(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset));
2273 __ Set(rcx, 0); // Type is two byte. 2286 __ Set(rcx, 0); // Type is two byte.
2274 2287
2275 __ bind(&check_code); 2288 __ bind(&check_code);
2276 // Check that the irregexp code has been generated for the actual string 2289 // Check that the irregexp code has been generated for the actual string
2277 // encoding. If it has, the field contains a code object otherwise it contains 2290 // 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
2343 #endif 2356 #endif
2344 2357
2345 // Keep track on aliasing between argX defined above and the registers used. 2358 // Keep track on aliasing between argX defined above and the registers used.
2346 // rdi: subject string 2359 // rdi: subject string
2347 // rbx: previous index 2360 // rbx: previous index
2348 // rcx: encoding of subject string (1 if ascii 0 if two_byte); 2361 // rcx: encoding of subject string (1 if ascii 0 if two_byte);
2349 // r11: code 2362 // r11: code
2350 2363
2351 // Argument 4: End of string data 2364 // Argument 4: End of string data
2352 // Argument 3: Start of string data 2365 // Argument 3: Start of string data
2353 NearLabel setup_two_byte, setup_rest; 2366 Label setup_two_byte, setup_rest;
2354 __ testb(rcx, rcx); // Last use of rcx as encoding of subject string. 2367 __ testb(rcx, rcx); // Last use of rcx as encoding of subject string.
2355 __ j(zero, &setup_two_byte); 2368 __ j(zero, &setup_two_byte, Label::kNear);
2356 __ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset)); 2369 __ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset));
2357 __ lea(arg4, FieldOperand(rdi, rcx, times_1, SeqAsciiString::kHeaderSize)); 2370 __ lea(arg4, FieldOperand(rdi, rcx, times_1, SeqAsciiString::kHeaderSize));
2358 __ lea(arg3, FieldOperand(rdi, rbx, times_1, SeqAsciiString::kHeaderSize)); 2371 __ lea(arg3, FieldOperand(rdi, rbx, times_1, SeqAsciiString::kHeaderSize));
2359 __ jmp(&setup_rest); 2372 __ jmp(&setup_rest, Label::kNear);
2360 __ bind(&setup_two_byte); 2373 __ bind(&setup_two_byte);
2361 __ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset)); 2374 __ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset));
2362 __ lea(arg4, FieldOperand(rdi, rcx, times_2, SeqTwoByteString::kHeaderSize)); 2375 __ lea(arg4, FieldOperand(rdi, rcx, times_2, SeqTwoByteString::kHeaderSize));
2363 __ lea(arg3, FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize)); 2376 __ lea(arg3, FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize));
2364 2377
2365 __ bind(&setup_rest); 2378 __ bind(&setup_rest);
2366 // Argument 2: Previous index. 2379 // Argument 2: Previous index.
2367 __ movq(arg2, rbx); 2380 __ movq(arg2, rbx);
2368 2381
2369 // Argument 1: Subject string. 2382 // Argument 1: Subject string.
2370 #ifdef _WIN64 2383 #ifdef _WIN64
2371 __ movq(arg1, rdi); 2384 __ movq(arg1, rdi);
2372 #else 2385 #else
2373 // Already there in AMD64 calling convention. 2386 // Already there in AMD64 calling convention.
2374 ASSERT(arg1.is(rdi)); 2387 ASSERT(arg1.is(rdi));
2375 #endif 2388 #endif
2376 2389
2377 // Locate the code entry and call it. 2390 // Locate the code entry and call it.
2378 __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag)); 2391 __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag));
2379 __ call(r11); 2392 __ call(r11);
2380 2393
2381 __ LeaveApiExitFrame(); 2394 __ LeaveApiExitFrame();
2382 2395
2383 // Check the result. 2396 // Check the result.
2384 NearLabel success; 2397 Label success;
2385 Label exception; 2398 Label exception;
2386 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::SUCCESS)); 2399 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::SUCCESS));
2387 __ j(equal, &success); 2400 __ j(equal, &success, Label::kNear);
2388 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION)); 2401 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION));
2389 __ j(equal, &exception); 2402 __ j(equal, &exception);
2390 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE)); 2403 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE));
2391 // If none of the above, it can only be retry. 2404 // If none of the above, it can only be retry.
2392 // Handle that in the runtime system. 2405 // Handle that in the runtime system.
2393 __ j(not_equal, &runtime); 2406 __ j(not_equal, &runtime);
2394 2407
2395 // For failure return null. 2408 // For failure return null.
2396 __ LoadRoot(rax, Heap::kNullValueRootIndex); 2409 __ LoadRoot(rax, Heap::kNullValueRootIndex);
2397 __ ret(4 * kPointerSize); 2410 __ ret(4 * kPointerSize);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2430 __ movq(rcx, rbx); 2443 __ movq(rcx, rbx);
2431 __ RecordWrite(rcx, RegExpImpl::kLastInputOffset, rax, rdi, kDontSaveFPRegs); 2444 __ RecordWrite(rcx, RegExpImpl::kLastInputOffset, rax, rdi, kDontSaveFPRegs);
2432 2445
2433 // Get the static offsets vector filled by the native regexp code. 2446 // Get the static offsets vector filled by the native regexp code.
2434 __ LoadAddress(rcx, 2447 __ LoadAddress(rcx,
2435 ExternalReference::address_of_static_offsets_vector(isolate)); 2448 ExternalReference::address_of_static_offsets_vector(isolate));
2436 2449
2437 // rbx: last_match_info backing store (FixedArray) 2450 // rbx: last_match_info backing store (FixedArray)
2438 // rcx: offsets vector 2451 // rcx: offsets vector
2439 // rdx: number of capture registers 2452 // rdx: number of capture registers
2440 NearLabel next_capture, done; 2453 Label next_capture, done;
2441 // Capture register counter starts from number of capture registers and 2454 // Capture register counter starts from number of capture registers and
2442 // counts down until wraping after zero. 2455 // counts down until wraping after zero.
2443 __ bind(&next_capture); 2456 __ bind(&next_capture);
2444 __ subq(rdx, Immediate(1)); 2457 __ subq(rdx, Immediate(1));
2445 __ j(negative, &done); 2458 __ j(negative, &done, Label::kNear);
2446 // Read the value from the static offsets vector buffer and make it a smi. 2459 // Read the value from the static offsets vector buffer and make it a smi.
2447 __ movl(rdi, Operand(rcx, rdx, times_int_size, 0)); 2460 __ movl(rdi, Operand(rcx, rdx, times_int_size, 0));
2448 __ Integer32ToSmi(rdi, rdi); 2461 __ Integer32ToSmi(rdi, rdi);
2449 // Store the smi value in the last match info. 2462 // Store the smi value in the last match info.
2450 __ movq(FieldOperand(rbx, 2463 __ movq(FieldOperand(rbx,
2451 rdx, 2464 rdx,
2452 times_pointer_size, 2465 times_pointer_size,
2453 RegExpImpl::kFirstCaptureOffset), 2466 RegExpImpl::kFirstCaptureOffset),
2454 rdi); 2467 rdi);
2455 __ jmp(&next_capture); 2468 __ jmp(&next_capture);
(...skipping 12 matching lines...) Expand all
2468 Isolate::k_pending_exception_address, isolate); 2481 Isolate::k_pending_exception_address, isolate);
2469 Operand pending_exception_operand = 2482 Operand pending_exception_operand =
2470 masm->ExternalOperand(pending_exception_address, rbx); 2483 masm->ExternalOperand(pending_exception_address, rbx);
2471 __ movq(rax, pending_exception_operand); 2484 __ movq(rax, pending_exception_operand);
2472 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); 2485 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
2473 __ cmpq(rax, rdx); 2486 __ cmpq(rax, rdx);
2474 __ j(equal, &runtime); 2487 __ j(equal, &runtime);
2475 __ movq(pending_exception_operand, rdx); 2488 __ movq(pending_exception_operand, rdx);
2476 2489
2477 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); 2490 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex);
2478 NearLabel termination_exception; 2491 Label termination_exception;
2479 __ j(equal, &termination_exception); 2492 __ j(equal, &termination_exception, Label::kNear);
2480 __ Throw(rax); 2493 __ Throw(rax);
2481 2494
2482 __ bind(&termination_exception); 2495 __ bind(&termination_exception);
2483 __ ThrowUncatchable(TERMINATION, rax); 2496 __ ThrowUncatchable(TERMINATION, rax);
2484 2497
2485 // Do the runtime call to execute the regexp. 2498 // Do the runtime call to execute the regexp.
2486 __ bind(&runtime); 2499 __ bind(&runtime);
2487 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); 2500 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
2488 #endif // V8_INTERPRETED_REGEXP 2501 #endif // V8_INTERPRETED_REGEXP
2489 } 2502 }
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
2597 2610
2598 // Calculate the entry in the number string cache. The hash value in the 2611 // Calculate the entry in the number string cache. The hash value in the
2599 // number string cache for smis is just the smi value, and the hash for 2612 // number string cache for smis is just the smi value, and the hash for
2600 // doubles is the xor of the upper and lower words. See 2613 // doubles is the xor of the upper and lower words. See
2601 // Heap::GetNumberStringCache. 2614 // Heap::GetNumberStringCache.
2602 Label is_smi; 2615 Label is_smi;
2603 Label load_result_from_cache; 2616 Label load_result_from_cache;
2604 Factory* factory = masm->isolate()->factory(); 2617 Factory* factory = masm->isolate()->factory();
2605 if (!object_is_smi) { 2618 if (!object_is_smi) {
2606 __ JumpIfSmi(object, &is_smi); 2619 __ JumpIfSmi(object, &is_smi);
2607 __ CheckMap(object, factory->heap_number_map(), not_found, true); 2620 __ CheckMap(object,
2621 factory->heap_number_map(),
2622 not_found,
2623 DONT_DO_SMI_CHECK);
2608 2624
2609 STATIC_ASSERT(8 == kDoubleSize); 2625 STATIC_ASSERT(8 == kDoubleSize);
2610 __ movl(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); 2626 __ movl(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4));
2611 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset)); 2627 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset));
2612 GenerateConvertHashCodeToIndex(masm, scratch, mask); 2628 GenerateConvertHashCodeToIndex(masm, scratch, mask);
2613 2629
2614 Register index = scratch; 2630 Register index = scratch;
2615 Register probe = mask; 2631 Register probe = mask;
2616 __ movq(probe, 2632 __ movq(probe,
2617 FieldOperand(number_string_cache, 2633 FieldOperand(number_string_cache,
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
2712 __ bind(&ok); 2728 __ bind(&ok);
2713 } 2729 }
2714 2730
2715 // The compare stub returns a positive, negative, or zero 64-bit integer 2731 // The compare stub returns a positive, negative, or zero 64-bit integer
2716 // value in rax, corresponding to result of comparing the two inputs. 2732 // value in rax, corresponding to result of comparing the two inputs.
2717 // NOTICE! This code is only reached after a smi-fast-case check, so 2733 // NOTICE! This code is only reached after a smi-fast-case check, so
2718 // it is certain that at least one operand isn't a smi. 2734 // it is certain that at least one operand isn't a smi.
2719 2735
2720 // Two identical objects are equal unless they are both NaN or undefined. 2736 // Two identical objects are equal unless they are both NaN or undefined.
2721 { 2737 {
2722 NearLabel not_identical; 2738 Label not_identical;
2723 __ cmpq(rax, rdx); 2739 __ cmpq(rax, rdx);
2724 __ j(not_equal, &not_identical); 2740 __ j(not_equal, &not_identical, Label::kNear);
2725 2741
2726 if (cc_ != equal) { 2742 if (cc_ != equal) {
2727 // Check for undefined. undefined OP undefined is false even though 2743 // Check for undefined. undefined OP undefined is false even though
2728 // undefined == undefined. 2744 // undefined == undefined.
2729 NearLabel check_for_nan; 2745 Label check_for_nan;
2730 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); 2746 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex);
2731 __ j(not_equal, &check_for_nan); 2747 __ j(not_equal, &check_for_nan, Label::kNear);
2732 __ Set(rax, NegativeComparisonResult(cc_)); 2748 __ Set(rax, NegativeComparisonResult(cc_));
2733 __ ret(0); 2749 __ ret(0);
2734 __ bind(&check_for_nan); 2750 __ bind(&check_for_nan);
2735 } 2751 }
2736 2752
2737 // Test for NaN. Sadly, we can't just compare to FACTORY->nan_value(), 2753 // Test for NaN. Sadly, we can't just compare to FACTORY->nan_value(),
2738 // so we do the second best thing - test it ourselves. 2754 // so we do the second best thing - test it ourselves.
2739 // Note: if cc_ != equal, never_nan_nan_ is not used. 2755 // Note: if cc_ != equal, never_nan_nan_ is not used.
2740 // We cannot set rax to EQUAL until just before return because 2756 // We cannot set rax to EQUAL until just before return because
2741 // rax must be unchanged on jump to not_identical. 2757 // rax must be unchanged on jump to not_identical.
2742 if (never_nan_nan_ && (cc_ == equal)) { 2758 if (never_nan_nan_ && (cc_ == equal)) {
2743 __ Set(rax, EQUAL); 2759 __ Set(rax, EQUAL);
2744 __ ret(0); 2760 __ ret(0);
2745 } else { 2761 } else {
2746 NearLabel heap_number; 2762 Label heap_number;
2747 // If it's not a heap number, then return equal for (in)equality operator. 2763 // If it's not a heap number, then return equal for (in)equality operator.
2748 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), 2764 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
2749 factory->heap_number_map()); 2765 factory->heap_number_map());
2750 __ j(equal, &heap_number); 2766 __ j(equal, &heap_number, Label::kNear);
2751 if (cc_ != equal) { 2767 if (cc_ != equal) {
2752 // Call runtime on identical JSObjects. Otherwise return equal. 2768 // Call runtime on identical JSObjects. Otherwise return equal.
2753 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx); 2769 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx);
2754 __ j(above_equal, &not_identical); 2770 __ j(above_equal, &not_identical, Label::kNear);
2755 } 2771 }
2756 __ Set(rax, EQUAL); 2772 __ Set(rax, EQUAL);
2757 __ ret(0); 2773 __ ret(0);
2758 2774
2759 __ bind(&heap_number); 2775 __ bind(&heap_number);
2760 // It is a heap number, so return equal if it's not NaN. 2776 // It is a heap number, so return equal if it's not NaN.
2761 // For NaN, return 1 for every condition except greater and 2777 // For NaN, return 1 for every condition except greater and
2762 // greater-equal. Return -1 for them, so the comparison yields 2778 // greater-equal. Return -1 for them, so the comparison yields
2763 // false for all conditions except not-equal. 2779 // false for all conditions except not-equal.
2764 __ Set(rax, EQUAL); 2780 __ Set(rax, EQUAL);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2800 2816
2801 __ bind(&not_smis); 2817 __ bind(&not_smis);
2802 } 2818 }
2803 2819
2804 // If either operand is a JSObject or an oddball value, then they are not 2820 // If either operand is a JSObject or an oddball value, then they are not
2805 // equal since their pointers are different 2821 // equal since their pointers are different
2806 // There is no test for undetectability in strict equality. 2822 // There is no test for undetectability in strict equality.
2807 2823
2808 // If the first object is a JS object, we have done pointer comparison. 2824 // If the first object is a JS object, we have done pointer comparison.
2809 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 2825 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
2810 NearLabel first_non_object; 2826 Label first_non_object;
2811 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx); 2827 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx);
2812 __ j(below, &first_non_object); 2828 __ j(below, &first_non_object, Label::kNear);
2813 // Return non-zero (eax (not rax) is not zero) 2829 // Return non-zero (eax (not rax) is not zero)
2814 Label return_not_equal; 2830 Label return_not_equal;
2815 STATIC_ASSERT(kHeapObjectTag != 0); 2831 STATIC_ASSERT(kHeapObjectTag != 0);
2816 __ bind(&return_not_equal); 2832 __ bind(&return_not_equal);
2817 __ ret(0); 2833 __ ret(0);
2818 2834
2819 __ bind(&first_non_object); 2835 __ bind(&first_non_object);
2820 // Check for oddballs: true, false, null, undefined. 2836 // Check for oddballs: true, false, null, undefined.
2821 __ CmpInstanceType(rcx, ODDBALL_TYPE); 2837 __ CmpInstanceType(rcx, ODDBALL_TYPE);
2822 __ j(equal, &return_not_equal); 2838 __ j(equal, &return_not_equal);
2823 2839
2824 __ CmpObjectType(rdx, FIRST_JS_OBJECT_TYPE, rcx); 2840 __ CmpObjectType(rdx, FIRST_JS_OBJECT_TYPE, rcx);
2825 __ j(above_equal, &return_not_equal); 2841 __ j(above_equal, &return_not_equal);
2826 2842
2827 // Check for oddballs: true, false, null, undefined. 2843 // Check for oddballs: true, false, null, undefined.
2828 __ CmpInstanceType(rcx, ODDBALL_TYPE); 2844 __ CmpInstanceType(rcx, ODDBALL_TYPE);
2829 __ j(equal, &return_not_equal); 2845 __ j(equal, &return_not_equal);
2830 2846
2831 // Fall through to the general case. 2847 // Fall through to the general case.
2832 } 2848 }
2833 __ bind(&slow); 2849 __ bind(&slow);
2834 } 2850 }
2835 2851
2836 // Generate the number comparison code. 2852 // Generate the number comparison code.
2837 if (include_number_compare_) { 2853 if (include_number_compare_) {
2838 Label non_number_comparison; 2854 Label non_number_comparison;
2839 NearLabel unordered; 2855 Label unordered;
2840 FloatingPointHelper::LoadSSE2UnknownOperands(masm, &non_number_comparison); 2856 FloatingPointHelper::LoadSSE2UnknownOperands(masm, &non_number_comparison);
2841 __ xorl(rax, rax); 2857 __ xorl(rax, rax);
2842 __ xorl(rcx, rcx); 2858 __ xorl(rcx, rcx);
2843 __ ucomisd(xmm0, xmm1); 2859 __ ucomisd(xmm0, xmm1);
2844 2860
2845 // Don't base result on EFLAGS when a NaN is involved. 2861 // Don't base result on EFLAGS when a NaN is involved.
2846 __ j(parity_even, &unordered); 2862 __ j(parity_even, &unordered, Label::kNear);
2847 // Return a result of -1, 0, or 1, based on EFLAGS. 2863 // Return a result of -1, 0, or 1, based on EFLAGS.
2848 __ setcc(above, rax); 2864 __ setcc(above, rax);
2849 __ setcc(below, rcx); 2865 __ setcc(below, rcx);
2850 __ subq(rax, rcx); 2866 __ subq(rax, rcx);
2851 __ ret(0); 2867 __ ret(0);
2852 2868
2853 // If one of the numbers was NaN, then the result is always false. 2869 // If one of the numbers was NaN, then the result is always false.
2854 // The cc is never not-equal. 2870 // The cc is never not-equal.
2855 __ bind(&unordered); 2871 __ bind(&unordered);
2856 ASSERT(cc_ != not_equal); 2872 ASSERT(cc_ != not_equal);
(...skipping 19 matching lines...) Expand all
2876 // non-zero value, which indicates not equal, so just return. 2892 // non-zero value, which indicates not equal, so just return.
2877 __ ret(0); 2893 __ ret(0);
2878 } 2894 }
2879 2895
2880 __ bind(&check_for_strings); 2896 __ bind(&check_for_strings);
2881 2897
2882 __ JumpIfNotBothSequentialAsciiStrings( 2898 __ JumpIfNotBothSequentialAsciiStrings(
2883 rdx, rax, rcx, rbx, &check_unequal_objects); 2899 rdx, rax, rcx, rbx, &check_unequal_objects);
2884 2900
2885 // Inline comparison of ascii strings. 2901 // Inline comparison of ascii strings.
2886 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, 2902 if (cc_ == equal) {
2903 StringCompareStub::GenerateFlatAsciiStringEquals(masm,
2887 rdx, 2904 rdx,
2888 rax, 2905 rax,
2889 rcx, 2906 rcx,
2890 rbx, 2907 rbx);
2891 rdi, 2908 } else {
2892 r8); 2909 StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
2910 rdx,
2911 rax,
2912 rcx,
2913 rbx,
2914 rdi,
2915 r8);
2916 }
2893 2917
2894 #ifdef DEBUG 2918 #ifdef DEBUG
2895 __ Abort("Unexpected fall-through from string comparison"); 2919 __ Abort("Unexpected fall-through from string comparison");
2896 #endif 2920 #endif
2897 2921
2898 __ bind(&check_unequal_objects); 2922 __ bind(&check_unequal_objects);
2899 if (cc_ == equal && !strict_) { 2923 if (cc_ == equal && !strict_) {
2900 // Not strict equality. Objects are unequal if 2924 // Not strict equality. Objects are unequal if
2901 // they are both JSObjects and not undetectable, 2925 // they are both JSObjects and not undetectable,
2902 // and their pointers are different. 2926 // and their pointers are different.
2903 NearLabel not_both_objects, return_unequal; 2927 Label not_both_objects, return_unequal;
2904 // At most one is a smi, so we can test for smi by adding the two. 2928 // At most one is a smi, so we can test for smi by adding the two.
2905 // A smi plus a heap object has the low bit set, a heap object plus 2929 // A smi plus a heap object has the low bit set, a heap object plus
2906 // a heap object has the low bit clear. 2930 // a heap object has the low bit clear.
2907 STATIC_ASSERT(kSmiTag == 0); 2931 STATIC_ASSERT(kSmiTag == 0);
2908 STATIC_ASSERT(kSmiTagMask == 1); 2932 STATIC_ASSERT(kSmiTagMask == 1);
2909 __ lea(rcx, Operand(rax, rdx, times_1, 0)); 2933 __ lea(rcx, Operand(rax, rdx, times_1, 0));
2910 __ testb(rcx, Immediate(kSmiTagMask)); 2934 __ testb(rcx, Immediate(kSmiTagMask));
2911 __ j(not_zero, &not_both_objects); 2935 __ j(not_zero, &not_both_objects, Label::kNear);
2912 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); 2936 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx);
2913 __ j(below, &not_both_objects); 2937 __ j(below, &not_both_objects, Label::kNear);
2914 __ CmpObjectType(rdx, FIRST_JS_OBJECT_TYPE, rcx); 2938 __ CmpObjectType(rdx, FIRST_JS_OBJECT_TYPE, rcx);
2915 __ j(below, &not_both_objects); 2939 __ j(below, &not_both_objects, Label::kNear);
2916 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2940 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2917 Immediate(1 << Map::kIsUndetectable)); 2941 Immediate(1 << Map::kIsUndetectable));
2918 __ j(zero, &return_unequal); 2942 __ j(zero, &return_unequal, Label::kNear);
2919 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), 2943 __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
2920 Immediate(1 << Map::kIsUndetectable)); 2944 Immediate(1 << Map::kIsUndetectable));
2921 __ j(zero, &return_unequal); 2945 __ j(zero, &return_unequal, Label::kNear);
2922 // The objects are both undetectable, so they both compare as the value 2946 // The objects are both undetectable, so they both compare as the value
2923 // undefined, and are equal. 2947 // undefined, and are equal.
2924 __ Set(rax, EQUAL); 2948 __ Set(rax, EQUAL);
2925 __ bind(&return_unequal); 2949 __ bind(&return_unequal);
2926 // Return non-equal by returning the non-zero object pointer in rax, 2950 // Return non-equal by returning the non-zero object pointer in rax,
2927 // or return equal if we fell through to here. 2951 // or return equal if we fell through to here.
2928 __ ret(0); 2952 __ ret(0);
2929 __ bind(&not_both_objects); 2953 __ bind(&not_both_objects);
2930 } 2954 }
2931 2955
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
3141 __ testl(rcx, Immediate(kFailureTagMask)); 3165 __ testl(rcx, Immediate(kFailureTagMask));
3142 __ j(zero, &failure_returned); 3166 __ j(zero, &failure_returned);
3143 3167
3144 // Exit the JavaScript to C++ exit frame. 3168 // Exit the JavaScript to C++ exit frame.
3145 __ LeaveExitFrame(save_doubles_); 3169 __ LeaveExitFrame(save_doubles_);
3146 __ ret(0); 3170 __ ret(0);
3147 3171
3148 // Handling of failure. 3172 // Handling of failure.
3149 __ bind(&failure_returned); 3173 __ bind(&failure_returned);
3150 3174
3151 NearLabel retry; 3175 Label retry;
3152 // If the returned exception is RETRY_AFTER_GC continue at retry label 3176 // If the returned exception is RETRY_AFTER_GC continue at retry label
3153 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); 3177 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
3154 __ testl(rax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); 3178 __ testl(rax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
3155 __ j(zero, &retry); 3179 __ j(zero, &retry, Label::kNear);
3156 3180
3157 // Special handling of out of memory exceptions. 3181 // Special handling of out of memory exceptions.
3158 __ movq(kScratchRegister, Failure::OutOfMemoryException(), RelocInfo::NONE); 3182 __ movq(kScratchRegister, Failure::OutOfMemoryException(), RelocInfo::NONE);
3159 __ cmpq(rax, kScratchRegister); 3183 __ cmpq(rax, kScratchRegister);
3160 __ j(equal, throw_out_of_memory_exception); 3184 __ j(equal, throw_out_of_memory_exception);
3161 3185
3162 // Retrieve the pending exception and clear the variable. 3186 // Retrieve the pending exception and clear the variable.
3163 ExternalReference pending_exception_address( 3187 ExternalReference pending_exception_address(
3164 Isolate::k_pending_exception_address, masm->isolate()); 3188 Isolate::k_pending_exception_address, masm->isolate());
3165 Operand pending_exception_operand = 3189 Operand pending_exception_operand =
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
3308 Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp); 3332 Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp);
3309 __ push(c_entry_fp_operand); 3333 __ push(c_entry_fp_operand);
3310 } 3334 }
3311 3335
3312 #ifdef ENABLE_LOGGING_AND_PROFILING 3336 #ifdef ENABLE_LOGGING_AND_PROFILING
3313 // If this is the outermost JS call, set js_entry_sp value. 3337 // If this is the outermost JS call, set js_entry_sp value.
3314 ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address, isolate); 3338 ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address, isolate);
3315 __ Load(rax, js_entry_sp); 3339 __ Load(rax, js_entry_sp);
3316 __ testq(rax, rax); 3340 __ testq(rax, rax);
3317 __ j(not_zero, &not_outermost_js); 3341 __ j(not_zero, &not_outermost_js);
3342 __ Push(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME));
3318 __ movq(rax, rbp); 3343 __ movq(rax, rbp);
3319 __ Store(js_entry_sp, rax); 3344 __ Store(js_entry_sp, rax);
3345 Label cont;
3346 __ jmp(&cont);
3320 __ bind(&not_outermost_js); 3347 __ bind(&not_outermost_js);
3348 __ Push(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME));
3349 __ bind(&cont);
3321 #endif 3350 #endif
3322 3351
3323 // Call a faked try-block that does the invoke. 3352 // Call a faked try-block that does the invoke.
3324 __ call(&invoke); 3353 __ call(&invoke);
3325 3354
3326 // Caught exception: Store result (exception) in the pending 3355 // Caught exception: Store result (exception) in the pending
3327 // exception field in the JSEnv and return a failure sentinel. 3356 // exception field in the JSEnv and return a failure sentinel.
3328 ExternalReference pending_exception(Isolate::k_pending_exception_address, 3357 ExternalReference pending_exception(Isolate::k_pending_exception_address,
3329 isolate); 3358 isolate);
3330 __ Store(pending_exception, rax); 3359 __ Store(pending_exception, rax);
(...skipping 21 matching lines...) Expand all
3352 isolate); 3381 isolate);
3353 __ Load(rax, construct_entry); 3382 __ Load(rax, construct_entry);
3354 } else { 3383 } else {
3355 ExternalReference entry(Builtins::kJSEntryTrampoline, isolate); 3384 ExternalReference entry(Builtins::kJSEntryTrampoline, isolate);
3356 __ Load(rax, entry); 3385 __ Load(rax, entry);
3357 } 3386 }
3358 __ lea(kScratchRegister, FieldOperand(rax, Code::kHeaderSize)); 3387 __ lea(kScratchRegister, FieldOperand(rax, Code::kHeaderSize));
3359 __ call(kScratchRegister); 3388 __ call(kScratchRegister);
3360 3389
3361 // Unlink this frame from the handler chain. 3390 // Unlink this frame from the handler chain.
3362 Operand handler_operand = 3391 __ PopTryHandler();
3363 masm->ExternalOperand(ExternalReference(Isolate::k_handler_address,
3364 isolate));
3365 __ pop(handler_operand);
3366 // Pop next_sp.
3367 __ addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize));
3368 3392
3393 __ bind(&exit);
3369 #ifdef ENABLE_LOGGING_AND_PROFILING 3394 #ifdef ENABLE_LOGGING_AND_PROFILING
3370 // If current RBP value is the same as js_entry_sp value, it means that 3395 // Check if the current stack frame is marked as the outermost JS frame.
3371 // the current function is the outermost. 3396 __ pop(rbx);
3397 __ Cmp(rbx, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME));
3398 __ j(not_equal, &not_outermost_js_2);
3372 __ movq(kScratchRegister, js_entry_sp); 3399 __ movq(kScratchRegister, js_entry_sp);
3373 __ cmpq(rbp, Operand(kScratchRegister, 0));
3374 __ j(not_equal, &not_outermost_js_2);
3375 __ movq(Operand(kScratchRegister, 0), Immediate(0)); 3400 __ movq(Operand(kScratchRegister, 0), Immediate(0));
3376 __ bind(&not_outermost_js_2); 3401 __ bind(&not_outermost_js_2);
3377 #endif 3402 #endif
3378 3403
3379 // Restore the top frame descriptor from the stack. 3404 // Restore the top frame descriptor from the stack.
3380 __ bind(&exit); 3405 { Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp);
3381 {
3382 Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp);
3383 __ pop(c_entry_fp_operand); 3406 __ pop(c_entry_fp_operand);
3384 } 3407 }
3385 3408
3386 // Restore callee-saved registers (X64 conventions). 3409 // Restore callee-saved registers (X64 conventions).
3387 __ pop(rbx); 3410 __ pop(rbx);
3388 #ifdef _WIN64 3411 #ifdef _WIN64
3389 // Callee save on in Win64 ABI, arguments/volatile in AMD64 ABI. 3412 // Callee save on in Win64 ABI, arguments/volatile in AMD64 ABI.
3390 __ pop(rsi); 3413 __ pop(rsi);
3391 __ pop(rdi); 3414 __ pop(rdi);
3392 #endif 3415 #endif
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
3446 __ j(above, &slow); 3469 __ j(above, &slow);
3447 3470
3448 // Get the prototype of the function. 3471 // Get the prototype of the function.
3449 __ movq(rdx, Operand(rsp, 1 * kPointerSize + extra_stack_space)); 3472 __ movq(rdx, Operand(rsp, 1 * kPointerSize + extra_stack_space));
3450 // rdx is function, rax is map. 3473 // rdx is function, rax is map.
3451 3474
3452 // If there is a call site cache don't look in the global cache, but do the 3475 // If there is a call site cache don't look in the global cache, but do the
3453 // real lookup and update the call site cache. 3476 // real lookup and update the call site cache.
3454 if (!HasCallSiteInlineCheck()) { 3477 if (!HasCallSiteInlineCheck()) {
3455 // Look up the function and the map in the instanceof cache. 3478 // Look up the function and the map in the instanceof cache.
3456 NearLabel miss; 3479 Label miss;
3457 __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); 3480 __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
3458 __ j(not_equal, &miss); 3481 __ j(not_equal, &miss, Label::kNear);
3459 __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex); 3482 __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex);
3460 __ j(not_equal, &miss); 3483 __ j(not_equal, &miss, Label::kNear);
3461 __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); 3484 __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
3462 __ ret(2 * kPointerSize); 3485 __ ret(2 * kPointerSize);
3463 __ bind(&miss); 3486 __ bind(&miss);
3464 } 3487 }
3465 3488
3466 __ TryGetFunctionPrototype(rdx, rbx, &slow); 3489 __ TryGetFunctionPrototype(rdx, rbx, &slow);
3467 3490
3468 // Check that the function prototype is a JS object. 3491 // Check that the function prototype is a JS object.
3469 __ JumpIfSmi(rbx, &slow); 3492 __ JumpIfSmi(rbx, &slow);
3470 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, kScratchRegister); 3493 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, kScratchRegister);
(...skipping 16 matching lines...) Expand all
3487 if (FLAG_debug_code) { 3510 if (FLAG_debug_code) {
3488 __ movl(rdi, Immediate(kWordBeforeMapCheckValue)); 3511 __ movl(rdi, Immediate(kWordBeforeMapCheckValue));
3489 __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi); 3512 __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi);
3490 __ Assert(equal, "InstanceofStub unexpected call site cache (check)."); 3513 __ Assert(equal, "InstanceofStub unexpected call site cache (check).");
3491 } 3514 }
3492 } 3515 }
3493 3516
3494 __ movq(rcx, FieldOperand(rax, Map::kPrototypeOffset)); 3517 __ movq(rcx, FieldOperand(rax, Map::kPrototypeOffset));
3495 3518
3496 // Loop through the prototype chain looking for the function prototype. 3519 // Loop through the prototype chain looking for the function prototype.
3497 NearLabel loop, is_instance, is_not_instance; 3520 Label loop, is_instance, is_not_instance;
3498 __ LoadRoot(kScratchRegister, Heap::kNullValueRootIndex); 3521 __ LoadRoot(kScratchRegister, Heap::kNullValueRootIndex);
3499 __ bind(&loop); 3522 __ bind(&loop);
3500 __ cmpq(rcx, rbx); 3523 __ cmpq(rcx, rbx);
3501 __ j(equal, &is_instance); 3524 __ j(equal, &is_instance, Label::kNear);
3502 __ cmpq(rcx, kScratchRegister); 3525 __ cmpq(rcx, kScratchRegister);
3503 // The code at is_not_instance assumes that kScratchRegister contains a 3526 // The code at is_not_instance assumes that kScratchRegister contains a
3504 // non-zero GCable value (the null object in this case). 3527 // non-zero GCable value (the null object in this case).
3505 __ j(equal, &is_not_instance); 3528 __ j(equal, &is_not_instance, Label::kNear);
3506 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); 3529 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
3507 __ movq(rcx, FieldOperand(rcx, Map::kPrototypeOffset)); 3530 __ movq(rcx, FieldOperand(rcx, Map::kPrototypeOffset));
3508 __ jmp(&loop); 3531 __ jmp(&loop);
3509 3532
3510 __ bind(&is_instance); 3533 __ bind(&is_instance);
3511 if (!HasCallSiteInlineCheck()) { 3534 if (!HasCallSiteInlineCheck()) {
3512 __ xorl(rax, rax); 3535 __ xorl(rax, rax);
3513 // Store bitwise zero in the cache. This is a Smi in GC terms. 3536 // Store bitwise zero in the cache. This is a Smi in GC terms.
3514 STATIC_ASSERT(kSmiTag == 0); 3537 STATIC_ASSERT(kSmiTag == 0);
3515 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); 3538 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
3724 3747
3725 3748
3726 void StringCharCodeAtGenerator::GenerateSlow( 3749 void StringCharCodeAtGenerator::GenerateSlow(
3727 MacroAssembler* masm, const RuntimeCallHelper& call_helper) { 3750 MacroAssembler* masm, const RuntimeCallHelper& call_helper) {
3728 __ Abort("Unexpected fallthrough to CharCodeAt slow case"); 3751 __ Abort("Unexpected fallthrough to CharCodeAt slow case");
3729 3752
3730 Factory* factory = masm->isolate()->factory(); 3753 Factory* factory = masm->isolate()->factory();
3731 // Index is not a smi. 3754 // Index is not a smi.
3732 __ bind(&index_not_smi_); 3755 __ bind(&index_not_smi_);
3733 // If index is a heap number, try converting it to an integer. 3756 // If index is a heap number, try converting it to an integer.
3734 __ CheckMap(index_, factory->heap_number_map(), index_not_number_, true); 3757 __ CheckMap(index_,
3758 factory->heap_number_map(),
3759 index_not_number_,
3760 DONT_DO_SMI_CHECK);
3735 call_helper.BeforeCall(masm); 3761 call_helper.BeforeCall(masm);
3736 __ push(object_); 3762 __ push(object_);
3737 __ push(index_); 3763 __ push(index_);
3738 __ push(index_); // Consumed by runtime conversion function. 3764 __ push(index_); // Consumed by runtime conversion function.
3739 if (index_flags_ == STRING_INDEX_IS_NUMBER) { 3765 if (index_flags_ == STRING_INDEX_IS_NUMBER) {
3740 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); 3766 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
3741 } else { 3767 } else {
3742 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); 3768 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
3743 // NumberToSmi discards numbers that are not exact integers. 3769 // NumberToSmi discards numbers that are not exact integers.
3744 __ CallRuntime(Runtime::kNumberToSmi, 1); 3770 __ CallRuntime(Runtime::kNumberToSmi, 1);
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
3864 GenerateConvertArgument(masm, 1 * kPointerSize, rdx, rbx, rcx, rdi, 3890 GenerateConvertArgument(masm, 1 * kPointerSize, rdx, rbx, rcx, rdi,
3865 &call_builtin); 3891 &call_builtin);
3866 builtin_id = Builtins::STRING_ADD_LEFT; 3892 builtin_id = Builtins::STRING_ADD_LEFT;
3867 } 3893 }
3868 } 3894 }
3869 3895
3870 // Both arguments are strings. 3896 // Both arguments are strings.
3871 // rax: first string 3897 // rax: first string
3872 // rdx: second string 3898 // rdx: second string
3873 // Check if either of the strings are empty. In that case return the other. 3899 // Check if either of the strings are empty. In that case return the other.
3874 NearLabel second_not_zero_length, both_not_zero_length; 3900 Label second_not_zero_length, both_not_zero_length;
3875 __ movq(rcx, FieldOperand(rdx, String::kLengthOffset)); 3901 __ movq(rcx, FieldOperand(rdx, String::kLengthOffset));
3876 __ SmiTest(rcx); 3902 __ SmiTest(rcx);
3877 __ j(not_zero, &second_not_zero_length); 3903 __ j(not_zero, &second_not_zero_length, Label::kNear);
3878 // Second string is empty, result is first string which is already in rax. 3904 // Second string is empty, result is first string which is already in rax.
3879 Counters* counters = masm->isolate()->counters(); 3905 Counters* counters = masm->isolate()->counters();
3880 __ IncrementCounter(counters->string_add_native(), 1); 3906 __ IncrementCounter(counters->string_add_native(), 1);
3881 __ ret(2 * kPointerSize); 3907 __ ret(2 * kPointerSize);
3882 __ bind(&second_not_zero_length); 3908 __ bind(&second_not_zero_length);
3883 __ movq(rbx, FieldOperand(rax, String::kLengthOffset)); 3909 __ movq(rbx, FieldOperand(rax, String::kLengthOffset));
3884 __ SmiTest(rbx); 3910 __ SmiTest(rbx);
3885 __ j(not_zero, &both_not_zero_length); 3911 __ j(not_zero, &both_not_zero_length, Label::kNear);
3886 // First string is empty, result is second string which is in rdx. 3912 // First string is empty, result is second string which is in rdx.
3887 __ movq(rax, rdx); 3913 __ movq(rax, rdx);
3888 __ IncrementCounter(counters->string_add_native(), 1); 3914 __ IncrementCounter(counters->string_add_native(), 1);
3889 __ ret(2 * kPointerSize); 3915 __ ret(2 * kPointerSize);
3890 3916
3891 // Both strings are non-empty. 3917 // Both strings are non-empty.
3892 // rax: first string 3918 // rax: first string
3893 // rbx: length of first string 3919 // rbx: length of first string
3894 // rcx: length of second string 3920 // rcx: length of second string
3895 // rdx: second string 3921 // rdx: second string
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
4169 bool ascii) { 4195 bool ascii) {
4170 // Copy characters using rep movs of doublewords. Align destination on 4 byte 4196 // Copy characters using rep movs of doublewords. Align destination on 4 byte
4171 // boundary before starting rep movs. Copy remaining characters after running 4197 // boundary before starting rep movs. Copy remaining characters after running
4172 // rep movs. 4198 // rep movs.
4173 // Count is positive int32, dest and src are character pointers. 4199 // Count is positive int32, dest and src are character pointers.
4174 ASSERT(dest.is(rdi)); // rep movs destination 4200 ASSERT(dest.is(rdi)); // rep movs destination
4175 ASSERT(src.is(rsi)); // rep movs source 4201 ASSERT(src.is(rsi)); // rep movs source
4176 ASSERT(count.is(rcx)); // rep movs count 4202 ASSERT(count.is(rcx)); // rep movs count
4177 4203
4178 // Nothing to do for zero characters. 4204 // Nothing to do for zero characters.
4179 NearLabel done; 4205 Label done;
4180 __ testl(count, count); 4206 __ testl(count, count);
4181 __ j(zero, &done); 4207 __ j(zero, &done, Label::kNear);
4182 4208
4183 // Make count the number of bytes to copy. 4209 // Make count the number of bytes to copy.
4184 if (!ascii) { 4210 if (!ascii) {
4185 STATIC_ASSERT(2 == sizeof(uc16)); 4211 STATIC_ASSERT(2 == sizeof(uc16));
4186 __ addl(count, count); 4212 __ addl(count, count);
4187 } 4213 }
4188 4214
4189 // Don't enter the rep movs if there are less than 4 bytes to copy. 4215 // Don't enter the rep movs if there are less than 4 bytes to copy.
4190 NearLabel last_bytes; 4216 Label last_bytes;
4191 __ testl(count, Immediate(~7)); 4217 __ testl(count, Immediate(~7));
4192 __ j(zero, &last_bytes); 4218 __ j(zero, &last_bytes, Label::kNear);
4193 4219
4194 // Copy from edi to esi using rep movs instruction. 4220 // Copy from edi to esi using rep movs instruction.
4195 __ movl(kScratchRegister, count); 4221 __ movl(kScratchRegister, count);
4196 __ shr(count, Immediate(3)); // Number of doublewords to copy. 4222 __ shr(count, Immediate(3)); // Number of doublewords to copy.
4197 __ repmovsq(); 4223 __ repmovsq();
4198 4224
4199 // Find number of bytes left. 4225 // Find number of bytes left.
4200 __ movl(count, kScratchRegister); 4226 __ movl(count, kScratchRegister);
4201 __ and_(count, Immediate(7)); 4227 __ and_(count, Immediate(7));
4202 4228
4203 // Check if there are more bytes to copy. 4229 // Check if there are more bytes to copy.
4204 __ bind(&last_bytes); 4230 __ bind(&last_bytes);
4205 __ testl(count, count); 4231 __ testl(count, count);
4206 __ j(zero, &done); 4232 __ j(zero, &done, Label::kNear);
4207 4233
4208 // Copy remaining characters. 4234 // Copy remaining characters.
4209 Label loop; 4235 Label loop;
4210 __ bind(&loop); 4236 __ bind(&loop);
4211 __ movb(kScratchRegister, Operand(src, 0)); 4237 __ movb(kScratchRegister, Operand(src, 0));
4212 __ movb(Operand(dest, 0), kScratchRegister); 4238 __ movb(Operand(dest, 0), kScratchRegister);
4213 __ incq(src); 4239 __ incq(src);
4214 __ incq(dest); 4240 __ incq(dest);
4215 __ decl(count); 4241 __ decl(count);
4216 __ j(not_zero, &loop); 4242 __ j(not_zero, &loop);
4217 4243
4218 __ bind(&done); 4244 __ bind(&done);
4219 } 4245 }
4220 4246
4221 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, 4247 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
4222 Register c1, 4248 Register c1,
4223 Register c2, 4249 Register c2,
4224 Register scratch1, 4250 Register scratch1,
4225 Register scratch2, 4251 Register scratch2,
4226 Register scratch3, 4252 Register scratch3,
4227 Register scratch4, 4253 Register scratch4,
4228 Label* not_found) { 4254 Label* not_found) {
4229 // Register scratch3 is the general scratch register in this function. 4255 // Register scratch3 is the general scratch register in this function.
4230 Register scratch = scratch3; 4256 Register scratch = scratch3;
4231 4257
4232 // Make sure that both characters are not digits as such strings has a 4258 // Make sure that both characters are not digits as such strings has a
4233 // different hash algorithm. Don't try to look for these in the symbol table. 4259 // different hash algorithm. Don't try to look for these in the symbol table.
4234 NearLabel not_array_index; 4260 Label not_array_index;
4235 __ leal(scratch, Operand(c1, -'0')); 4261 __ leal(scratch, Operand(c1, -'0'));
4236 __ cmpl(scratch, Immediate(static_cast<int>('9' - '0'))); 4262 __ cmpl(scratch, Immediate(static_cast<int>('9' - '0')));
4237 __ j(above, &not_array_index); 4263 __ j(above, &not_array_index, Label::kNear);
4238 __ leal(scratch, Operand(c2, -'0')); 4264 __ leal(scratch, Operand(c2, -'0'));
4239 __ cmpl(scratch, Immediate(static_cast<int>('9' - '0'))); 4265 __ cmpl(scratch, Immediate(static_cast<int>('9' - '0')));
4240 __ j(below_equal, not_found); 4266 __ j(below_equal, not_found);
4241 4267
4242 __ bind(&not_array_index); 4268 __ bind(&not_array_index);
4243 // Calculate the two character string hash. 4269 // Calculate the two character string hash.
4244 Register hash = scratch1; 4270 Register hash = scratch1;
4245 GenerateHashInit(masm, hash, c1, scratch); 4271 GenerateHashInit(masm, hash, c1, scratch);
4246 GenerateHashAddCharacter(masm, hash, c2, scratch); 4272 GenerateHashAddCharacter(masm, hash, c2, scratch);
4247 GenerateHashGetHash(masm, hash, scratch); 4273 GenerateHashGetHash(masm, hash, scratch);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
4289 // Load the entry from the symbol table. 4315 // Load the entry from the symbol table.
4290 Register candidate = scratch; // Scratch register contains candidate. 4316 Register candidate = scratch; // Scratch register contains candidate.
4291 STATIC_ASSERT(SymbolTable::kEntrySize == 1); 4317 STATIC_ASSERT(SymbolTable::kEntrySize == 1);
4292 __ movq(candidate, 4318 __ movq(candidate,
4293 FieldOperand(symbol_table, 4319 FieldOperand(symbol_table,
4294 scratch, 4320 scratch,
4295 times_pointer_size, 4321 times_pointer_size,
4296 SymbolTable::kElementsStartOffset)); 4322 SymbolTable::kElementsStartOffset));
4297 4323
4298 // If entry is undefined no string with this hash can be found. 4324 // If entry is undefined no string with this hash can be found.
4299 NearLabel is_string; 4325 Label is_string;
4300 __ CmpObjectType(candidate, ODDBALL_TYPE, map); 4326 __ CmpObjectType(candidate, ODDBALL_TYPE, map);
4301 __ j(not_equal, &is_string); 4327 __ j(not_equal, &is_string, Label::kNear);
4302 4328
4303 __ CompareRoot(candidate, Heap::kUndefinedValueRootIndex); 4329 __ CompareRoot(candidate, Heap::kUndefinedValueRootIndex);
4304 __ j(equal, not_found); 4330 __ j(equal, not_found);
4305 // Must be null (deleted entry). 4331 // Must be null (deleted entry).
4306 __ jmp(&next_probe[i]); 4332 __ jmp(&next_probe[i]);
4307 4333
4308 __ bind(&is_string); 4334 __ bind(&is_string);
4309 4335
4310 // If length is not 2 the string is not a candidate. 4336 // If length is not 2 the string is not a candidate.
4311 __ SmiCompare(FieldOperand(candidate, String::kLengthOffset), 4337 __ SmiCompare(FieldOperand(candidate, String::kLengthOffset),
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
4535 __ bind(&return_rax); 4561 __ bind(&return_rax);
4536 __ IncrementCounter(counters->sub_string_native(), 1); 4562 __ IncrementCounter(counters->sub_string_native(), 1);
4537 __ ret(kArgumentsSize); 4563 __ ret(kArgumentsSize);
4538 4564
4539 // Just jump to runtime to create the sub string. 4565 // Just jump to runtime to create the sub string.
4540 __ bind(&runtime); 4566 __ bind(&runtime);
4541 __ TailCallRuntime(Runtime::kSubString, 3, 1); 4567 __ TailCallRuntime(Runtime::kSubString, 3, 1);
4542 } 4568 }
4543 4569
4544 4570
4571 void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm,
4572 Register left,
4573 Register right,
4574 Register scratch1,
4575 Register scratch2) {
4576 Register length = scratch1;
4577
4578 // Compare lengths.
4579 Label check_zero_length;
4580 __ movq(length, FieldOperand(left, String::kLengthOffset));
4581 __ SmiCompare(length, FieldOperand(right, String::kLengthOffset));
4582 __ j(equal, &check_zero_length, Label::kNear);
4583 __ Move(rax, Smi::FromInt(NOT_EQUAL));
4584 __ ret(0);
4585
4586 // Check if the length is zero.
4587 Label compare_chars;
4588 __ bind(&check_zero_length);
4589 STATIC_ASSERT(kSmiTag == 0);
4590 __ SmiTest(length);
4591 __ j(not_zero, &compare_chars, Label::kNear);
4592 __ Move(rax, Smi::FromInt(EQUAL));
4593 __ ret(0);
4594
4595 // Compare characters.
4596 __ bind(&compare_chars);
4597 Label strings_not_equal;
4598 GenerateAsciiCharsCompareLoop(masm, left, right, length, scratch2,
4599 &strings_not_equal, Label::kNear);
4600
4601 // Characters are equal.
4602 __ Move(rax, Smi::FromInt(EQUAL));
4603 __ ret(0);
4604
4605 // Characters are not equal.
4606 __ bind(&strings_not_equal);
4607 __ Move(rax, Smi::FromInt(NOT_EQUAL));
4608 __ ret(0);
4609 }
4610
4611
4545 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 4612 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
4546 Register left, 4613 Register left,
4547 Register right, 4614 Register right,
4548 Register scratch1, 4615 Register scratch1,
4549 Register scratch2, 4616 Register scratch2,
4550 Register scratch3, 4617 Register scratch3,
4551 Register scratch4) { 4618 Register scratch4) {
4552 // Ensure that you can always subtract a string length from a non-negative 4619 // Ensure that you can always subtract a string length from a non-negative
4553 // number (e.g. another length). 4620 // number (e.g. another length).
4554 STATIC_ASSERT(String::kMaxLength < 0x7fffffff); 4621 STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
4555 4622
4556 // Find minimum length and length difference. 4623 // Find minimum length and length difference.
4557 __ movq(scratch1, FieldOperand(left, String::kLengthOffset)); 4624 __ movq(scratch1, FieldOperand(left, String::kLengthOffset));
4558 __ movq(scratch4, scratch1); 4625 __ movq(scratch4, scratch1);
4559 __ SmiSub(scratch4, 4626 __ SmiSub(scratch4,
4560 scratch4, 4627 scratch4,
4561 FieldOperand(right, String::kLengthOffset)); 4628 FieldOperand(right, String::kLengthOffset));
4562 // Register scratch4 now holds left.length - right.length. 4629 // Register scratch4 now holds left.length - right.length.
4563 const Register length_difference = scratch4; 4630 const Register length_difference = scratch4;
4564 NearLabel left_shorter; 4631 Label left_shorter;
4565 __ j(less, &left_shorter); 4632 __ j(less, &left_shorter, Label::kNear);
4566 // The right string isn't longer that the left one. 4633 // The right string isn't longer that the left one.
4567 // Get the right string's length by subtracting the (non-negative) difference 4634 // Get the right string's length by subtracting the (non-negative) difference
4568 // from the left string's length. 4635 // from the left string's length.
4569 __ SmiSub(scratch1, scratch1, length_difference); 4636 __ SmiSub(scratch1, scratch1, length_difference);
4570 __ bind(&left_shorter); 4637 __ bind(&left_shorter);
4571 // Register scratch1 now holds Min(left.length, right.length). 4638 // Register scratch1 now holds Min(left.length, right.length).
4572 const Register min_length = scratch1; 4639 const Register min_length = scratch1;
4573 4640
4574 NearLabel compare_lengths; 4641 Label compare_lengths;
4575 // If min-length is zero, go directly to comparing lengths. 4642 // If min-length is zero, go directly to comparing lengths.
4576 __ SmiTest(min_length); 4643 __ SmiTest(min_length);
4577 __ j(zero, &compare_lengths); 4644 __ j(zero, &compare_lengths, Label::kNear);
4578 4645
4579 __ SmiToInteger32(min_length, min_length); 4646 // Compare loop.
4647 Label result_not_equal;
4648 GenerateAsciiCharsCompareLoop(masm, left, right, min_length, scratch2,
4649 &result_not_equal, Label::kNear);
4580 4650
4581 // Registers scratch2 and scratch3 are free.
4582 NearLabel result_not_equal;
4583 Label loop;
4584 {
4585 // Check characters 0 .. min_length - 1 in a loop.
4586 // Use scratch3 as loop index, min_length as limit and scratch2
4587 // for computation.
4588 const Register index = scratch3;
4589 __ Set(index, 0); // Index into strings.
4590 __ bind(&loop);
4591 // Compare characters.
4592 // TODO(lrn): Could we load more than one character at a time?
4593 __ movb(scratch2, FieldOperand(left,
4594 index,
4595 times_1,
4596 SeqAsciiString::kHeaderSize));
4597 // Increment index and use -1 modifier on next load to give
4598 // the previous load extra time to complete.
4599 __ addl(index, Immediate(1));
4600 __ cmpb(scratch2, FieldOperand(right,
4601 index,
4602 times_1,
4603 SeqAsciiString::kHeaderSize - 1));
4604 __ j(not_equal, &result_not_equal);
4605 __ cmpl(index, min_length);
4606 __ j(not_equal, &loop);
4607 }
4608 // Completed loop without finding different characters. 4651 // Completed loop without finding different characters.
4609 // Compare lengths (precomputed). 4652 // Compare lengths (precomputed).
4610 __ bind(&compare_lengths); 4653 __ bind(&compare_lengths);
4611 __ SmiTest(length_difference); 4654 __ SmiTest(length_difference);
4612 __ j(not_zero, &result_not_equal); 4655 __ j(not_zero, &result_not_equal, Label::kNear);
4613 4656
4614 // Result is EQUAL. 4657 // Result is EQUAL.
4615 __ Move(rax, Smi::FromInt(EQUAL)); 4658 __ Move(rax, Smi::FromInt(EQUAL));
4616 __ ret(0); 4659 __ ret(0);
4617 4660
4618 NearLabel result_greater; 4661 Label result_greater;
4619 __ bind(&result_not_equal); 4662 __ bind(&result_not_equal);
4620 // Unequal comparison of left to right, either character or length. 4663 // Unequal comparison of left to right, either character or length.
4621 __ j(greater, &result_greater); 4664 __ j(greater, &result_greater, Label::kNear);
4622 4665
4623 // Result is LESS. 4666 // Result is LESS.
4624 __ Move(rax, Smi::FromInt(LESS)); 4667 __ Move(rax, Smi::FromInt(LESS));
4625 __ ret(0); 4668 __ ret(0);
4626 4669
4627 // Result is GREATER. 4670 // Result is GREATER.
4628 __ bind(&result_greater); 4671 __ bind(&result_greater);
4629 __ Move(rax, Smi::FromInt(GREATER)); 4672 __ Move(rax, Smi::FromInt(GREATER));
4630 __ ret(0); 4673 __ ret(0);
4631 } 4674 }
4632 4675
4633 4676
4677 void StringCompareStub::GenerateAsciiCharsCompareLoop(
4678 MacroAssembler* masm,
4679 Register left,
4680 Register right,
4681 Register length,
4682 Register scratch,
4683 Label* chars_not_equal,
4684 Label::Distance near_jump) {
4685 // Change index to run from -length to -1 by adding length to string
4686 // start. This means that loop ends when index reaches zero, which
4687 // doesn't need an additional compare.
4688 __ SmiToInteger32(length, length);
4689 __ lea(left,
4690 FieldOperand(left, length, times_1, SeqAsciiString::kHeaderSize));
4691 __ lea(right,
4692 FieldOperand(right, length, times_1, SeqAsciiString::kHeaderSize));
4693 __ neg(length);
4694 Register index = length; // index = -length;
4695
4696 // Compare loop.
4697 Label loop;
4698 __ bind(&loop);
4699 __ movb(scratch, Operand(left, index, times_1, 0));
4700 __ cmpb(scratch, Operand(right, index, times_1, 0));
4701 __ j(not_equal, chars_not_equal, near_jump);
4702 __ addq(index, Immediate(1));
4703 __ j(not_zero, &loop);
4704 }
4705
4706
4634 void StringCompareStub::Generate(MacroAssembler* masm) { 4707 void StringCompareStub::Generate(MacroAssembler* masm) {
4635 Label runtime; 4708 Label runtime;
4636 4709
4637 // Stack frame on entry. 4710 // Stack frame on entry.
4638 // rsp[0]: return address 4711 // rsp[0]: return address
4639 // rsp[8]: right string 4712 // rsp[8]: right string
4640 // rsp[16]: left string 4713 // rsp[16]: left string
4641 4714
4642 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // left 4715 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // left
4643 __ movq(rax, Operand(rsp, 1 * kPointerSize)); // right 4716 __ movq(rax, Operand(rsp, 1 * kPointerSize)); // right
4644 4717
4645 // Check for identity. 4718 // Check for identity.
4646 NearLabel not_same; 4719 Label not_same;
4647 __ cmpq(rdx, rax); 4720 __ cmpq(rdx, rax);
4648 __ j(not_equal, &not_same); 4721 __ j(not_equal, &not_same, Label::kNear);
4649 __ Move(rax, Smi::FromInt(EQUAL)); 4722 __ Move(rax, Smi::FromInt(EQUAL));
4650 Counters* counters = masm->isolate()->counters(); 4723 Counters* counters = masm->isolate()->counters();
4651 __ IncrementCounter(counters->string_compare_native(), 1); 4724 __ IncrementCounter(counters->string_compare_native(), 1);
4652 __ ret(2 * kPointerSize); 4725 __ ret(2 * kPointerSize);
4653 4726
4654 __ bind(&not_same); 4727 __ bind(&not_same);
4655 4728
4656 // Check that both are sequential ASCII strings. 4729 // Check that both are sequential ASCII strings.
4657 __ JumpIfNotBothSequentialAsciiStrings(rdx, rax, rcx, rbx, &runtime); 4730 __ JumpIfNotBothSequentialAsciiStrings(rdx, rax, rcx, rbx, &runtime);
4658 4731
4659 // Inline comparison of ascii strings. 4732 // Inline comparison of ascii strings.
4660 __ IncrementCounter(counters->string_compare_native(), 1); 4733 __ IncrementCounter(counters->string_compare_native(), 1);
4661 // Drop arguments from the stack 4734 // Drop arguments from the stack
4662 __ pop(rcx); 4735 __ pop(rcx);
4663 __ addq(rsp, Immediate(2 * kPointerSize)); 4736 __ addq(rsp, Immediate(2 * kPointerSize));
4664 __ push(rcx); 4737 __ push(rcx);
4665 GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8); 4738 GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8);
4666 4739
4667 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 4740 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
4668 // tagged as a small integer. 4741 // tagged as a small integer.
4669 __ bind(&runtime); 4742 __ bind(&runtime);
4670 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 4743 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
4671 } 4744 }
4672 4745
4673 4746
4674 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { 4747 void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
4675 ASSERT(state_ == CompareIC::SMIS); 4748 ASSERT(state_ == CompareIC::SMIS);
4676 NearLabel miss; 4749 Label miss;
4677 __ JumpIfNotBothSmi(rdx, rax, &miss); 4750 __ JumpIfNotBothSmi(rdx, rax, &miss, Label::kNear);
4678 4751
4679 if (GetCondition() == equal) { 4752 if (GetCondition() == equal) {
4680 // For equality we do not care about the sign of the result. 4753 // For equality we do not care about the sign of the result.
4681 __ subq(rax, rdx); 4754 __ subq(rax, rdx);
4682 } else { 4755 } else {
4683 NearLabel done; 4756 Label done;
4684 __ subq(rdx, rax); 4757 __ subq(rdx, rax);
4685 __ j(no_overflow, &done); 4758 __ j(no_overflow, &done, Label::kNear);
4686 // Correct sign of result in case of overflow. 4759 // Correct sign of result in case of overflow.
4687 __ SmiNot(rdx, rdx); 4760 __ SmiNot(rdx, rdx);
4688 __ bind(&done); 4761 __ bind(&done);
4689 __ movq(rax, rdx); 4762 __ movq(rax, rdx);
4690 } 4763 }
4691 __ ret(0); 4764 __ ret(0);
4692 4765
4693 __ bind(&miss); 4766 __ bind(&miss);
4694 GenerateMiss(masm); 4767 GenerateMiss(masm);
4695 } 4768 }
4696 4769
4697 4770
4698 void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) { 4771 void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
4699 ASSERT(state_ == CompareIC::HEAP_NUMBERS); 4772 ASSERT(state_ == CompareIC::HEAP_NUMBERS);
4700 4773
4701 NearLabel generic_stub; 4774 Label generic_stub;
4702 NearLabel unordered; 4775 Label unordered;
4703 NearLabel miss; 4776 Label miss;
4704 Condition either_smi = masm->CheckEitherSmi(rax, rdx); 4777 Condition either_smi = masm->CheckEitherSmi(rax, rdx);
4705 __ j(either_smi, &generic_stub); 4778 __ j(either_smi, &generic_stub, Label::kNear);
4706 4779
4707 __ CmpObjectType(rax, HEAP_NUMBER_TYPE, rcx); 4780 __ CmpObjectType(rax, HEAP_NUMBER_TYPE, rcx);
4708 __ j(not_equal, &miss); 4781 __ j(not_equal, &miss, Label::kNear);
4709 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx); 4782 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx);
4710 __ j(not_equal, &miss); 4783 __ j(not_equal, &miss, Label::kNear);
4711 4784
4712 // Load left and right operand 4785 // Load left and right operand
4713 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); 4786 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
4714 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); 4787 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
4715 4788
4716 // Compare operands 4789 // Compare operands
4717 __ ucomisd(xmm0, xmm1); 4790 __ ucomisd(xmm0, xmm1);
4718 4791
4719 // Don't base result on EFLAGS when a NaN is involved. 4792 // Don't base result on EFLAGS when a NaN is involved.
4720 __ j(parity_even, &unordered); 4793 __ j(parity_even, &unordered, Label::kNear);
4721 4794
4722 // Return a result of -1, 0, or 1, based on EFLAGS. 4795 // Return a result of -1, 0, or 1, based on EFLAGS.
4723 // Performing mov, because xor would destroy the flag register. 4796 // Performing mov, because xor would destroy the flag register.
4724 __ movl(rax, Immediate(0)); 4797 __ movl(rax, Immediate(0));
4725 __ movl(rcx, Immediate(0)); 4798 __ movl(rcx, Immediate(0));
4726 __ setcc(above, rax); // Add one to zero if carry clear and not equal. 4799 __ setcc(above, rax); // Add one to zero if carry clear and not equal.
4727 __ sbbq(rax, rcx); // Subtract one if below (aka. carry set). 4800 __ sbbq(rax, rcx); // Subtract one if below (aka. carry set).
4728 __ ret(0); 4801 __ ret(0);
4729 4802
4730 __ bind(&unordered); 4803 __ bind(&unordered);
4731 4804
4732 CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS); 4805 CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS);
4733 __ bind(&generic_stub); 4806 __ bind(&generic_stub);
4734 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); 4807 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET);
4735 4808
4736 __ bind(&miss); 4809 __ bind(&miss);
4737 GenerateMiss(masm); 4810 GenerateMiss(masm);
4738 } 4811 }
4739 4812
4740 4813
4814 void ICCompareStub::GenerateSymbols(MacroAssembler* masm) {
4815 ASSERT(state_ == CompareIC::SYMBOLS);
4816 ASSERT(GetCondition() == equal);
4817
4818 // Registers containing left and right operands respectively.
4819 Register left = rdx;
4820 Register right = rax;
4821 Register tmp1 = rcx;
4822 Register tmp2 = rbx;
4823
4824 // Check that both operands are heap objects.
4825 Label miss;
4826 Condition cond = masm->CheckEitherSmi(left, right, tmp1);
4827 __ j(cond, &miss, Label::kNear);
4828
4829 // Check that both operands are symbols.
4830 __ movq(tmp1, FieldOperand(left, HeapObject::kMapOffset));
4831 __ movq(tmp2, FieldOperand(right, HeapObject::kMapOffset));
4832 __ movzxbq(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
4833 __ movzxbq(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
4834 STATIC_ASSERT(kSymbolTag != 0);
4835 __ and_(tmp1, tmp2);
4836 __ testb(tmp1, Immediate(kIsSymbolMask));
4837 __ j(zero, &miss, Label::kNear);
4838
4839 // Symbols are compared by identity.
4840 Label done;
4841 __ cmpq(left, right);
4842 // Make sure rax is non-zero. At this point input operands are
4843 // guaranteed to be non-zero.
4844 ASSERT(right.is(rax));
4845 __ j(not_equal, &done, Label::kNear);
4846 STATIC_ASSERT(EQUAL == 0);
4847 STATIC_ASSERT(kSmiTag == 0);
4848 __ Move(rax, Smi::FromInt(EQUAL));
4849 __ bind(&done);
4850 __ ret(0);
4851
4852 __ bind(&miss);
4853 GenerateMiss(masm);
4854 }
4855
4856
4741 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { 4857 void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
4742 ASSERT(state_ == CompareIC::STRINGS); 4858 ASSERT(state_ == CompareIC::STRINGS);
4859 ASSERT(GetCondition() == equal);
4743 Label miss; 4860 Label miss;
4744 4861
4745 // Registers containing left and right operands respectively. 4862 // Registers containing left and right operands respectively.
4746 Register left = rdx; 4863 Register left = rdx;
4747 Register right = rax; 4864 Register right = rax;
4748 Register tmp1 = rcx; 4865 Register tmp1 = rcx;
4749 Register tmp2 = rbx; 4866 Register tmp2 = rbx;
4750 Register tmp3 = rdi; 4867 Register tmp3 = rdi;
4751 Register tmp4 = r8;
4752 4868
4753 // Check that both operands are heap objects. 4869 // Check that both operands are heap objects.
4754 Condition cond = masm->CheckEitherSmi(left, right, tmp1); 4870 Condition cond = masm->CheckEitherSmi(left, right, tmp1);
4755 __ j(cond, &miss); 4871 __ j(cond, &miss);
4756 4872
4757 // Check that both operands are strings. This leaves the instance 4873 // Check that both operands are strings. This leaves the instance
4758 // types loaded in tmp1 and tmp2. 4874 // types loaded in tmp1 and tmp2.
4759 __ movq(tmp1, FieldOperand(left, HeapObject::kMapOffset)); 4875 __ movq(tmp1, FieldOperand(left, HeapObject::kMapOffset));
4760 __ movq(tmp2, FieldOperand(right, HeapObject::kMapOffset)); 4876 __ movq(tmp2, FieldOperand(right, HeapObject::kMapOffset));
4761 __ movzxbq(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); 4877 __ movzxbq(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
4762 __ movzxbq(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); 4878 __ movzxbq(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
4763 __ movq(tmp3, tmp1); 4879 __ movq(tmp3, tmp1);
4764 STATIC_ASSERT(kNotStringTag != 0); 4880 STATIC_ASSERT(kNotStringTag != 0);
4765 __ or_(tmp3, tmp2); 4881 __ or_(tmp3, tmp2);
4766 __ testl(tmp3, Immediate(kIsNotStringMask)); 4882 __ testb(tmp3, Immediate(kIsNotStringMask));
4767 __ j(not_zero, &miss); 4883 __ j(not_zero, &miss);
4768 4884
4769 // Fast check for identical strings. 4885 // Fast check for identical strings.
4770 NearLabel not_same; 4886 Label not_same;
4771 __ cmpq(left, right); 4887 __ cmpq(left, right);
4772 __ j(not_equal, &not_same); 4888 __ j(not_equal, &not_same, Label::kNear);
4773 STATIC_ASSERT(EQUAL == 0); 4889 STATIC_ASSERT(EQUAL == 0);
4774 STATIC_ASSERT(kSmiTag == 0); 4890 STATIC_ASSERT(kSmiTag == 0);
4775 __ Move(rax, Smi::FromInt(EQUAL)); 4891 __ Move(rax, Smi::FromInt(EQUAL));
4776 __ ret(0); 4892 __ ret(0);
4777 4893
4778 // Handle not identical strings. 4894 // Handle not identical strings.
4779 __ bind(&not_same); 4895 __ bind(&not_same);
4780 4896
4781 // Check that both strings are symbols. If they are, we're done 4897 // Check that both strings are symbols. If they are, we're done
4782 // because we already know they are not identical. 4898 // because we already know they are not identical.
4783 NearLabel do_compare; 4899 Label do_compare;
4784 ASSERT(GetCondition() == equal);
4785 STATIC_ASSERT(kSymbolTag != 0); 4900 STATIC_ASSERT(kSymbolTag != 0);
4786 __ and_(tmp1, tmp2); 4901 __ and_(tmp1, tmp2);
4787 __ testl(tmp1, Immediate(kIsSymbolMask)); 4902 __ testb(tmp1, Immediate(kIsSymbolMask));
4788 __ j(zero, &do_compare); 4903 __ j(zero, &do_compare, Label::kNear);
4789 // Make sure rax is non-zero. At this point input operands are 4904 // Make sure rax is non-zero. At this point input operands are
4790 // guaranteed to be non-zero. 4905 // guaranteed to be non-zero.
4791 ASSERT(right.is(rax)); 4906 ASSERT(right.is(rax));
4792 __ ret(0); 4907 __ ret(0);
4793 4908
4794 // Check that both strings are sequential ASCII. 4909 // Check that both strings are sequential ASCII.
4795 Label runtime; 4910 Label runtime;
4796 __ bind(&do_compare); 4911 __ bind(&do_compare);
4797 __ JumpIfNotBothSequentialAsciiStrings(left, right, tmp1, tmp2, &runtime); 4912 __ JumpIfNotBothSequentialAsciiStrings(left, right, tmp1, tmp2, &runtime);
4798 4913
4799 // Compare flat ASCII strings. Returns when done. 4914 // Compare flat ASCII strings. Returns when done.
4800 StringCompareStub::GenerateCompareFlatAsciiStrings( 4915 StringCompareStub::GenerateFlatAsciiStringEquals(
4801 masm, left, right, tmp1, tmp2, tmp3, tmp4); 4916 masm, left, right, tmp1, tmp2);
4802 4917
4803 // Handle more complex cases in runtime. 4918 // Handle more complex cases in runtime.
4804 __ bind(&runtime); 4919 __ bind(&runtime);
4805 __ pop(tmp1); // Return address. 4920 __ pop(tmp1); // Return address.
4806 __ push(left); 4921 __ push(left);
4807 __ push(right); 4922 __ push(right);
4808 __ push(tmp1); 4923 __ push(tmp1);
4809 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 4924 __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
4810 4925
4811 __ bind(&miss); 4926 __ bind(&miss);
4812 GenerateMiss(masm); 4927 GenerateMiss(masm);
4813 } 4928 }
4814 4929
4815 4930
4816 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { 4931 void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
4817 ASSERT(state_ == CompareIC::OBJECTS); 4932 ASSERT(state_ == CompareIC::OBJECTS);
4818 NearLabel miss; 4933 Label miss;
4819 Condition either_smi = masm->CheckEitherSmi(rdx, rax); 4934 Condition either_smi = masm->CheckEitherSmi(rdx, rax);
4820 __ j(either_smi, &miss); 4935 __ j(either_smi, &miss, Label::kNear);
4821 4936
4822 __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx); 4937 __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx);
4823 __ j(not_equal, &miss, not_taken); 4938 __ j(not_equal, &miss, Label::kNear);
4824 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); 4939 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
4825 __ j(not_equal, &miss, not_taken); 4940 __ j(not_equal, &miss, Label::kNear);
4826 4941
4827 ASSERT(GetCondition() == equal); 4942 ASSERT(GetCondition() == equal);
4828 __ subq(rax, rdx); 4943 __ subq(rax, rdx);
4829 __ ret(0); 4944 __ ret(0);
4830 4945
4831 __ bind(&miss); 4946 __ bind(&miss);
4832 GenerateMiss(masm); 4947 GenerateMiss(masm);
4833 } 4948 }
4834 4949
4835 4950
(...skipping 21 matching lines...) Expand all
4857 __ pop(rcx); 4972 __ pop(rcx);
4858 __ pop(rax); 4973 __ pop(rax);
4859 __ pop(rdx); 4974 __ pop(rdx);
4860 __ push(rcx); 4975 __ push(rcx);
4861 4976
4862 // Do a tail call to the rewritten stub. 4977 // Do a tail call to the rewritten stub.
4863 __ jmp(rdi); 4978 __ jmp(rdi);
4864 } 4979 }
4865 4980
4866 4981
4982 MaybeObject* StringDictionaryLookupStub::GenerateNegativeLookup(
4983 MacroAssembler* masm,
4984 Label* miss,
4985 Label* done,
4986 Register properties,
4987 String* name,
4988 Register r0) {
4989 // If names of slots in range from 1 to kProbes - 1 for the hash value are
4990 // not equal to the name and kProbes-th slot is not used (its name is the
4991 // undefined value), it guarantees the hash table doesn't contain the
4992 // property. It's true even if some slots represent deleted properties
4993 // (their names are the null value).
4994 for (int i = 0; i < kInlinedProbes; i++) {
4995 // r0 points to properties hash.
4996 // Compute the masked index: (hash + i + i * i) & mask.
4997 Register index = r0;
4998 // Capacity is smi 2^n.
4999 __ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset));
5000 __ decl(index);
5001 __ and_(index,
5002 Immediate(name->Hash() + StringDictionary::GetProbeOffset(i)));
5003
5004 // Scale the index by multiplying by the entry size.
5005 ASSERT(StringDictionary::kEntrySize == 3);
5006 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3.
5007
5008 Register entity_name = r0;
5009 // Having undefined at this place means the name is not contained.
5010 ASSERT_EQ(kSmiTagSize, 1);
5011 __ movq(entity_name, Operand(properties,
5012 index,
5013 times_pointer_size,
5014 kElementsStartOffset - kHeapObjectTag));
5015 __ Cmp(entity_name, masm->isolate()->factory()->undefined_value());
5016 __ j(equal, done);
5017
5018 // Stop if found the property.
5019 __ Cmp(entity_name, Handle<String>(name));
5020 __ j(equal, miss);
5021
5022 // Check if the entry name is not a symbol.
5023 __ movq(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
5024 __ testb(FieldOperand(entity_name, Map::kInstanceTypeOffset),
5025 Immediate(kIsSymbolMask));
5026 __ j(zero, miss);
5027 }
5028
5029 StringDictionaryLookupStub stub(properties,
5030 r0,
5031 r0,
5032 StringDictionaryLookupStub::NEGATIVE_LOOKUP);
5033 __ Push(Handle<Object>(name));
5034 __ push(Immediate(name->Hash()));
5035 MaybeObject* result = masm->TryCallStub(&stub);
5036 if (result->IsFailure()) return result;
5037 __ testq(r0, r0);
5038 __ j(not_zero, miss);
5039 __ jmp(done);
5040 return result;
5041 }
5042
5043
5044 // Probe the string dictionary in the |elements| register. Jump to the
5045 // |done| label if a property with the given name is found leaving the
5046 // index into the dictionary in |r1|. Jump to the |miss| label
5047 // otherwise.
5048 void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
5049 Label* miss,
5050 Label* done,
5051 Register elements,
5052 Register name,
5053 Register r0,
5054 Register r1) {
5055 // Assert that name contains a string.
5056 if (FLAG_debug_code) __ AbortIfNotString(name);
5057
5058 __ SmiToInteger32(r0, FieldOperand(elements, kCapacityOffset));
5059 __ decl(r0);
5060
5061 for (int i = 0; i < kInlinedProbes; i++) {
5062 // Compute the masked index: (hash + i + i * i) & mask.
5063 __ movl(r1, FieldOperand(name, String::kHashFieldOffset));
5064 __ shrl(r1, Immediate(String::kHashShift));
5065 if (i > 0) {
5066 __ addl(r1, Immediate(StringDictionary::GetProbeOffset(i)));
5067 }
5068 __ and_(r1, r0);
5069
5070 // Scale the index by multiplying by the entry size.
5071 ASSERT(StringDictionary::kEntrySize == 3);
5072 __ lea(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3
5073
5074 // Check if the key is identical to the name.
5075 __ cmpq(name, Operand(elements, r1, times_pointer_size,
5076 kElementsStartOffset - kHeapObjectTag));
5077 __ j(equal, done);
5078 }
5079
5080 StringDictionaryLookupStub stub(elements,
5081 r0,
5082 r1,
5083 POSITIVE_LOOKUP);
5084 __ push(name);
5085 __ movl(r0, FieldOperand(name, String::kHashFieldOffset));
5086 __ shrl(r0, Immediate(String::kHashShift));
5087 __ push(r0);
5088 __ CallStub(&stub);
5089
5090 __ testq(r0, r0);
5091 __ j(zero, miss);
5092 __ jmp(done);
5093 }
5094
5095
5096 void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
5097 // Stack frame on entry:
5098 // esp[0 * kPointerSize]: return address.
5099 // esp[1 * kPointerSize]: key's hash.
5100 // esp[2 * kPointerSize]: key.
5101 // Registers:
5102 // dictionary_: StringDictionary to probe.
5103 // result_: used as scratch.
5104 // index_: will hold an index of entry if lookup is successful.
5105 // might alias with result_.
5106 // Returns:
5107 // result_ is zero if lookup failed, non zero otherwise.
5108
5109 Label in_dictionary, maybe_in_dictionary, not_in_dictionary;
5110
5111 Register scratch = result_;
5112
5113 __ SmiToInteger32(scratch, FieldOperand(dictionary_, kCapacityOffset));
5114 __ decl(scratch);
5115 __ push(scratch);
5116
5117 // If names of slots in range from 1 to kProbes - 1 for the hash value are
5118 // not equal to the name and kProbes-th slot is not used (its name is the
5119 // undefined value), it guarantees the hash table doesn't contain the
5120 // property. It's true even if some slots represent deleted properties
5121 // (their names are the null value).
5122 for (int i = kInlinedProbes; i < kTotalProbes; i++) {
5123 // Compute the masked index: (hash + i + i * i) & mask.
5124 __ movq(scratch, Operand(rsp, 2 * kPointerSize));
5125 if (i > 0) {
5126 __ addl(scratch, Immediate(StringDictionary::GetProbeOffset(i)));
5127 }
5128 __ and_(scratch, Operand(rsp, 0));
5129
5130 // Scale the index by multiplying by the entry size.
5131 ASSERT(StringDictionary::kEntrySize == 3);
5132 __ lea(index_, Operand(scratch, scratch, times_2, 0)); // index *= 3.
5133
5134 // Having undefined at this place means the name is not contained.
5135 __ movq(scratch, Operand(dictionary_,
5136 index_,
5137 times_pointer_size,
5138 kElementsStartOffset - kHeapObjectTag));
5139
5140 __ Cmp(scratch, masm->isolate()->factory()->undefined_value());
5141 __ j(equal, &not_in_dictionary);
5142
5143 // Stop if found the property.
5144 __ cmpq(scratch, Operand(rsp, 3 * kPointerSize));
5145 __ j(equal, &in_dictionary);
5146
5147 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
5148 // If we hit a non symbol key during negative lookup
5149 // we have to bailout as this key might be equal to the
5150 // key we are looking for.
5151
5152 // Check if the entry name is not a symbol.
5153 __ movq(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
5154 __ testb(FieldOperand(scratch, Map::kInstanceTypeOffset),
5155 Immediate(kIsSymbolMask));
5156 __ j(zero, &maybe_in_dictionary);
5157 }
5158 }
5159
5160 __ bind(&maybe_in_dictionary);
5161 // If we are doing negative lookup then probing failure should be
5162 // treated as a lookup success. For positive lookup probing failure
5163 // should be treated as lookup failure.
5164 if (mode_ == POSITIVE_LOOKUP) {
5165 __ movq(scratch, Immediate(0));
5166 __ Drop(1);
5167 __ ret(2 * kPointerSize);
5168 }
5169
5170 __ bind(&in_dictionary);
5171 __ movq(scratch, Immediate(1));
5172 __ Drop(1);
5173 __ ret(2 * kPointerSize);
5174
5175 __ bind(&not_in_dictionary);
5176 __ movq(scratch, Immediate(0));
5177 __ Drop(1);
5178 __ ret(2 * kPointerSize);
5179 }
5180
5181
4867 #undef __ 5182 #undef __
4868 5183
4869 } } // namespace v8::internal 5184 } } // namespace v8::internal
4870 5185
4871 #endif // V8_TARGET_ARCH_X64 5186 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/code-stubs-x64.h ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698