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

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

Issue 143633007: A64: Synchronize with r18764. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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/codegen-x64.h » ('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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 Isolate* isolate, 43 Isolate* isolate,
44 CodeStubInterfaceDescriptor* descriptor) { 44 CodeStubInterfaceDescriptor* descriptor) {
45 static Register registers[] = { rbx }; 45 static Register registers[] = { rbx };
46 descriptor->register_param_count_ = 1; 46 descriptor->register_param_count_ = 1;
47 descriptor->register_params_ = registers; 47 descriptor->register_params_ = registers;
48 descriptor->deoptimization_handler_ = 48 descriptor->deoptimization_handler_ =
49 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry; 49 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry;
50 } 50 }
51 51
52 52
53 void FastNewContextStub::InitializeInterfaceDescriptor(
54 Isolate* isolate,
55 CodeStubInterfaceDescriptor* descriptor) {
56 static Register registers[] = { rdi };
57 descriptor->register_param_count_ = 1;
58 descriptor->register_params_ = registers;
59 descriptor->deoptimization_handler_ = NULL;
60 }
61
62
53 void ToNumberStub::InitializeInterfaceDescriptor( 63 void ToNumberStub::InitializeInterfaceDescriptor(
54 Isolate* isolate, 64 Isolate* isolate,
55 CodeStubInterfaceDescriptor* descriptor) { 65 CodeStubInterfaceDescriptor* descriptor) {
56 static Register registers[] = { rax }; 66 static Register registers[] = { rax };
57 descriptor->register_param_count_ = 1; 67 descriptor->register_param_count_ = 1;
58 descriptor->register_params_ = registers; 68 descriptor->register_params_ = registers;
59 descriptor->deoptimization_handler_ = NULL; 69 descriptor->deoptimization_handler_ = NULL;
60 } 70 }
61 71
62 72
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 } 190 }
181 191
182 192
183 static void InitializeArrayConstructorDescriptor( 193 static void InitializeArrayConstructorDescriptor(
184 Isolate* isolate, 194 Isolate* isolate,
185 CodeStubInterfaceDescriptor* descriptor, 195 CodeStubInterfaceDescriptor* descriptor,
186 int constant_stack_parameter_count) { 196 int constant_stack_parameter_count) {
187 // register state 197 // register state
188 // rax -- number of arguments 198 // rax -- number of arguments
189 // rdi -- function 199 // rdi -- function
190 // rbx -- type info cell with elements kind 200 // rbx -- allocation site with elements kind
191 static Register registers_variable_args[] = { rdi, rbx, rax }; 201 static Register registers_variable_args[] = { rdi, rbx, rax };
192 static Register registers_no_args[] = { rdi, rbx }; 202 static Register registers_no_args[] = { rdi, rbx };
193 203
194 if (constant_stack_parameter_count == 0) { 204 if (constant_stack_parameter_count == 0) {
195 descriptor->register_param_count_ = 2; 205 descriptor->register_param_count_ = 2;
196 descriptor->register_params_ = registers_no_args; 206 descriptor->register_params_ = registers_no_args;
197 } else { 207 } else {
198 // stack param count needs (constructor pointer, and single argument) 208 // stack param count needs (constructor pointer, and single argument)
199 descriptor->handler_arguments_mode_ = PASS_ARGUMENTS; 209 descriptor->handler_arguments_mode_ = PASS_ARGUMENTS;
200 descriptor->stack_parameter_count_ = rax; 210 descriptor->stack_parameter_count_ = rax;
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 Isolate* isolate, 353 Isolate* isolate,
344 CodeStubInterfaceDescriptor* descriptor) { 354 CodeStubInterfaceDescriptor* descriptor) {
345 static Register registers[] = { rcx, rdx, rax }; 355 static Register registers[] = { rcx, rdx, rax };
346 descriptor->register_param_count_ = 3; 356 descriptor->register_param_count_ = 3;
347 descriptor->register_params_ = registers; 357 descriptor->register_params_ = registers;
348 descriptor->deoptimization_handler_ = 358 descriptor->deoptimization_handler_ =
349 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite); 359 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite);
350 } 360 }
351 361
352 362
353 void NewStringAddStub::InitializeInterfaceDescriptor( 363 void StringAddStub::InitializeInterfaceDescriptor(
354 Isolate* isolate, 364 Isolate* isolate,
355 CodeStubInterfaceDescriptor* descriptor) { 365 CodeStubInterfaceDescriptor* descriptor) {
356 static Register registers[] = { rdx, rax }; 366 static Register registers[] = { rdx, rax };
357 descriptor->register_param_count_ = 2; 367 descriptor->register_param_count_ = 2;
358 descriptor->register_params_ = registers; 368 descriptor->register_params_ = registers;
359 descriptor->deoptimization_handler_ = 369 descriptor->deoptimization_handler_ =
360 Runtime::FunctionForId(Runtime::kStringAdd)->entry; 370 Runtime::FunctionForId(Runtime::kStringAdd)->entry;
361 } 371 }
362 372
363 373
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 __ push(descriptor->register_params_[i]); 441 __ push(descriptor->register_params_[i]);
432 } 442 }
433 ExternalReference miss = descriptor->miss_handler(); 443 ExternalReference miss = descriptor->miss_handler();
434 __ CallExternalReference(miss, descriptor->register_param_count_); 444 __ CallExternalReference(miss, descriptor->register_param_count_);
435 } 445 }
436 446
437 __ Ret(); 447 __ Ret();
438 } 448 }
439 449
440 450
441 void FastNewContextStub::Generate(MacroAssembler* masm) {
442 // Try to allocate the context in new space.
443 Label gc;
444 int length = slots_ + Context::MIN_CONTEXT_SLOTS;
445 __ Allocate((length * kPointerSize) + FixedArray::kHeaderSize,
446 rax, rbx, rcx, &gc, TAG_OBJECT);
447
448 // Get the function from the stack.
449 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER);
450 __ movq(rcx, args.GetArgumentOperand(0));
451
452 // Set up the object header.
453 __ LoadRoot(kScratchRegister, Heap::kFunctionContextMapRootIndex);
454 __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister);
455 __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length));
456
457 // Set up the fixed slots.
458 __ Set(rbx, 0); // Set to NULL.
459 __ movq(Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)), rcx);
460 __ movq(Operand(rax, Context::SlotOffset(Context::PREVIOUS_INDEX)), rsi);
461 __ movq(Operand(rax, Context::SlotOffset(Context::EXTENSION_INDEX)), rbx);
462
463 // Copy the global object from the previous context.
464 __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
465 __ movq(Operand(rax, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)), rbx);
466
467 // Initialize the rest of the slots to undefined.
468 __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
469 for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
470 __ movq(Operand(rax, Context::SlotOffset(i)), rbx);
471 }
472
473 // Return and remove the on-stack parameter.
474 __ movq(rsi, rax);
475 __ ret(1 * kPointerSize);
476
477 // Need to collect. Call into runtime system.
478 __ bind(&gc);
479 __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1);
480 }
481
482
483 void FastNewBlockContextStub::Generate(MacroAssembler* masm) { 451 void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
484 // Stack layout on entry: 452 // Stack layout on entry:
485 // 453 //
486 // [rsp + (1 * kPointerSize)] : function 454 // [rsp + (1 * kPointerSize)] : function
487 // [rsp + (2 * kPointerSize)] : serialized scope info 455 // [rsp + (2 * kPointerSize)] : serialized scope info
488 456
489 // Try to allocate the context in new space. 457 // Try to allocate the context in new space.
490 Label gc; 458 Label gc;
491 int length = slots_ + Context::MIN_CONTEXT_SLOTS; 459 int length = slots_ + Context::MIN_CONTEXT_SLOTS;
492 __ Allocate(FixedArray::SizeFor(length), 460 __ Allocate(FixedArray::SizeFor(length),
493 rax, rbx, rcx, &gc, TAG_OBJECT); 461 rax, rbx, rcx, &gc, TAG_OBJECT);
494 462
495 // Get the function from the stack. 463 // Get the function from the stack.
496 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER); 464 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER);
497 __ movq(rcx, args.GetArgumentOperand(1)); 465 __ movp(rcx, args.GetArgumentOperand(1));
498 // Get the serialized scope info from the stack. 466 // Get the serialized scope info from the stack.
499 __ movq(rbx, args.GetArgumentOperand(0)); 467 __ movp(rbx, args.GetArgumentOperand(0));
500 468
501 // Set up the object header. 469 // Set up the object header.
502 __ LoadRoot(kScratchRegister, Heap::kBlockContextMapRootIndex); 470 __ LoadRoot(kScratchRegister, Heap::kBlockContextMapRootIndex);
503 __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister); 471 __ movp(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister);
504 __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length)); 472 __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length));
505 473
506 // If this block context is nested in the native context we get a smi 474 // If this block context is nested in the native context we get a smi
507 // sentinel instead of a function. The block context should get the 475 // sentinel instead of a function. The block context should get the
508 // canonical empty function of the native context as its closure which 476 // canonical empty function of the native context as its closure which
509 // we still have to look up. 477 // we still have to look up.
510 Label after_sentinel; 478 Label after_sentinel;
511 __ JumpIfNotSmi(rcx, &after_sentinel, Label::kNear); 479 __ JumpIfNotSmi(rcx, &after_sentinel, Label::kNear);
512 if (FLAG_debug_code) { 480 if (FLAG_debug_code) {
513 __ cmpq(rcx, Immediate(0)); 481 __ cmpq(rcx, Immediate(0));
514 __ Assert(equal, kExpected0AsASmiSentinel); 482 __ Assert(equal, kExpected0AsASmiSentinel);
515 } 483 }
516 __ movq(rcx, GlobalObjectOperand()); 484 __ movp(rcx, GlobalObjectOperand());
517 __ movq(rcx, FieldOperand(rcx, GlobalObject::kNativeContextOffset)); 485 __ movp(rcx, FieldOperand(rcx, GlobalObject::kNativeContextOffset));
518 __ movq(rcx, ContextOperand(rcx, Context::CLOSURE_INDEX)); 486 __ movp(rcx, ContextOperand(rcx, Context::CLOSURE_INDEX));
519 __ bind(&after_sentinel); 487 __ bind(&after_sentinel);
520 488
521 // Set up the fixed slots. 489 // Set up the fixed slots.
522 __ movq(ContextOperand(rax, Context::CLOSURE_INDEX), rcx); 490 __ movp(ContextOperand(rax, Context::CLOSURE_INDEX), rcx);
523 __ movq(ContextOperand(rax, Context::PREVIOUS_INDEX), rsi); 491 __ movp(ContextOperand(rax, Context::PREVIOUS_INDEX), rsi);
524 __ movq(ContextOperand(rax, Context::EXTENSION_INDEX), rbx); 492 __ movp(ContextOperand(rax, Context::EXTENSION_INDEX), rbx);
525 493
526 // Copy the global object from the previous context. 494 // Copy the global object from the previous context.
527 __ movq(rbx, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX)); 495 __ movp(rbx, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX));
528 __ movq(ContextOperand(rax, Context::GLOBAL_OBJECT_INDEX), rbx); 496 __ movp(ContextOperand(rax, Context::GLOBAL_OBJECT_INDEX), rbx);
529 497
530 // Initialize the rest of the slots to the hole value. 498 // Initialize the rest of the slots to the hole value.
531 __ LoadRoot(rbx, Heap::kTheHoleValueRootIndex); 499 __ LoadRoot(rbx, Heap::kTheHoleValueRootIndex);
532 for (int i = 0; i < slots_; i++) { 500 for (int i = 0; i < slots_; i++) {
533 __ movq(ContextOperand(rax, i + Context::MIN_CONTEXT_SLOTS), rbx); 501 __ movp(ContextOperand(rax, i + Context::MIN_CONTEXT_SLOTS), rbx);
534 } 502 }
535 503
536 // Return and remove the on-stack parameter. 504 // Return and remove the on-stack parameter.
537 __ movq(rsi, rax); 505 __ movp(rsi, rax);
538 __ ret(2 * kPointerSize); 506 __ ret(2 * kPointerSize);
539 507
540 // Need to collect. Call into runtime system. 508 // Need to collect. Call into runtime system.
541 __ bind(&gc); 509 __ bind(&gc);
542 __ TailCallRuntime(Runtime::kPushBlockContext, 2, 1); 510 __ TailCallRuntime(Runtime::kPushBlockContext, 2, 1);
543 } 511 }
544 512
545 513
546 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { 514 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
547 __ PushCallerSaved(save_doubles_); 515 __ PushCallerSaved(save_doubles_);
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
693 const Register base = rax; 661 const Register base = rax;
694 const Register scratch = rcx; 662 const Register scratch = rcx;
695 const XMMRegister double_result = xmm3; 663 const XMMRegister double_result = xmm3;
696 const XMMRegister double_base = xmm2; 664 const XMMRegister double_base = xmm2;
697 const XMMRegister double_exponent = xmm1; 665 const XMMRegister double_exponent = xmm1;
698 const XMMRegister double_scratch = xmm4; 666 const XMMRegister double_scratch = xmm4;
699 667
700 Label call_runtime, done, exponent_not_smi, int_exponent; 668 Label call_runtime, done, exponent_not_smi, int_exponent;
701 669
702 // Save 1 in double_result - we need this several times later on. 670 // Save 1 in double_result - we need this several times later on.
703 __ movq(scratch, Immediate(1)); 671 __ movp(scratch, Immediate(1));
704 __ Cvtlsi2sd(double_result, scratch); 672 __ Cvtlsi2sd(double_result, scratch);
705 673
706 if (exponent_type_ == ON_STACK) { 674 if (exponent_type_ == ON_STACK) {
707 Label base_is_smi, unpack_exponent; 675 Label base_is_smi, unpack_exponent;
708 // The exponent and base are supplied as arguments on the stack. 676 // The exponent and base are supplied as arguments on the stack.
709 // This can only happen if the stub is called from non-optimized code. 677 // This can only happen if the stub is called from non-optimized code.
710 // Load input parameters from stack. 678 // Load input parameters from stack.
711 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER); 679 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER);
712 __ movq(base, args.GetArgumentOperand(0)); 680 __ movp(base, args.GetArgumentOperand(0));
713 __ movq(exponent, args.GetArgumentOperand(1)); 681 __ movp(exponent, args.GetArgumentOperand(1));
714 __ JumpIfSmi(base, &base_is_smi, Label::kNear); 682 __ JumpIfSmi(base, &base_is_smi, Label::kNear);
715 __ CompareRoot(FieldOperand(base, HeapObject::kMapOffset), 683 __ CompareRoot(FieldOperand(base, HeapObject::kMapOffset),
716 Heap::kHeapNumberMapRootIndex); 684 Heap::kHeapNumberMapRootIndex);
717 __ j(not_equal, &call_runtime); 685 __ j(not_equal, &call_runtime);
718 686
719 __ movsd(double_base, FieldOperand(base, HeapNumber::kValueOffset)); 687 __ movsd(double_base, FieldOperand(base, HeapNumber::kValueOffset));
720 __ jmp(&unpack_exponent, Label::kNear); 688 __ jmp(&unpack_exponent, Label::kNear);
721 689
722 __ bind(&base_is_smi); 690 __ bind(&base_is_smi);
723 __ SmiToInteger32(base, base); 691 __ SmiToInteger32(base, base);
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
863 __ bind(&fast_power_failed); 831 __ bind(&fast_power_failed);
864 __ fninit(); 832 __ fninit();
865 __ addq(rsp, Immediate(kDoubleSize)); 833 __ addq(rsp, Immediate(kDoubleSize));
866 __ jmp(&call_runtime); 834 __ jmp(&call_runtime);
867 } 835 }
868 836
869 // Calculate power with integer exponent. 837 // Calculate power with integer exponent.
870 __ bind(&int_exponent); 838 __ bind(&int_exponent);
871 const XMMRegister double_scratch2 = double_exponent; 839 const XMMRegister double_scratch2 = double_exponent;
872 // Back up exponent as we need to check if exponent is negative later. 840 // Back up exponent as we need to check if exponent is negative later.
873 __ movq(scratch, exponent); // Back up exponent. 841 __ movp(scratch, exponent); // Back up exponent.
874 __ movsd(double_scratch, double_base); // Back up base. 842 __ movsd(double_scratch, double_base); // Back up base.
875 __ movsd(double_scratch2, double_result); // Load double_exponent with 1. 843 __ movsd(double_scratch2, double_result); // Load double_exponent with 1.
876 844
877 // Get absolute value of exponent. 845 // Get absolute value of exponent.
878 Label no_neg, while_true, while_false; 846 Label no_neg, while_true, while_false;
879 __ testl(scratch, scratch); 847 __ testl(scratch, scratch);
880 __ j(positive, &no_neg, Label::kNear); 848 __ j(positive, &no_neg, Label::kNear);
881 __ negl(scratch); 849 __ negl(scratch);
882 __ bind(&no_neg); 850 __ bind(&no_neg);
883 851
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
1031 // Check that the receiver isn't a smi. 999 // Check that the receiver isn't a smi.
1032 __ JumpIfSmi(receiver, &miss); 1000 __ JumpIfSmi(receiver, &miss);
1033 1001
1034 // Check that the object is a JS array. 1002 // Check that the object is a JS array.
1035 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); 1003 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
1036 __ j(not_equal, &miss); 1004 __ j(not_equal, &miss);
1037 1005
1038 // Check that elements are FixedArray. 1006 // Check that elements are FixedArray.
1039 // We rely on StoreIC_ArrayLength below to deal with all types of 1007 // We rely on StoreIC_ArrayLength below to deal with all types of
1040 // fast elements (including COW). 1008 // fast elements (including COW).
1041 __ movq(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); 1009 __ movp(scratch, FieldOperand(receiver, JSArray::kElementsOffset));
1042 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); 1010 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch);
1043 __ j(not_equal, &miss); 1011 __ j(not_equal, &miss);
1044 1012
1045 // Check that the array has fast properties, otherwise the length 1013 // Check that the array has fast properties, otherwise the length
1046 // property might have been redefined. 1014 // property might have been redefined.
1047 __ movq(scratch, FieldOperand(receiver, JSArray::kPropertiesOffset)); 1015 __ movp(scratch, FieldOperand(receiver, JSArray::kPropertiesOffset));
1048 __ CompareRoot(FieldOperand(scratch, FixedArray::kMapOffset), 1016 __ CompareRoot(FieldOperand(scratch, FixedArray::kMapOffset),
1049 Heap::kHashTableMapRootIndex); 1017 Heap::kHashTableMapRootIndex);
1050 __ j(equal, &miss); 1018 __ j(equal, &miss);
1051 1019
1052 // Check that value is a smi. 1020 // Check that value is a smi.
1053 __ JumpIfNotSmi(value, &miss); 1021 __ JumpIfNotSmi(value, &miss);
1054 1022
1055 // Prepare tail call to StoreIC_ArrayLength. 1023 // Prepare tail call to StoreIC_ArrayLength.
1056 __ PopReturnAddressTo(scratch); 1024 __ PopReturnAddressTo(scratch);
1057 __ push(receiver); 1025 __ push(receiver);
(...skipping 16 matching lines...) Expand all
1074 1042
1075 // Check that the key is a smi. 1043 // Check that the key is a smi.
1076 Label slow; 1044 Label slow;
1077 __ JumpIfNotSmi(rdx, &slow); 1045 __ JumpIfNotSmi(rdx, &slow);
1078 1046
1079 // Check if the calling frame is an arguments adaptor frame. We look at the 1047 // Check if the calling frame is an arguments adaptor frame. We look at the
1080 // context offset, and if the frame is not a regular one, then we find a 1048 // context offset, and if the frame is not a regular one, then we find a
1081 // Smi instead of the context. We can't use SmiCompare here, because that 1049 // Smi instead of the context. We can't use SmiCompare here, because that
1082 // only works for comparing two smis. 1050 // only works for comparing two smis.
1083 Label adaptor; 1051 Label adaptor;
1084 __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 1052 __ movp(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
1085 __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset), 1053 __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset),
1086 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 1054 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
1087 __ j(equal, &adaptor); 1055 __ j(equal, &adaptor);
1088 1056
1089 // Check index against formal parameters count limit passed in 1057 // Check index against formal parameters count limit passed in
1090 // through register rax. Use unsigned comparison to get negative 1058 // through register rax. Use unsigned comparison to get negative
1091 // check for free. 1059 // check for free.
1092 __ cmpq(rdx, rax); 1060 __ cmpq(rdx, rax);
1093 __ j(above_equal, &slow); 1061 __ j(above_equal, &slow);
1094 1062
1095 // Read the argument from the stack and return it. 1063 // Read the argument from the stack and return it.
1096 __ SmiSub(rax, rax, rdx); 1064 __ SmiSub(rax, rax, rdx);
1097 __ SmiToInteger32(rax, rax); 1065 __ SmiToInteger32(rax, rax);
1098 StackArgumentsAccessor args(rbp, rax, ARGUMENTS_DONT_CONTAIN_RECEIVER); 1066 StackArgumentsAccessor args(rbp, rax, ARGUMENTS_DONT_CONTAIN_RECEIVER);
1099 __ movq(rax, args.GetArgumentOperand(0)); 1067 __ movp(rax, args.GetArgumentOperand(0));
1100 __ Ret(); 1068 __ Ret();
1101 1069
1102 // Arguments adaptor case: Check index against actual arguments 1070 // Arguments adaptor case: Check index against actual arguments
1103 // limit found in the arguments adaptor frame. Use unsigned 1071 // limit found in the arguments adaptor frame. Use unsigned
1104 // comparison to get negative check for free. 1072 // comparison to get negative check for free.
1105 __ bind(&adaptor); 1073 __ bind(&adaptor);
1106 __ movq(rcx, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 1074 __ movp(rcx, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
1107 __ cmpq(rdx, rcx); 1075 __ cmpq(rdx, rcx);
1108 __ j(above_equal, &slow); 1076 __ j(above_equal, &slow);
1109 1077
1110 // Read the argument from the stack and return it. 1078 // Read the argument from the stack and return it.
1111 __ SmiSub(rcx, rcx, rdx); 1079 __ SmiSub(rcx, rcx, rdx);
1112 __ SmiToInteger32(rcx, rcx); 1080 __ SmiToInteger32(rcx, rcx);
1113 StackArgumentsAccessor adaptor_args(rbx, rcx, 1081 StackArgumentsAccessor adaptor_args(rbx, rcx,
1114 ARGUMENTS_DONT_CONTAIN_RECEIVER); 1082 ARGUMENTS_DONT_CONTAIN_RECEIVER);
1115 __ movq(rax, adaptor_args.GetArgumentOperand(0)); 1083 __ movp(rax, adaptor_args.GetArgumentOperand(0));
1116 __ Ret(); 1084 __ Ret();
1117 1085
1118 // Slow-case: Handle non-smi or out-of-bounds access to arguments 1086 // Slow-case: Handle non-smi or out-of-bounds access to arguments
1119 // by calling the runtime system. 1087 // by calling the runtime system.
1120 __ bind(&slow); 1088 __ bind(&slow);
1121 __ PopReturnAddressTo(rbx); 1089 __ PopReturnAddressTo(rbx);
1122 __ push(rdx); 1090 __ push(rdx);
1123 __ PushReturnAddressFrom(rbx); 1091 __ PushReturnAddressFrom(rbx);
1124 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); 1092 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
1125 } 1093 }
(...skipping 11 matching lines...) Expand all
1137 1105
1138 Factory* factory = masm->isolate()->factory(); 1106 Factory* factory = masm->isolate()->factory();
1139 1107
1140 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER); 1108 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER);
1141 __ SmiToInteger64(rbx, args.GetArgumentOperand(2)); 1109 __ SmiToInteger64(rbx, args.GetArgumentOperand(2));
1142 // rbx = parameter count (untagged) 1110 // rbx = parameter count (untagged)
1143 1111
1144 // Check if the calling frame is an arguments adaptor frame. 1112 // Check if the calling frame is an arguments adaptor frame.
1145 Label runtime; 1113 Label runtime;
1146 Label adaptor_frame, try_allocate; 1114 Label adaptor_frame, try_allocate;
1147 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 1115 __ movp(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
1148 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); 1116 __ movp(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
1149 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 1117 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
1150 __ j(equal, &adaptor_frame); 1118 __ j(equal, &adaptor_frame);
1151 1119
1152 // No adaptor, parameter count = argument count. 1120 // No adaptor, parameter count = argument count.
1153 __ movq(rcx, rbx); 1121 __ movp(rcx, rbx);
1154 __ jmp(&try_allocate, Label::kNear); 1122 __ jmp(&try_allocate, Label::kNear);
1155 1123
1156 // We have an adaptor frame. Patch the parameters pointer. 1124 // We have an adaptor frame. Patch the parameters pointer.
1157 __ bind(&adaptor_frame); 1125 __ bind(&adaptor_frame);
1158 __ SmiToInteger64(rcx, 1126 __ SmiToInteger64(rcx,
1159 Operand(rdx, 1127 Operand(rdx,
1160 ArgumentsAdaptorFrameConstants::kLengthOffset)); 1128 ArgumentsAdaptorFrameConstants::kLengthOffset));
1161 __ lea(rdx, Operand(rdx, rcx, times_pointer_size, 1129 __ lea(rdx, Operand(rdx, rcx, times_pointer_size,
1162 StandardFrameConstants::kCallerSPOffset)); 1130 StandardFrameConstants::kCallerSPOffset));
1163 __ movq(args.GetArgumentOperand(1), rdx); 1131 __ movp(args.GetArgumentOperand(1), rdx);
1164 1132
1165 // rbx = parameter count (untagged) 1133 // rbx = parameter count (untagged)
1166 // rcx = argument count (untagged) 1134 // rcx = argument count (untagged)
1167 // Compute the mapped parameter count = min(rbx, rcx) in rbx. 1135 // Compute the mapped parameter count = min(rbx, rcx) in rbx.
1168 __ cmpq(rbx, rcx); 1136 __ cmpq(rbx, rcx);
1169 __ j(less_equal, &try_allocate, Label::kNear); 1137 __ j(less_equal, &try_allocate, Label::kNear);
1170 __ movq(rbx, rcx); 1138 __ movp(rbx, rcx);
1171 1139
1172 __ bind(&try_allocate); 1140 __ bind(&try_allocate);
1173 1141
1174 // Compute the sizes of backing store, parameter map, and arguments object. 1142 // Compute the sizes of backing store, parameter map, and arguments object.
1175 // 1. Parameter map, has 2 extra words containing context and backing store. 1143 // 1. Parameter map, has 2 extra words containing context and backing store.
1176 const int kParameterMapHeaderSize = 1144 const int kParameterMapHeaderSize =
1177 FixedArray::kHeaderSize + 2 * kPointerSize; 1145 FixedArray::kHeaderSize + 2 * kPointerSize;
1178 Label no_parameter_map; 1146 Label no_parameter_map;
1179 __ xor_(r8, r8); 1147 __ xor_(r8, r8);
1180 __ testq(rbx, rbx); 1148 __ testq(rbx, rbx);
1181 __ j(zero, &no_parameter_map, Label::kNear); 1149 __ j(zero, &no_parameter_map, Label::kNear);
1182 __ lea(r8, Operand(rbx, times_pointer_size, kParameterMapHeaderSize)); 1150 __ lea(r8, Operand(rbx, times_pointer_size, kParameterMapHeaderSize));
1183 __ bind(&no_parameter_map); 1151 __ bind(&no_parameter_map);
1184 1152
1185 // 2. Backing store. 1153 // 2. Backing store.
1186 __ lea(r8, Operand(r8, rcx, times_pointer_size, FixedArray::kHeaderSize)); 1154 __ lea(r8, Operand(r8, rcx, times_pointer_size, FixedArray::kHeaderSize));
1187 1155
1188 // 3. Arguments object. 1156 // 3. Arguments object.
1189 __ addq(r8, Immediate(Heap::kArgumentsObjectSize)); 1157 __ addq(r8, Immediate(Heap::kArgumentsObjectSize));
1190 1158
1191 // Do the allocation of all three objects in one go. 1159 // Do the allocation of all three objects in one go.
1192 __ Allocate(r8, rax, rdx, rdi, &runtime, TAG_OBJECT); 1160 __ Allocate(r8, rax, rdx, rdi, &runtime, TAG_OBJECT);
1193 1161
1194 // rax = address of new object(s) (tagged) 1162 // rax = address of new object(s) (tagged)
1195 // rcx = argument count (untagged) 1163 // rcx = argument count (untagged)
1196 // Get the arguments boilerplate from the current native context into rdi. 1164 // Get the arguments boilerplate from the current native context into rdi.
1197 Label has_mapped_parameters, copy; 1165 Label has_mapped_parameters, copy;
1198 __ movq(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 1166 __ movp(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
1199 __ movq(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset)); 1167 __ movp(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset));
1200 __ testq(rbx, rbx); 1168 __ testq(rbx, rbx);
1201 __ j(not_zero, &has_mapped_parameters, Label::kNear); 1169 __ j(not_zero, &has_mapped_parameters, Label::kNear);
1202 1170
1203 const int kIndex = Context::ARGUMENTS_BOILERPLATE_INDEX; 1171 const int kIndex = Context::ARGUMENTS_BOILERPLATE_INDEX;
1204 __ movq(rdi, Operand(rdi, Context::SlotOffset(kIndex))); 1172 __ movp(rdi, Operand(rdi, Context::SlotOffset(kIndex)));
1205 __ jmp(&copy, Label::kNear); 1173 __ jmp(&copy, Label::kNear);
1206 1174
1207 const int kAliasedIndex = Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX; 1175 const int kAliasedIndex = Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX;
1208 __ bind(&has_mapped_parameters); 1176 __ bind(&has_mapped_parameters);
1209 __ movq(rdi, Operand(rdi, Context::SlotOffset(kAliasedIndex))); 1177 __ movp(rdi, Operand(rdi, Context::SlotOffset(kAliasedIndex)));
1210 __ bind(&copy); 1178 __ bind(&copy);
1211 1179
1212 // rax = address of new object (tagged) 1180 // rax = address of new object (tagged)
1213 // rbx = mapped parameter count (untagged) 1181 // rbx = mapped parameter count (untagged)
1214 // rcx = argument count (untagged) 1182 // rcx = argument count (untagged)
1215 // rdi = address of boilerplate object (tagged) 1183 // rdi = address of boilerplate object (tagged)
1216 // Copy the JS object part. 1184 // Copy the JS object part.
1217 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { 1185 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
1218 __ movq(rdx, FieldOperand(rdi, i)); 1186 __ movp(rdx, FieldOperand(rdi, i));
1219 __ movq(FieldOperand(rax, i), rdx); 1187 __ movp(FieldOperand(rax, i), rdx);
1220 } 1188 }
1221 1189
1222 // Set up the callee in-object property. 1190 // Set up the callee in-object property.
1223 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); 1191 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
1224 __ movq(rdx, args.GetArgumentOperand(0)); 1192 __ movp(rdx, args.GetArgumentOperand(0));
1225 __ movq(FieldOperand(rax, JSObject::kHeaderSize + 1193 __ movp(FieldOperand(rax, JSObject::kHeaderSize +
1226 Heap::kArgumentsCalleeIndex * kPointerSize), 1194 Heap::kArgumentsCalleeIndex * kPointerSize),
1227 rdx); 1195 rdx);
1228 1196
1229 // Use the length (smi tagged) and set that as an in-object property too. 1197 // Use the length (smi tagged) and set that as an in-object property too.
1230 // Note: rcx is tagged from here on. 1198 // Note: rcx is tagged from here on.
1231 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); 1199 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
1232 __ Integer32ToSmi(rcx, rcx); 1200 __ Integer32ToSmi(rcx, rcx);
1233 __ movq(FieldOperand(rax, JSObject::kHeaderSize + 1201 __ movp(FieldOperand(rax, JSObject::kHeaderSize +
1234 Heap::kArgumentsLengthIndex * kPointerSize), 1202 Heap::kArgumentsLengthIndex * kPointerSize),
1235 rcx); 1203 rcx);
1236 1204
1237 // Set up the elements pointer in the allocated arguments object. 1205 // Set up the elements pointer in the allocated arguments object.
1238 // If we allocated a parameter map, edi will point there, otherwise to the 1206 // If we allocated a parameter map, edi will point there, otherwise to the
1239 // backing store. 1207 // backing store.
1240 __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSize)); 1208 __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSize));
1241 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi); 1209 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi);
1242 1210
1243 // rax = address of new object (tagged) 1211 // rax = address of new object (tagged)
1244 // rbx = mapped parameter count (untagged) 1212 // rbx = mapped parameter count (untagged)
1245 // rcx = argument count (tagged) 1213 // rcx = argument count (tagged)
1246 // rdi = address of parameter map or backing store (tagged) 1214 // rdi = address of parameter map or backing store (tagged)
1247 1215
1248 // Initialize parameter map. If there are no mapped arguments, we're done. 1216 // Initialize parameter map. If there are no mapped arguments, we're done.
1249 Label skip_parameter_map; 1217 Label skip_parameter_map;
1250 __ testq(rbx, rbx); 1218 __ testq(rbx, rbx);
1251 __ j(zero, &skip_parameter_map); 1219 __ j(zero, &skip_parameter_map);
1252 1220
1253 __ LoadRoot(kScratchRegister, Heap::kNonStrictArgumentsElementsMapRootIndex); 1221 __ LoadRoot(kScratchRegister, Heap::kNonStrictArgumentsElementsMapRootIndex);
1254 // rbx contains the untagged argument count. Add 2 and tag to write. 1222 // rbx contains the untagged argument count. Add 2 and tag to write.
1255 __ movq(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); 1223 __ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister);
1256 __ Integer64PlusConstantToSmi(r9, rbx, 2); 1224 __ Integer64PlusConstantToSmi(r9, rbx, 2);
1257 __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), r9); 1225 __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), r9);
1258 __ movq(FieldOperand(rdi, FixedArray::kHeaderSize + 0 * kPointerSize), rsi); 1226 __ movp(FieldOperand(rdi, FixedArray::kHeaderSize + 0 * kPointerSize), rsi);
1259 __ lea(r9, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize)); 1227 __ lea(r9, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize));
1260 __ movq(FieldOperand(rdi, FixedArray::kHeaderSize + 1 * kPointerSize), r9); 1228 __ movp(FieldOperand(rdi, FixedArray::kHeaderSize + 1 * kPointerSize), r9);
1261 1229
1262 // Copy the parameter slots and the holes in the arguments. 1230 // Copy the parameter slots and the holes in the arguments.
1263 // We need to fill in mapped_parameter_count slots. They index the context, 1231 // We need to fill in mapped_parameter_count slots. They index the context,
1264 // where parameters are stored in reverse order, at 1232 // where parameters are stored in reverse order, at
1265 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 1233 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1
1266 // The mapped parameter thus need to get indices 1234 // The mapped parameter thus need to get indices
1267 // MIN_CONTEXT_SLOTS+parameter_count-1 .. 1235 // MIN_CONTEXT_SLOTS+parameter_count-1 ..
1268 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count 1236 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
1269 // We loop from right to left. 1237 // We loop from right to left.
1270 Label parameters_loop, parameters_test; 1238 Label parameters_loop, parameters_test;
1271 1239
1272 // Load tagged parameter count into r9. 1240 // Load tagged parameter count into r9.
1273 __ Integer32ToSmi(r9, rbx); 1241 __ Integer32ToSmi(r9, rbx);
1274 __ Move(r8, Smi::FromInt(Context::MIN_CONTEXT_SLOTS)); 1242 __ Move(r8, Smi::FromInt(Context::MIN_CONTEXT_SLOTS));
1275 __ addq(r8, args.GetArgumentOperand(2)); 1243 __ addq(r8, args.GetArgumentOperand(2));
1276 __ subq(r8, r9); 1244 __ subq(r8, r9);
1277 __ Move(r11, factory->the_hole_value()); 1245 __ Move(r11, factory->the_hole_value());
1278 __ movq(rdx, rdi); 1246 __ movp(rdx, rdi);
1279 __ lea(rdi, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize)); 1247 __ lea(rdi, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize));
1280 // r9 = loop variable (tagged) 1248 // r9 = loop variable (tagged)
1281 // r8 = mapping index (tagged) 1249 // r8 = mapping index (tagged)
1282 // r11 = the hole value 1250 // r11 = the hole value
1283 // rdx = address of parameter map (tagged) 1251 // rdx = address of parameter map (tagged)
1284 // rdi = address of backing store (tagged) 1252 // rdi = address of backing store (tagged)
1285 __ jmp(&parameters_test, Label::kNear); 1253 __ jmp(&parameters_test, Label::kNear);
1286 1254
1287 __ bind(&parameters_loop); 1255 __ bind(&parameters_loop);
1288 __ SmiSubConstant(r9, r9, Smi::FromInt(1)); 1256 __ SmiSubConstant(r9, r9, Smi::FromInt(1));
1289 __ SmiToInteger64(kScratchRegister, r9); 1257 __ SmiToInteger64(kScratchRegister, r9);
1290 __ movq(FieldOperand(rdx, kScratchRegister, 1258 __ movp(FieldOperand(rdx, kScratchRegister,
1291 times_pointer_size, 1259 times_pointer_size,
1292 kParameterMapHeaderSize), 1260 kParameterMapHeaderSize),
1293 r8); 1261 r8);
1294 __ movq(FieldOperand(rdi, kScratchRegister, 1262 __ movp(FieldOperand(rdi, kScratchRegister,
1295 times_pointer_size, 1263 times_pointer_size,
1296 FixedArray::kHeaderSize), 1264 FixedArray::kHeaderSize),
1297 r11); 1265 r11);
1298 __ SmiAddConstant(r8, r8, Smi::FromInt(1)); 1266 __ SmiAddConstant(r8, r8, Smi::FromInt(1));
1299 __ bind(&parameters_test); 1267 __ bind(&parameters_test);
1300 __ SmiTest(r9); 1268 __ SmiTest(r9);
1301 __ j(not_zero, &parameters_loop, Label::kNear); 1269 __ j(not_zero, &parameters_loop, Label::kNear);
1302 1270
1303 __ bind(&skip_parameter_map); 1271 __ bind(&skip_parameter_map);
1304 1272
1305 // rcx = argument count (tagged) 1273 // rcx = argument count (tagged)
1306 // rdi = address of backing store (tagged) 1274 // rdi = address of backing store (tagged)
1307 // Copy arguments header and remaining slots (if there are any). 1275 // Copy arguments header and remaining slots (if there are any).
1308 __ Move(FieldOperand(rdi, FixedArray::kMapOffset), 1276 __ Move(FieldOperand(rdi, FixedArray::kMapOffset),
1309 factory->fixed_array_map()); 1277 factory->fixed_array_map());
1310 __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); 1278 __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), rcx);
1311 1279
1312 Label arguments_loop, arguments_test; 1280 Label arguments_loop, arguments_test;
1313 __ movq(r8, rbx); 1281 __ movp(r8, rbx);
1314 __ movq(rdx, args.GetArgumentOperand(1)); 1282 __ movp(rdx, args.GetArgumentOperand(1));
1315 // Untag rcx for the loop below. 1283 // Untag rcx for the loop below.
1316 __ SmiToInteger64(rcx, rcx); 1284 __ SmiToInteger64(rcx, rcx);
1317 __ lea(kScratchRegister, Operand(r8, times_pointer_size, 0)); 1285 __ lea(kScratchRegister, Operand(r8, times_pointer_size, 0));
1318 __ subq(rdx, kScratchRegister); 1286 __ subq(rdx, kScratchRegister);
1319 __ jmp(&arguments_test, Label::kNear); 1287 __ jmp(&arguments_test, Label::kNear);
1320 1288
1321 __ bind(&arguments_loop); 1289 __ bind(&arguments_loop);
1322 __ subq(rdx, Immediate(kPointerSize)); 1290 __ subq(rdx, Immediate(kPointerSize));
1323 __ movq(r9, Operand(rdx, 0)); 1291 __ movp(r9, Operand(rdx, 0));
1324 __ movq(FieldOperand(rdi, r8, 1292 __ movp(FieldOperand(rdi, r8,
1325 times_pointer_size, 1293 times_pointer_size,
1326 FixedArray::kHeaderSize), 1294 FixedArray::kHeaderSize),
1327 r9); 1295 r9);
1328 __ addq(r8, Immediate(1)); 1296 __ addq(r8, Immediate(1));
1329 1297
1330 __ bind(&arguments_test); 1298 __ bind(&arguments_test);
1331 __ cmpq(r8, rcx); 1299 __ cmpq(r8, rcx);
1332 __ j(less, &arguments_loop, Label::kNear); 1300 __ j(less, &arguments_loop, Label::kNear);
1333 1301
1334 // Return and remove the on-stack parameters. 1302 // Return and remove the on-stack parameters.
1335 __ ret(3 * kPointerSize); 1303 __ ret(3 * kPointerSize);
1336 1304
1337 // Do the runtime call to allocate the arguments object. 1305 // Do the runtime call to allocate the arguments object.
1338 // rcx = argument count (untagged) 1306 // rcx = argument count (untagged)
1339 __ bind(&runtime); 1307 __ bind(&runtime);
1340 __ Integer32ToSmi(rcx, rcx); 1308 __ Integer32ToSmi(rcx, rcx);
1341 __ movq(args.GetArgumentOperand(2), rcx); // Patch argument count. 1309 __ movp(args.GetArgumentOperand(2), rcx); // Patch argument count.
1342 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); 1310 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
1343 } 1311 }
1344 1312
1345 1313
1346 void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) { 1314 void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) {
1347 // rsp[0] : return address 1315 // rsp[0] : return address
1348 // rsp[8] : number of parameters 1316 // rsp[8] : number of parameters
1349 // rsp[16] : receiver displacement 1317 // rsp[16] : receiver displacement
1350 // rsp[24] : function 1318 // rsp[24] : function
1351 1319
1352 // Check if the calling frame is an arguments adaptor frame. 1320 // Check if the calling frame is an arguments adaptor frame.
1353 Label runtime; 1321 Label runtime;
1354 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 1322 __ movp(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
1355 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); 1323 __ movp(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
1356 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 1324 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
1357 __ j(not_equal, &runtime); 1325 __ j(not_equal, &runtime);
1358 1326
1359 // Patch the arguments.length and the parameters pointer. 1327 // Patch the arguments.length and the parameters pointer.
1360 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER); 1328 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER);
1361 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 1329 __ movp(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
1362 __ movq(args.GetArgumentOperand(2), rcx); 1330 __ movp(args.GetArgumentOperand(2), rcx);
1363 __ SmiToInteger64(rcx, rcx); 1331 __ SmiToInteger64(rcx, rcx);
1364 __ lea(rdx, Operand(rdx, rcx, times_pointer_size, 1332 __ lea(rdx, Operand(rdx, rcx, times_pointer_size,
1365 StandardFrameConstants::kCallerSPOffset)); 1333 StandardFrameConstants::kCallerSPOffset));
1366 __ movq(args.GetArgumentOperand(1), rdx); 1334 __ movp(args.GetArgumentOperand(1), rdx);
1367 1335
1368 __ bind(&runtime); 1336 __ bind(&runtime);
1369 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); 1337 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
1370 } 1338 }
1371 1339
1372 1340
1373 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { 1341 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
1374 // rsp[0] : return address 1342 // rsp[0] : return address
1375 // rsp[8] : number of parameters 1343 // rsp[8] : number of parameters
1376 // rsp[16] : receiver displacement 1344 // rsp[16] : receiver displacement
1377 // rsp[24] : function 1345 // rsp[24] : function
1378 1346
1379 // Check if the calling frame is an arguments adaptor frame. 1347 // Check if the calling frame is an arguments adaptor frame.
1380 Label adaptor_frame, try_allocate, runtime; 1348 Label adaptor_frame, try_allocate, runtime;
1381 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 1349 __ movp(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
1382 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); 1350 __ movp(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
1383 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 1351 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
1384 __ j(equal, &adaptor_frame); 1352 __ j(equal, &adaptor_frame);
1385 1353
1386 // Get the length from the frame. 1354 // Get the length from the frame.
1387 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER); 1355 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER);
1388 __ movq(rcx, args.GetArgumentOperand(2)); 1356 __ movp(rcx, args.GetArgumentOperand(2));
1389 __ SmiToInteger64(rcx, rcx); 1357 __ SmiToInteger64(rcx, rcx);
1390 __ jmp(&try_allocate); 1358 __ jmp(&try_allocate);
1391 1359
1392 // Patch the arguments.length and the parameters pointer. 1360 // Patch the arguments.length and the parameters pointer.
1393 __ bind(&adaptor_frame); 1361 __ bind(&adaptor_frame);
1394 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 1362 __ movp(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
1395 __ movq(args.GetArgumentOperand(2), rcx); 1363 __ movp(args.GetArgumentOperand(2), rcx);
1396 __ SmiToInteger64(rcx, rcx); 1364 __ SmiToInteger64(rcx, rcx);
1397 __ lea(rdx, Operand(rdx, rcx, times_pointer_size, 1365 __ lea(rdx, Operand(rdx, rcx, times_pointer_size,
1398 StandardFrameConstants::kCallerSPOffset)); 1366 StandardFrameConstants::kCallerSPOffset));
1399 __ movq(args.GetArgumentOperand(1), rdx); 1367 __ movp(args.GetArgumentOperand(1), rdx);
1400 1368
1401 // Try the new space allocation. Start out with computing the size of 1369 // Try the new space allocation. Start out with computing the size of
1402 // the arguments object and the elements array. 1370 // the arguments object and the elements array.
1403 Label add_arguments_object; 1371 Label add_arguments_object;
1404 __ bind(&try_allocate); 1372 __ bind(&try_allocate);
1405 __ testq(rcx, rcx); 1373 __ testq(rcx, rcx);
1406 __ j(zero, &add_arguments_object, Label::kNear); 1374 __ j(zero, &add_arguments_object, Label::kNear);
1407 __ lea(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize)); 1375 __ lea(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize));
1408 __ bind(&add_arguments_object); 1376 __ bind(&add_arguments_object);
1409 __ addq(rcx, Immediate(Heap::kArgumentsObjectSizeStrict)); 1377 __ addq(rcx, Immediate(Heap::kArgumentsObjectSizeStrict));
1410 1378
1411 // Do the allocation of both objects in one go. 1379 // Do the allocation of both objects in one go.
1412 __ Allocate(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT); 1380 __ Allocate(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT);
1413 1381
1414 // Get the arguments boilerplate from the current native context. 1382 // Get the arguments boilerplate from the current native context.
1415 __ movq(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 1383 __ movp(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
1416 __ movq(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset)); 1384 __ movp(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset));
1417 const int offset = 1385 const int offset =
1418 Context::SlotOffset(Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX); 1386 Context::SlotOffset(Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX);
1419 __ movq(rdi, Operand(rdi, offset)); 1387 __ movp(rdi, Operand(rdi, offset));
1420 1388
1421 // Copy the JS object part. 1389 // Copy the JS object part.
1422 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { 1390 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
1423 __ movq(rbx, FieldOperand(rdi, i)); 1391 __ movp(rbx, FieldOperand(rdi, i));
1424 __ movq(FieldOperand(rax, i), rbx); 1392 __ movp(FieldOperand(rax, i), rbx);
1425 } 1393 }
1426 1394
1427 // Get the length (smi tagged) and set that as an in-object property too. 1395 // Get the length (smi tagged) and set that as an in-object property too.
1428 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); 1396 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
1429 __ movq(rcx, args.GetArgumentOperand(2)); 1397 __ movp(rcx, args.GetArgumentOperand(2));
1430 __ movq(FieldOperand(rax, JSObject::kHeaderSize + 1398 __ movp(FieldOperand(rax, JSObject::kHeaderSize +
1431 Heap::kArgumentsLengthIndex * kPointerSize), 1399 Heap::kArgumentsLengthIndex * kPointerSize),
1432 rcx); 1400 rcx);
1433 1401
1434 // If there are no actual arguments, we're done. 1402 // If there are no actual arguments, we're done.
1435 Label done; 1403 Label done;
1436 __ testq(rcx, rcx); 1404 __ testq(rcx, rcx);
1437 __ j(zero, &done); 1405 __ j(zero, &done);
1438 1406
1439 // Get the parameters pointer from the stack. 1407 // Get the parameters pointer from the stack.
1440 __ movq(rdx, args.GetArgumentOperand(1)); 1408 __ movp(rdx, args.GetArgumentOperand(1));
1441 1409
1442 // Set up the elements pointer in the allocated arguments object and 1410 // Set up the elements pointer in the allocated arguments object and
1443 // initialize the header in the elements fixed array. 1411 // initialize the header in the elements fixed array.
1444 __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSizeStrict)); 1412 __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSizeStrict));
1445 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi); 1413 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi);
1446 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); 1414 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex);
1447 __ movq(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); 1415 __ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister);
1448 1416
1449 1417
1450 __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); 1418 __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), rcx);
1451 // Untag the length for the loop below. 1419 // Untag the length for the loop below.
1452 __ SmiToInteger64(rcx, rcx); 1420 __ SmiToInteger64(rcx, rcx);
1453 1421
1454 // Copy the fixed array slots. 1422 // Copy the fixed array slots.
1455 Label loop; 1423 Label loop;
1456 __ bind(&loop); 1424 __ bind(&loop);
1457 __ movq(rbx, Operand(rdx, -1 * kPointerSize)); // Skip receiver. 1425 __ movp(rbx, Operand(rdx, -1 * kPointerSize)); // Skip receiver.
1458 __ movq(FieldOperand(rdi, FixedArray::kHeaderSize), rbx); 1426 __ movp(FieldOperand(rdi, FixedArray::kHeaderSize), rbx);
1459 __ addq(rdi, Immediate(kPointerSize)); 1427 __ addq(rdi, Immediate(kPointerSize));
1460 __ subq(rdx, Immediate(kPointerSize)); 1428 __ subq(rdx, Immediate(kPointerSize));
1461 __ decq(rcx); 1429 __ decq(rcx);
1462 __ j(not_zero, &loop); 1430 __ j(not_zero, &loop);
1463 1431
1464 // Return and remove the on-stack parameters. 1432 // Return and remove the on-stack parameters.
1465 __ bind(&done); 1433 __ bind(&done);
1466 __ ret(3 * kPointerSize); 1434 __ ret(3 * kPointerSize);
1467 1435
1468 // Do the runtime call to allocate the arguments object. 1436 // Do the runtime call to allocate the arguments object.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1501 Isolate* isolate = masm->isolate(); 1469 Isolate* isolate = masm->isolate();
1502 ExternalReference address_of_regexp_stack_memory_address = 1470 ExternalReference address_of_regexp_stack_memory_address =
1503 ExternalReference::address_of_regexp_stack_memory_address(isolate); 1471 ExternalReference::address_of_regexp_stack_memory_address(isolate);
1504 ExternalReference address_of_regexp_stack_memory_size = 1472 ExternalReference address_of_regexp_stack_memory_size =
1505 ExternalReference::address_of_regexp_stack_memory_size(isolate); 1473 ExternalReference::address_of_regexp_stack_memory_size(isolate);
1506 __ Load(kScratchRegister, address_of_regexp_stack_memory_size); 1474 __ Load(kScratchRegister, address_of_regexp_stack_memory_size);
1507 __ testq(kScratchRegister, kScratchRegister); 1475 __ testq(kScratchRegister, kScratchRegister);
1508 __ j(zero, &runtime); 1476 __ j(zero, &runtime);
1509 1477
1510 // Check that the first argument is a JSRegExp object. 1478 // Check that the first argument is a JSRegExp object.
1511 __ movq(rax, args.GetArgumentOperand(JS_REG_EXP_OBJECT_ARGUMENT_INDEX)); 1479 __ movp(rax, args.GetArgumentOperand(JS_REG_EXP_OBJECT_ARGUMENT_INDEX));
1512 __ JumpIfSmi(rax, &runtime); 1480 __ JumpIfSmi(rax, &runtime);
1513 __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister); 1481 __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister);
1514 __ j(not_equal, &runtime); 1482 __ j(not_equal, &runtime);
1515 1483
1516 // Check that the RegExp has been compiled (data contains a fixed array). 1484 // Check that the RegExp has been compiled (data contains a fixed array).
1517 __ movq(rax, FieldOperand(rax, JSRegExp::kDataOffset)); 1485 __ movp(rax, FieldOperand(rax, JSRegExp::kDataOffset));
1518 if (FLAG_debug_code) { 1486 if (FLAG_debug_code) {
1519 Condition is_smi = masm->CheckSmi(rax); 1487 Condition is_smi = masm->CheckSmi(rax);
1520 __ Check(NegateCondition(is_smi), 1488 __ Check(NegateCondition(is_smi),
1521 kUnexpectedTypeForRegExpDataFixedArrayExpected); 1489 kUnexpectedTypeForRegExpDataFixedArrayExpected);
1522 __ CmpObjectType(rax, FIXED_ARRAY_TYPE, kScratchRegister); 1490 __ CmpObjectType(rax, FIXED_ARRAY_TYPE, kScratchRegister);
1523 __ Check(equal, kUnexpectedTypeForRegExpDataFixedArrayExpected); 1491 __ Check(equal, kUnexpectedTypeForRegExpDataFixedArrayExpected);
1524 } 1492 }
1525 1493
1526 // rax: RegExp data (FixedArray) 1494 // rax: RegExp data (FixedArray)
1527 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. 1495 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
1528 __ SmiToInteger32(rbx, FieldOperand(rax, JSRegExp::kDataTagOffset)); 1496 __ SmiToInteger32(rbx, FieldOperand(rax, JSRegExp::kDataTagOffset));
1529 __ cmpl(rbx, Immediate(JSRegExp::IRREGEXP)); 1497 __ cmpl(rbx, Immediate(JSRegExp::IRREGEXP));
1530 __ j(not_equal, &runtime); 1498 __ j(not_equal, &runtime);
1531 1499
1532 // rax: RegExp data (FixedArray) 1500 // rax: RegExp data (FixedArray)
1533 // Check that the number of captures fit in the static offsets vector buffer. 1501 // Check that the number of captures fit in the static offsets vector buffer.
1534 __ SmiToInteger32(rdx, 1502 __ SmiToInteger32(rdx,
1535 FieldOperand(rax, JSRegExp::kIrregexpCaptureCountOffset)); 1503 FieldOperand(rax, JSRegExp::kIrregexpCaptureCountOffset));
1536 // Check (number_of_captures + 1) * 2 <= offsets vector size 1504 // Check (number_of_captures + 1) * 2 <= offsets vector size
1537 // Or number_of_captures <= offsets vector size / 2 - 1 1505 // Or number_of_captures <= offsets vector size / 2 - 1
1538 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); 1506 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2);
1539 __ cmpl(rdx, Immediate(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1)); 1507 __ cmpl(rdx, Immediate(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1));
1540 __ j(above, &runtime); 1508 __ j(above, &runtime);
1541 1509
1542 // Reset offset for possibly sliced string. 1510 // Reset offset for possibly sliced string.
1543 __ Set(r14, 0); 1511 __ Set(r14, 0);
1544 __ movq(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX)); 1512 __ movp(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX));
1545 __ JumpIfSmi(rdi, &runtime); 1513 __ JumpIfSmi(rdi, &runtime);
1546 __ movq(r15, rdi); // Make a copy of the original subject string. 1514 __ movp(r15, rdi); // Make a copy of the original subject string.
1547 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); 1515 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
1548 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 1516 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
1549 // rax: RegExp data (FixedArray) 1517 // rax: RegExp data (FixedArray)
1550 // rdi: subject string 1518 // rdi: subject string
1551 // r15: subject string 1519 // r15: subject string
1552 // Handle subject string according to its encoding and representation: 1520 // Handle subject string according to its encoding and representation:
1553 // (1) Sequential two byte? If yes, go to (9). 1521 // (1) Sequential two byte? If yes, go to (9).
1554 // (2) Sequential one byte? If yes, go to (6). 1522 // (2) Sequential one byte? If yes, go to (6).
1555 // (3) Anything but sequential or cons? If yes, go to (7). 1523 // (3) Anything but sequential or cons? If yes, go to (7).
1556 // (4) Cons string. If the string is flat, replace subject with first string. 1524 // (4) Cons string. If the string is flat, replace subject with first string.
1557 // Otherwise bailout. 1525 // Otherwise bailout.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1597 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); 1565 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
1598 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); 1566 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
1599 __ cmpq(rbx, Immediate(kExternalStringTag)); 1567 __ cmpq(rbx, Immediate(kExternalStringTag));
1600 __ j(greater_equal, &not_seq_nor_cons); // Go to (7). 1568 __ j(greater_equal, &not_seq_nor_cons); // Go to (7).
1601 1569
1602 // (4) Cons string. Check that it's flat. 1570 // (4) Cons string. Check that it's flat.
1603 // Replace subject with first string and reload instance type. 1571 // Replace subject with first string and reload instance type.
1604 __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset), 1572 __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset),
1605 Heap::kempty_stringRootIndex); 1573 Heap::kempty_stringRootIndex);
1606 __ j(not_equal, &runtime); 1574 __ j(not_equal, &runtime);
1607 __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); 1575 __ movp(rdi, FieldOperand(rdi, ConsString::kFirstOffset));
1608 __ bind(&check_underlying); 1576 __ bind(&check_underlying);
1609 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); 1577 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
1610 __ movq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 1578 __ movp(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
1611 1579
1612 // (5a) Is subject sequential two byte? If yes, go to (9). 1580 // (5a) Is subject sequential two byte? If yes, go to (9).
1613 __ testb(rbx, Immediate(kStringRepresentationMask | kStringEncodingMask)); 1581 __ testb(rbx, Immediate(kStringRepresentationMask | kStringEncodingMask));
1614 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); 1582 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
1615 __ j(zero, &seq_two_byte_string); // Go to (9). 1583 __ j(zero, &seq_two_byte_string); // Go to (9).
1616 // (5b) Is subject external? If yes, go to (8). 1584 // (5b) Is subject external? If yes, go to (8).
1617 __ testb(rbx, Immediate(kStringRepresentationMask)); 1585 __ testb(rbx, Immediate(kStringRepresentationMask));
1618 // The underlying external string is never a short external string. 1586 // The underlying external string is never a short external string.
1619 STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength); 1587 STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength);
1620 STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength); 1588 STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength);
1621 __ j(not_zero, &external_string); // Go to (8) 1589 __ j(not_zero, &external_string); // Go to (8)
1622 1590
1623 // (6) One byte sequential. Load regexp code for one byte. 1591 // (6) One byte sequential. Load regexp code for one byte.
1624 __ bind(&seq_one_byte_string); 1592 __ bind(&seq_one_byte_string);
1625 // rax: RegExp data (FixedArray) 1593 // rax: RegExp data (FixedArray)
1626 __ movq(r11, FieldOperand(rax, JSRegExp::kDataAsciiCodeOffset)); 1594 __ movp(r11, FieldOperand(rax, JSRegExp::kDataAsciiCodeOffset));
1627 __ Set(rcx, 1); // Type is one byte. 1595 __ Set(rcx, 1); // Type is one byte.
1628 1596
1629 // (E) Carry on. String handling is done. 1597 // (E) Carry on. String handling is done.
1630 __ bind(&check_code); 1598 __ bind(&check_code);
1631 // r11: irregexp code 1599 // r11: irregexp code
1632 // Check that the irregexp code has been generated for the actual string 1600 // Check that the irregexp code has been generated for the actual string
1633 // encoding. If it has, the field contains a code object otherwise it contains 1601 // encoding. If it has, the field contains a code object otherwise it contains
1634 // smi (code flushing support) 1602 // smi (code flushing support)
1635 __ JumpIfSmi(r11, &runtime); 1603 __ JumpIfSmi(r11, &runtime);
1636 1604
1637 // rdi: sequential subject string (or look-alike, external string) 1605 // rdi: sequential subject string (or look-alike, external string)
1638 // r15: original subject string 1606 // r15: original subject string
1639 // rcx: encoding of subject string (1 if ASCII, 0 if two_byte); 1607 // rcx: encoding of subject string (1 if ASCII, 0 if two_byte);
1640 // r11: code 1608 // r11: code
1641 // Load used arguments before starting to push arguments for call to native 1609 // Load used arguments before starting to push arguments for call to native
1642 // RegExp code to avoid handling changing stack height. 1610 // RegExp code to avoid handling changing stack height.
1643 // We have to use r15 instead of rdi to load the length because rdi might 1611 // We have to use r15 instead of rdi to load the length because rdi might
1644 // have been only made to look like a sequential string when it actually 1612 // have been only made to look like a sequential string when it actually
1645 // is an external string. 1613 // is an external string.
1646 __ movq(rbx, args.GetArgumentOperand(PREVIOUS_INDEX_ARGUMENT_INDEX)); 1614 __ movp(rbx, args.GetArgumentOperand(PREVIOUS_INDEX_ARGUMENT_INDEX));
1647 __ JumpIfNotSmi(rbx, &runtime); 1615 __ JumpIfNotSmi(rbx, &runtime);
1648 __ SmiCompare(rbx, FieldOperand(r15, String::kLengthOffset)); 1616 __ SmiCompare(rbx, FieldOperand(r15, String::kLengthOffset));
1649 __ j(above_equal, &runtime); 1617 __ j(above_equal, &runtime);
1650 __ SmiToInteger64(rbx, rbx); 1618 __ SmiToInteger64(rbx, rbx);
1651 1619
1652 // rdi: subject string 1620 // rdi: subject string
1653 // rbx: previous index 1621 // rbx: previous index
1654 // rcx: encoding of subject string (1 if ASCII 0 if two_byte); 1622 // rcx: encoding of subject string (1 if ASCII 0 if two_byte);
1655 // r11: code 1623 // r11: code
1656 // All checks done. Now push arguments for native regexp code. 1624 // All checks done. Now push arguments for native regexp code.
1657 Counters* counters = masm->isolate()->counters(); 1625 Counters* counters = masm->isolate()->counters();
1658 __ IncrementCounter(counters->regexp_entry_native(), 1); 1626 __ IncrementCounter(counters->regexp_entry_native(), 1);
1659 1627
1660 // Isolates: note we add an additional parameter here (isolate pointer). 1628 // Isolates: note we add an additional parameter here (isolate pointer).
1661 static const int kRegExpExecuteArguments = 9; 1629 static const int kRegExpExecuteArguments = 9;
1662 int argument_slots_on_stack = 1630 int argument_slots_on_stack =
1663 masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments); 1631 masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments);
1664 __ EnterApiExitFrame(argument_slots_on_stack); 1632 __ EnterApiExitFrame(argument_slots_on_stack);
1665 1633
1666 // Argument 9: Pass current isolate address. 1634 // Argument 9: Pass current isolate address.
1667 __ LoadAddress(kScratchRegister, 1635 __ LoadAddress(kScratchRegister,
1668 ExternalReference::isolate_address(masm->isolate())); 1636 ExternalReference::isolate_address(masm->isolate()));
1669 __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize), 1637 __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kRegisterSize),
1670 kScratchRegister); 1638 kScratchRegister);
1671 1639
1672 // Argument 8: Indicate that this is a direct call from JavaScript. 1640 // Argument 8: Indicate that this is a direct call from JavaScript.
1673 __ movq(Operand(rsp, (argument_slots_on_stack - 2) * kPointerSize), 1641 __ movq(Operand(rsp, (argument_slots_on_stack - 2) * kRegisterSize),
1674 Immediate(1)); 1642 Immediate(1));
1675 1643
1676 // Argument 7: Start (high end) of backtracking stack memory area. 1644 // Argument 7: Start (high end) of backtracking stack memory area.
1677 __ Move(kScratchRegister, address_of_regexp_stack_memory_address); 1645 __ Move(kScratchRegister, address_of_regexp_stack_memory_address);
1678 __ movq(r9, Operand(kScratchRegister, 0)); 1646 __ movp(r9, Operand(kScratchRegister, 0));
1679 __ Move(kScratchRegister, address_of_regexp_stack_memory_size); 1647 __ Move(kScratchRegister, address_of_regexp_stack_memory_size);
1680 __ addq(r9, Operand(kScratchRegister, 0)); 1648 __ addq(r9, Operand(kScratchRegister, 0));
1681 __ movq(Operand(rsp, (argument_slots_on_stack - 3) * kPointerSize), r9); 1649 __ movq(Operand(rsp, (argument_slots_on_stack - 3) * kRegisterSize), r9);
1682 1650
1683 // Argument 6: Set the number of capture registers to zero to force global 1651 // Argument 6: Set the number of capture registers to zero to force global
1684 // regexps to behave as non-global. This does not affect non-global regexps. 1652 // regexps to behave as non-global. This does not affect non-global regexps.
1685 // Argument 6 is passed in r9 on Linux and on the stack on Windows. 1653 // Argument 6 is passed in r9 on Linux and on the stack on Windows.
1686 #ifdef _WIN64 1654 #ifdef _WIN64
1687 __ movq(Operand(rsp, (argument_slots_on_stack - 4) * kPointerSize), 1655 __ movq(Operand(rsp, (argument_slots_on_stack - 4) * kRegisterSize),
1688 Immediate(0)); 1656 Immediate(0));
1689 #else 1657 #else
1690 __ Set(r9, 0); 1658 __ Set(r9, 0);
1691 #endif 1659 #endif
1692 1660
1693 // Argument 5: static offsets vector buffer. 1661 // Argument 5: static offsets vector buffer.
1694 __ LoadAddress(r8, 1662 __ LoadAddress(r8,
1695 ExternalReference::address_of_static_offsets_vector(isolate)); 1663 ExternalReference::address_of_static_offsets_vector(isolate));
1696 // Argument 5 passed in r8 on Linux and on the stack on Windows. 1664 // Argument 5 passed in r8 on Linux and on the stack on Windows.
1697 #ifdef _WIN64 1665 #ifdef _WIN64
1698 __ movq(Operand(rsp, (argument_slots_on_stack - 5) * kPointerSize), r8); 1666 __ movq(Operand(rsp, (argument_slots_on_stack - 5) * kRegisterSize), r8);
1699 #endif 1667 #endif
1700 1668
1701 // rdi: subject string 1669 // rdi: subject string
1702 // rbx: previous index 1670 // rbx: previous index
1703 // rcx: encoding of subject string (1 if ASCII 0 if two_byte); 1671 // rcx: encoding of subject string (1 if ASCII 0 if two_byte);
1704 // r11: code 1672 // r11: code
1705 // r14: slice offset 1673 // r14: slice offset
1706 // r15: original subject string 1674 // r15: original subject string
1707 1675
1708 // Argument 2: Previous index. 1676 // Argument 2: Previous index.
1709 __ movq(arg_reg_2, rbx); 1677 __ movp(arg_reg_2, rbx);
1710 1678
1711 // Argument 4: End of string data 1679 // Argument 4: End of string data
1712 // Argument 3: Start of string data 1680 // Argument 3: Start of string data
1713 Label setup_two_byte, setup_rest, got_length, length_not_from_slice; 1681 Label setup_two_byte, setup_rest, got_length, length_not_from_slice;
1714 // Prepare start and end index of the input. 1682 // Prepare start and end index of the input.
1715 // Load the length from the original sliced string if that is the case. 1683 // Load the length from the original sliced string if that is the case.
1716 __ addq(rbx, r14); 1684 __ addq(rbx, r14);
1717 __ SmiToInteger32(arg_reg_3, FieldOperand(r15, String::kLengthOffset)); 1685 __ SmiToInteger32(arg_reg_3, FieldOperand(r15, String::kLengthOffset));
1718 __ addq(r14, arg_reg_3); // Using arg3 as scratch. 1686 __ addq(r14, arg_reg_3); // Using arg3 as scratch.
1719 1687
(...skipping 12 matching lines...) Expand all
1732 FieldOperand(rdi, r14, times_2, SeqTwoByteString::kHeaderSize)); 1700 FieldOperand(rdi, r14, times_2, SeqTwoByteString::kHeaderSize));
1733 __ lea(arg_reg_3, 1701 __ lea(arg_reg_3,
1734 FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize)); 1702 FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize));
1735 __ bind(&setup_rest); 1703 __ bind(&setup_rest);
1736 1704
1737 // Argument 1: Original subject string. 1705 // Argument 1: Original subject string.
1738 // The original subject is in the previous stack frame. Therefore we have to 1706 // The original subject is in the previous stack frame. Therefore we have to
1739 // use rbp, which points exactly to one pointer size below the previous rsp. 1707 // use rbp, which points exactly to one pointer size below the previous rsp.
1740 // (Because creating a new stack frame pushes the previous rbp onto the stack 1708 // (Because creating a new stack frame pushes the previous rbp onto the stack
1741 // and thereby moves up rsp by one kPointerSize.) 1709 // and thereby moves up rsp by one kPointerSize.)
1742 __ movq(arg_reg_1, r15); 1710 __ movp(arg_reg_1, r15);
1743 1711
1744 // Locate the code entry and call it. 1712 // Locate the code entry and call it.
1745 __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag)); 1713 __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag));
1746 __ call(r11); 1714 __ call(r11);
1747 1715
1748 __ LeaveApiExitFrame(true); 1716 __ LeaveApiExitFrame(true);
1749 1717
1750 // Check the result. 1718 // Check the result.
1751 Label success; 1719 Label success;
1752 Label exception; 1720 Label exception;
1753 __ cmpl(rax, Immediate(1)); 1721 __ cmpl(rax, Immediate(1));
1754 // We expect exactly one result since we force the called regexp to behave 1722 // We expect exactly one result since we force the called regexp to behave
1755 // as non-global. 1723 // as non-global.
1756 __ j(equal, &success, Label::kNear); 1724 __ j(equal, &success, Label::kNear);
1757 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION)); 1725 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION));
1758 __ j(equal, &exception); 1726 __ j(equal, &exception);
1759 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE)); 1727 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE));
1760 // If none of the above, it can only be retry. 1728 // If none of the above, it can only be retry.
1761 // Handle that in the runtime system. 1729 // Handle that in the runtime system.
1762 __ j(not_equal, &runtime); 1730 __ j(not_equal, &runtime);
1763 1731
1764 // For failure return null. 1732 // For failure return null.
1765 __ LoadRoot(rax, Heap::kNullValueRootIndex); 1733 __ LoadRoot(rax, Heap::kNullValueRootIndex);
1766 __ ret(REG_EXP_EXEC_ARGUMENT_COUNT * kPointerSize); 1734 __ ret(REG_EXP_EXEC_ARGUMENT_COUNT * kPointerSize);
1767 1735
1768 // Load RegExp data. 1736 // Load RegExp data.
1769 __ bind(&success); 1737 __ bind(&success);
1770 __ movq(rax, args.GetArgumentOperand(JS_REG_EXP_OBJECT_ARGUMENT_INDEX)); 1738 __ movp(rax, args.GetArgumentOperand(JS_REG_EXP_OBJECT_ARGUMENT_INDEX));
1771 __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset)); 1739 __ movp(rcx, FieldOperand(rax, JSRegExp::kDataOffset));
1772 __ SmiToInteger32(rax, 1740 __ SmiToInteger32(rax,
1773 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); 1741 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset));
1774 // Calculate number of capture registers (number_of_captures + 1) * 2. 1742 // Calculate number of capture registers (number_of_captures + 1) * 2.
1775 __ leal(rdx, Operand(rax, rax, times_1, 2)); 1743 __ leal(rdx, Operand(rax, rax, times_1, 2));
1776 1744
1777 // rdx: Number of capture registers 1745 // rdx: Number of capture registers
1778 // Check that the fourth object is a JSArray object. 1746 // Check that the fourth object is a JSArray object.
1779 __ movq(r15, args.GetArgumentOperand(LAST_MATCH_INFO_ARGUMENT_INDEX)); 1747 __ movp(r15, args.GetArgumentOperand(LAST_MATCH_INFO_ARGUMENT_INDEX));
1780 __ JumpIfSmi(r15, &runtime); 1748 __ JumpIfSmi(r15, &runtime);
1781 __ CmpObjectType(r15, JS_ARRAY_TYPE, kScratchRegister); 1749 __ CmpObjectType(r15, JS_ARRAY_TYPE, kScratchRegister);
1782 __ j(not_equal, &runtime); 1750 __ j(not_equal, &runtime);
1783 // Check that the JSArray is in fast case. 1751 // Check that the JSArray is in fast case.
1784 __ movq(rbx, FieldOperand(r15, JSArray::kElementsOffset)); 1752 __ movp(rbx, FieldOperand(r15, JSArray::kElementsOffset));
1785 __ movq(rax, FieldOperand(rbx, HeapObject::kMapOffset)); 1753 __ movp(rax, FieldOperand(rbx, HeapObject::kMapOffset));
1786 __ CompareRoot(rax, Heap::kFixedArrayMapRootIndex); 1754 __ CompareRoot(rax, Heap::kFixedArrayMapRootIndex);
1787 __ j(not_equal, &runtime); 1755 __ j(not_equal, &runtime);
1788 // Check that the last match info has space for the capture registers and the 1756 // Check that the last match info has space for the capture registers and the
1789 // additional information. Ensure no overflow in add. 1757 // additional information. Ensure no overflow in add.
1790 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); 1758 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset);
1791 __ SmiToInteger32(rax, FieldOperand(rbx, FixedArray::kLengthOffset)); 1759 __ SmiToInteger32(rax, FieldOperand(rbx, FixedArray::kLengthOffset));
1792 __ subl(rax, Immediate(RegExpImpl::kLastMatchOverhead)); 1760 __ subl(rax, Immediate(RegExpImpl::kLastMatchOverhead));
1793 __ cmpl(rdx, rax); 1761 __ cmpl(rdx, rax);
1794 __ j(greater, &runtime); 1762 __ j(greater, &runtime);
1795 1763
1796 // rbx: last_match_info backing store (FixedArray) 1764 // rbx: last_match_info backing store (FixedArray)
1797 // rdx: number of capture registers 1765 // rdx: number of capture registers
1798 // Store the capture count. 1766 // Store the capture count.
1799 __ Integer32ToSmi(kScratchRegister, rdx); 1767 __ Integer32ToSmi(kScratchRegister, rdx);
1800 __ movq(FieldOperand(rbx, RegExpImpl::kLastCaptureCountOffset), 1768 __ movp(FieldOperand(rbx, RegExpImpl::kLastCaptureCountOffset),
1801 kScratchRegister); 1769 kScratchRegister);
1802 // Store last subject and last input. 1770 // Store last subject and last input.
1803 __ movq(rax, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX)); 1771 __ movp(rax, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX));
1804 __ movq(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax); 1772 __ movp(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax);
1805 __ movq(rcx, rax); 1773 __ movp(rcx, rax);
1806 __ RecordWriteField(rbx, 1774 __ RecordWriteField(rbx,
1807 RegExpImpl::kLastSubjectOffset, 1775 RegExpImpl::kLastSubjectOffset,
1808 rax, 1776 rax,
1809 rdi, 1777 rdi,
1810 kDontSaveFPRegs); 1778 kDontSaveFPRegs);
1811 __ movq(rax, rcx); 1779 __ movp(rax, rcx);
1812 __ movq(FieldOperand(rbx, RegExpImpl::kLastInputOffset), rax); 1780 __ movp(FieldOperand(rbx, RegExpImpl::kLastInputOffset), rax);
1813 __ RecordWriteField(rbx, 1781 __ RecordWriteField(rbx,
1814 RegExpImpl::kLastInputOffset, 1782 RegExpImpl::kLastInputOffset,
1815 rax, 1783 rax,
1816 rdi, 1784 rdi,
1817 kDontSaveFPRegs); 1785 kDontSaveFPRegs);
1818 1786
1819 // Get the static offsets vector filled by the native regexp code. 1787 // Get the static offsets vector filled by the native regexp code.
1820 __ LoadAddress(rcx, 1788 __ LoadAddress(rcx,
1821 ExternalReference::address_of_static_offsets_vector(isolate)); 1789 ExternalReference::address_of_static_offsets_vector(isolate));
1822 1790
1823 // rbx: last_match_info backing store (FixedArray) 1791 // rbx: last_match_info backing store (FixedArray)
1824 // rcx: offsets vector 1792 // rcx: offsets vector
1825 // rdx: number of capture registers 1793 // rdx: number of capture registers
1826 Label next_capture, done; 1794 Label next_capture, done;
1827 // Capture register counter starts from number of capture registers and 1795 // Capture register counter starts from number of capture registers and
1828 // counts down until wraping after zero. 1796 // counts down until wraping after zero.
1829 __ bind(&next_capture); 1797 __ bind(&next_capture);
1830 __ subq(rdx, Immediate(1)); 1798 __ subq(rdx, Immediate(1));
1831 __ j(negative, &done, Label::kNear); 1799 __ j(negative, &done, Label::kNear);
1832 // Read the value from the static offsets vector buffer and make it a smi. 1800 // Read the value from the static offsets vector buffer and make it a smi.
1833 __ movl(rdi, Operand(rcx, rdx, times_int_size, 0)); 1801 __ movl(rdi, Operand(rcx, rdx, times_int_size, 0));
1834 __ Integer32ToSmi(rdi, rdi); 1802 __ Integer32ToSmi(rdi, rdi);
1835 // Store the smi value in the last match info. 1803 // Store the smi value in the last match info.
1836 __ movq(FieldOperand(rbx, 1804 __ movp(FieldOperand(rbx,
1837 rdx, 1805 rdx,
1838 times_pointer_size, 1806 times_pointer_size,
1839 RegExpImpl::kFirstCaptureOffset), 1807 RegExpImpl::kFirstCaptureOffset),
1840 rdi); 1808 rdi);
1841 __ jmp(&next_capture); 1809 __ jmp(&next_capture);
1842 __ bind(&done); 1810 __ bind(&done);
1843 1811
1844 // Return last match info. 1812 // Return last match info.
1845 __ movq(rax, r15); 1813 __ movp(rax, r15);
1846 __ ret(REG_EXP_EXEC_ARGUMENT_COUNT * kPointerSize); 1814 __ ret(REG_EXP_EXEC_ARGUMENT_COUNT * kPointerSize);
1847 1815
1848 __ bind(&exception); 1816 __ bind(&exception);
1849 // Result must now be exception. If there is no pending exception already a 1817 // Result must now be exception. If there is no pending exception already a
1850 // stack overflow (on the backtrack stack) was detected in RegExp code but 1818 // stack overflow (on the backtrack stack) was detected in RegExp code but
1851 // haven't created the exception yet. Handle that in the runtime system. 1819 // haven't created the exception yet. Handle that in the runtime system.
1852 // TODO(592): Rerunning the RegExp to get the stack overflow exception. 1820 // TODO(592): Rerunning the RegExp to get the stack overflow exception.
1853 ExternalReference pending_exception_address( 1821 ExternalReference pending_exception_address(
1854 Isolate::kPendingExceptionAddress, isolate); 1822 Isolate::kPendingExceptionAddress, isolate);
1855 Operand pending_exception_operand = 1823 Operand pending_exception_operand =
1856 masm->ExternalOperand(pending_exception_address, rbx); 1824 masm->ExternalOperand(pending_exception_address, rbx);
1857 __ movq(rax, pending_exception_operand); 1825 __ movp(rax, pending_exception_operand);
1858 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); 1826 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
1859 __ cmpq(rax, rdx); 1827 __ cmpq(rax, rdx);
1860 __ j(equal, &runtime); 1828 __ j(equal, &runtime);
1861 __ movq(pending_exception_operand, rdx); 1829 __ movp(pending_exception_operand, rdx);
1862 1830
1863 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); 1831 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex);
1864 Label termination_exception; 1832 Label termination_exception;
1865 __ j(equal, &termination_exception, Label::kNear); 1833 __ j(equal, &termination_exception, Label::kNear);
1866 __ Throw(rax); 1834 __ Throw(rax);
1867 1835
1868 __ bind(&termination_exception); 1836 __ bind(&termination_exception);
1869 __ ThrowUncatchable(rax); 1837 __ ThrowUncatchable(rax);
1870 1838
1871 // Do the runtime call to execute the regexp. 1839 // Do the runtime call to execute the regexp.
1872 __ bind(&runtime); 1840 __ bind(&runtime);
1873 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); 1841 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
1874 1842
1875 // Deferred code for string handling. 1843 // Deferred code for string handling.
1876 // (7) Not a long external string? If yes, go to (10). 1844 // (7) Not a long external string? If yes, go to (10).
1877 __ bind(&not_seq_nor_cons); 1845 __ bind(&not_seq_nor_cons);
1878 // Compare flags are still set from (3). 1846 // Compare flags are still set from (3).
1879 __ j(greater, &not_long_external, Label::kNear); // Go to (10). 1847 __ j(greater, &not_long_external, Label::kNear); // Go to (10).
1880 1848
1881 // (8) External string. Short external strings have been ruled out. 1849 // (8) External string. Short external strings have been ruled out.
1882 __ bind(&external_string); 1850 __ bind(&external_string);
1883 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); 1851 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
1884 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 1852 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
1885 if (FLAG_debug_code) { 1853 if (FLAG_debug_code) {
1886 // Assert that we do not have a cons or slice (indirect strings) here. 1854 // Assert that we do not have a cons or slice (indirect strings) here.
1887 // Sequential strings have already been ruled out. 1855 // Sequential strings have already been ruled out.
1888 __ testb(rbx, Immediate(kIsIndirectStringMask)); 1856 __ testb(rbx, Immediate(kIsIndirectStringMask));
1889 __ Assert(zero, kExternalStringExpectedButNotFound); 1857 __ Assert(zero, kExternalStringExpectedButNotFound);
1890 } 1858 }
1891 __ movq(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); 1859 __ movp(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset));
1892 // Move the pointer so that offset-wise, it looks like a sequential string. 1860 // Move the pointer so that offset-wise, it looks like a sequential string.
1893 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 1861 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
1894 __ subq(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 1862 __ subq(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
1895 STATIC_ASSERT(kTwoByteStringTag == 0); 1863 STATIC_ASSERT(kTwoByteStringTag == 0);
1896 // (8a) Is the external string one byte? If yes, go to (6). 1864 // (8a) Is the external string one byte? If yes, go to (6).
1897 __ testb(rbx, Immediate(kStringEncodingMask)); 1865 __ testb(rbx, Immediate(kStringEncodingMask));
1898 __ j(not_zero, &seq_one_byte_string); // Goto (6). 1866 __ j(not_zero, &seq_one_byte_string); // Goto (6).
1899 1867
1900 // rdi: subject string (flat two-byte) 1868 // rdi: subject string (flat two-byte)
1901 // rax: RegExp data (FixedArray) 1869 // rax: RegExp data (FixedArray)
1902 // (9) Two byte sequential. Load regexp code for one byte. Go to (E). 1870 // (9) Two byte sequential. Load regexp code for one byte. Go to (E).
1903 __ bind(&seq_two_byte_string); 1871 __ bind(&seq_two_byte_string);
1904 __ movq(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); 1872 __ movp(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset));
1905 __ Set(rcx, 0); // Type is two byte. 1873 __ Set(rcx, 0); // Type is two byte.
1906 __ jmp(&check_code); // Go to (E). 1874 __ jmp(&check_code); // Go to (E).
1907 1875
1908 // (10) Not a string or a short external string? If yes, bail out to runtime. 1876 // (10) Not a string or a short external string? If yes, bail out to runtime.
1909 __ bind(&not_long_external); 1877 __ bind(&not_long_external);
1910 // Catch non-string subject or short external string. 1878 // Catch non-string subject or short external string.
1911 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); 1879 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
1912 __ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask)); 1880 __ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask));
1913 __ j(not_zero, &runtime); 1881 __ j(not_zero, &runtime);
1914 1882
1915 // (11) Sliced string. Replace subject with parent. Go to (5a). 1883 // (11) Sliced string. Replace subject with parent. Go to (5a).
1916 // Load offset into r14 and replace subject string with parent. 1884 // Load offset into r14 and replace subject string with parent.
1917 __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset)); 1885 __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset));
1918 __ movq(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); 1886 __ movp(rdi, FieldOperand(rdi, SlicedString::kParentOffset));
1919 __ jmp(&check_underlying); 1887 __ jmp(&check_underlying);
1920 #endif // V8_INTERPRETED_REGEXP 1888 #endif // V8_INTERPRETED_REGEXP
1921 } 1889 }
1922 1890
1923 1891
1924 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { 1892 void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
1925 const int kMaxInlineLength = 100; 1893 const int kMaxInlineLength = 100;
1926 Label slowcase; 1894 Label slowcase;
1927 Label done; 1895 Label done;
1928 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER); 1896 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER);
1929 __ movq(r8, args.GetArgumentOperand(0)); 1897 __ movp(r8, args.GetArgumentOperand(0));
1930 __ JumpIfNotSmi(r8, &slowcase); 1898 __ JumpIfNotSmi(r8, &slowcase);
1931 __ SmiToInteger32(rbx, r8); 1899 __ SmiToInteger32(rbx, r8);
1932 __ cmpl(rbx, Immediate(kMaxInlineLength)); 1900 __ cmpl(rbx, Immediate(kMaxInlineLength));
1933 __ j(above, &slowcase); 1901 __ j(above, &slowcase);
1934 // Smi-tagging is equivalent to multiplying by 2. 1902 // Smi-tagging is equivalent to multiplying by 2.
1935 STATIC_ASSERT(kSmiTag == 0); 1903 STATIC_ASSERT(kSmiTag == 0);
1936 STATIC_ASSERT(kSmiTagSize == 1); 1904 STATIC_ASSERT(kSmiTagSize == 1);
1937 // Allocate RegExpResult followed by FixedArray with size in rbx. 1905 // Allocate RegExpResult followed by FixedArray with size in rbx.
1938 // JSArray: [Map][empty properties][Elements][Length-smi][index][input] 1906 // JSArray: [Map][empty properties][Elements][Length-smi][index][input]
1939 // Elements: [Map][Length][..elements..] 1907 // Elements: [Map][Length][..elements..]
1940 __ Allocate(JSRegExpResult::kSize + FixedArray::kHeaderSize, 1908 __ Allocate(JSRegExpResult::kSize + FixedArray::kHeaderSize,
1941 times_pointer_size, 1909 times_pointer_size,
1942 rbx, // In: Number of elements. 1910 rbx, // In: Number of elements.
1943 rax, // Out: Start of allocation (tagged). 1911 rax, // Out: Start of allocation (tagged).
1944 rcx, // Out: End of allocation. 1912 rcx, // Out: End of allocation.
1945 rdx, // Scratch register 1913 rdx, // Scratch register
1946 &slowcase, 1914 &slowcase,
1947 TAG_OBJECT); 1915 TAG_OBJECT);
1948 // rax: Start of allocated area, object-tagged. 1916 // rax: Start of allocated area, object-tagged.
1949 // rbx: Number of array elements as int32. 1917 // rbx: Number of array elements as int32.
1950 // r8: Number of array elements as smi. 1918 // r8: Number of array elements as smi.
1951 1919
1952 // Set JSArray map to global.regexp_result_map(). 1920 // Set JSArray map to global.regexp_result_map().
1953 __ movq(rdx, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX)); 1921 __ movp(rdx, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX));
1954 __ movq(rdx, FieldOperand(rdx, GlobalObject::kNativeContextOffset)); 1922 __ movp(rdx, FieldOperand(rdx, GlobalObject::kNativeContextOffset));
1955 __ movq(rdx, ContextOperand(rdx, Context::REGEXP_RESULT_MAP_INDEX)); 1923 __ movp(rdx, ContextOperand(rdx, Context::REGEXP_RESULT_MAP_INDEX));
1956 __ movq(FieldOperand(rax, HeapObject::kMapOffset), rdx); 1924 __ movp(FieldOperand(rax, HeapObject::kMapOffset), rdx);
1957 1925
1958 // Set empty properties FixedArray. 1926 // Set empty properties FixedArray.
1959 __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex); 1927 __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex);
1960 __ movq(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister); 1928 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister);
1961 1929
1962 // Set elements to point to FixedArray allocated right after the JSArray. 1930 // Set elements to point to FixedArray allocated right after the JSArray.
1963 __ lea(rcx, Operand(rax, JSRegExpResult::kSize)); 1931 __ lea(rcx, Operand(rax, JSRegExpResult::kSize));
1964 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rcx); 1932 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rcx);
1965 1933
1966 // Set input, index and length fields from arguments. 1934 // Set input, index and length fields from arguments.
1967 __ movq(r8, args.GetArgumentOperand(2)); 1935 __ movp(r8, args.GetArgumentOperand(2));
1968 __ movq(FieldOperand(rax, JSRegExpResult::kInputOffset), r8); 1936 __ movp(FieldOperand(rax, JSRegExpResult::kInputOffset), r8);
1969 __ movq(r8, args.GetArgumentOperand(1)); 1937 __ movp(r8, args.GetArgumentOperand(1));
1970 __ movq(FieldOperand(rax, JSRegExpResult::kIndexOffset), r8); 1938 __ movp(FieldOperand(rax, JSRegExpResult::kIndexOffset), r8);
1971 __ movq(r8, args.GetArgumentOperand(0)); 1939 __ movp(r8, args.GetArgumentOperand(0));
1972 __ movq(FieldOperand(rax, JSArray::kLengthOffset), r8); 1940 __ movp(FieldOperand(rax, JSArray::kLengthOffset), r8);
1973 1941
1974 // Fill out the elements FixedArray. 1942 // Fill out the elements FixedArray.
1975 // rax: JSArray. 1943 // rax: JSArray.
1976 // rcx: FixedArray. 1944 // rcx: FixedArray.
1977 // rbx: Number of elements in array as int32. 1945 // rbx: Number of elements in array as int32.
1978 1946
1979 // Set map. 1947 // Set map.
1980 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); 1948 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex);
1981 __ movq(FieldOperand(rcx, HeapObject::kMapOffset), kScratchRegister); 1949 __ movp(FieldOperand(rcx, HeapObject::kMapOffset), kScratchRegister);
1982 // Set length. 1950 // Set length.
1983 __ Integer32ToSmi(rdx, rbx); 1951 __ Integer32ToSmi(rdx, rbx);
1984 __ movq(FieldOperand(rcx, FixedArray::kLengthOffset), rdx); 1952 __ movp(FieldOperand(rcx, FixedArray::kLengthOffset), rdx);
1985 // Fill contents of fixed-array with undefined. 1953 // Fill contents of fixed-array with undefined.
1986 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); 1954 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
1987 __ lea(rcx, FieldOperand(rcx, FixedArray::kHeaderSize)); 1955 __ lea(rcx, FieldOperand(rcx, FixedArray::kHeaderSize));
1988 // Fill fixed array elements with undefined. 1956 // Fill fixed array elements with undefined.
1989 // rax: JSArray. 1957 // rax: JSArray.
1990 // rbx: Number of elements in array that remains to be filled, as int32. 1958 // rbx: Number of elements in array that remains to be filled, as int32.
1991 // rcx: Start of elements in FixedArray. 1959 // rcx: Start of elements in FixedArray.
1992 // rdx: undefined. 1960 // rdx: undefined.
1993 Label loop; 1961 Label loop;
1994 __ testl(rbx, rbx); 1962 __ testl(rbx, rbx);
1995 __ bind(&loop); 1963 __ bind(&loop);
1996 __ j(less_equal, &done); // Jump if rcx is negative or zero. 1964 __ j(less_equal, &done); // Jump if rcx is negative or zero.
1997 __ subl(rbx, Immediate(1)); 1965 __ subl(rbx, Immediate(1));
1998 __ movq(Operand(rcx, rbx, times_pointer_size, 0), rdx); 1966 __ movp(Operand(rcx, rbx, times_pointer_size, 0), rdx);
1999 __ jmp(&loop); 1967 __ jmp(&loop);
2000 1968
2001 __ bind(&done); 1969 __ bind(&done);
2002 __ ret(3 * kPointerSize); 1970 __ ret(3 * kPointerSize);
2003 1971
2004 __ bind(&slowcase); 1972 __ bind(&slowcase);
2005 __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1); 1973 __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1);
2006 } 1974 }
2007 1975
2008 1976
(...skipping 21 matching lines...) Expand all
2030 // hydrogen doesn't care, the stub doesn't have to care either. 1998 // hydrogen doesn't care, the stub doesn't have to care either.
2031 __ bind(&ok); 1999 __ bind(&ok);
2032 } 2000 }
2033 2001
2034 2002
2035 static void BranchIfNotInternalizedString(MacroAssembler* masm, 2003 static void BranchIfNotInternalizedString(MacroAssembler* masm,
2036 Label* label, 2004 Label* label,
2037 Register object, 2005 Register object,
2038 Register scratch) { 2006 Register scratch) {
2039 __ JumpIfSmi(object, label); 2007 __ JumpIfSmi(object, label);
2040 __ movq(scratch, FieldOperand(object, HeapObject::kMapOffset)); 2008 __ movp(scratch, FieldOperand(object, HeapObject::kMapOffset));
2041 __ movzxbq(scratch, 2009 __ movzxbq(scratch,
2042 FieldOperand(scratch, Map::kInstanceTypeOffset)); 2010 FieldOperand(scratch, Map::kInstanceTypeOffset));
2043 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 2011 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
2044 __ testb(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); 2012 __ testb(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
2045 __ j(not_zero, label); 2013 __ j(not_zero, label);
2046 } 2014 }
2047 2015
2048 2016
2049 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { 2017 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
2050 Label check_unequal_objects, done; 2018 Label check_unequal_objects, done;
2051 Condition cc = GetCondition(); 2019 Condition cc = GetCondition();
2052 Factory* factory = masm->isolate()->factory(); 2020 Factory* factory = masm->isolate()->factory();
2053 2021
2054 Label miss; 2022 Label miss;
2055 CheckInputType(masm, rdx, left_, &miss); 2023 CheckInputType(masm, rdx, left_, &miss);
2056 CheckInputType(masm, rax, right_, &miss); 2024 CheckInputType(masm, rax, right_, &miss);
2057 2025
2058 // Compare two smis. 2026 // Compare two smis.
2059 Label non_smi, smi_done; 2027 Label non_smi, smi_done;
2060 __ JumpIfNotBothSmi(rax, rdx, &non_smi); 2028 __ JumpIfNotBothSmi(rax, rdx, &non_smi);
2061 __ subq(rdx, rax); 2029 __ subq(rdx, rax);
2062 __ j(no_overflow, &smi_done); 2030 __ j(no_overflow, &smi_done);
2063 __ not_(rdx); // Correct sign in case of overflow. rdx cannot be 0 here. 2031 __ not_(rdx); // Correct sign in case of overflow. rdx cannot be 0 here.
2064 __ bind(&smi_done); 2032 __ bind(&smi_done);
2065 __ movq(rax, rdx); 2033 __ movp(rax, rdx);
2066 __ ret(0); 2034 __ ret(0);
2067 __ bind(&non_smi); 2035 __ bind(&non_smi);
2068 2036
2069 // The compare stub returns a positive, negative, or zero 64-bit integer 2037 // The compare stub returns a positive, negative, or zero 64-bit integer
2070 // value in rax, corresponding to result of comparing the two inputs. 2038 // value in rax, corresponding to result of comparing the two inputs.
2071 // NOTICE! This code is only reached after a smi-fast-case check, so 2039 // NOTICE! This code is only reached after a smi-fast-case check, so
2072 // it is certain that at least one operand isn't a smi. 2040 // it is certain that at least one operand isn't a smi.
2073 2041
2074 // Two identical objects are equal unless they are both NaN or undefined. 2042 // Two identical objects are equal unless they are both NaN or undefined.
2075 { 2043 {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
2134 { 2102 {
2135 Label not_smis; 2103 Label not_smis;
2136 __ SelectNonSmi(rbx, rax, rdx, &not_smis); 2104 __ SelectNonSmi(rbx, rax, rdx, &not_smis);
2137 2105
2138 // Check if the non-smi operand is a heap number. 2106 // Check if the non-smi operand is a heap number.
2139 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), 2107 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
2140 factory->heap_number_map()); 2108 factory->heap_number_map());
2141 // If heap number, handle it in the slow case. 2109 // If heap number, handle it in the slow case.
2142 __ j(equal, &slow); 2110 __ j(equal, &slow);
2143 // Return non-equal. ebx (the lower half of rbx) is not zero. 2111 // Return non-equal. ebx (the lower half of rbx) is not zero.
2144 __ movq(rax, rbx); 2112 __ movp(rax, rbx);
2145 __ ret(0); 2113 __ ret(0);
2146 2114
2147 __ bind(&not_smis); 2115 __ bind(&not_smis);
2148 } 2116 }
2149 2117
2150 // If either operand is a JSObject or an oddball value, then they are not 2118 // If either operand is a JSObject or an oddball value, then they are not
2151 // equal since their pointers are different 2119 // equal since their pointers are different
2152 // There is no test for undetectability in strict equality. 2120 // There is no test for undetectability in strict equality.
2153 2121
2154 // If the first object is a JS object, we have done pointer comparison. 2122 // If the first object is a JS object, we have done pointer comparison.
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
2312 // Cache the called function in a global property cell. Cache states 2280 // Cache the called function in a global property cell. Cache states
2313 // are uninitialized, monomorphic (indicated by a JSFunction), and 2281 // are uninitialized, monomorphic (indicated by a JSFunction), and
2314 // megamorphic. 2282 // megamorphic.
2315 // rax : number of arguments to the construct function 2283 // rax : number of arguments to the construct function
2316 // rbx : cache cell for call target 2284 // rbx : cache cell for call target
2317 // rdi : the function to call 2285 // rdi : the function to call
2318 Isolate* isolate = masm->isolate(); 2286 Isolate* isolate = masm->isolate();
2319 Label initialize, done, miss, megamorphic, not_array_function; 2287 Label initialize, done, miss, megamorphic, not_array_function;
2320 2288
2321 // Load the cache state into rcx. 2289 // Load the cache state into rcx.
2322 __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset)); 2290 __ movp(rcx, FieldOperand(rbx, Cell::kValueOffset));
2323 2291
2324 // A monomorphic cache hit or an already megamorphic state: invoke the 2292 // A monomorphic cache hit or an already megamorphic state: invoke the
2325 // function without changing the state. 2293 // function without changing the state.
2326 __ cmpq(rcx, rdi); 2294 __ cmpq(rcx, rdi);
2327 __ j(equal, &done); 2295 __ j(equal, &done);
2328 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate)); 2296 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate));
2329 __ j(equal, &done); 2297 __ j(equal, &done);
2330 2298
2331 // If we came here, we need to see if we are the array function. 2299 // If we came here, we need to see if we are the array function.
2332 // If we didn't have a matching function, and we didn't find the megamorph 2300 // If we didn't have a matching function, and we didn't find the megamorph
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
2379 __ CallStub(&create_stub); 2347 __ CallStub(&create_stub);
2380 2348
2381 __ pop(rbx); 2349 __ pop(rbx);
2382 __ pop(rdi); 2350 __ pop(rdi);
2383 __ pop(rax); 2351 __ pop(rax);
2384 __ SmiToInteger32(rax, rax); 2352 __ SmiToInteger32(rax, rax);
2385 } 2353 }
2386 __ jmp(&done); 2354 __ jmp(&done);
2387 2355
2388 __ bind(&not_array_function); 2356 __ bind(&not_array_function);
2389 __ movq(FieldOperand(rbx, Cell::kValueOffset), rdi); 2357 __ movp(FieldOperand(rbx, Cell::kValueOffset), rdi);
2390 // No need for a write barrier here - cells are rescanned. 2358 // No need for a write barrier here - cells are rescanned.
2391 2359
2392 __ bind(&done); 2360 __ bind(&done);
2393 } 2361 }
2394 2362
2395 2363
2396 void CallFunctionStub::Generate(MacroAssembler* masm) { 2364 void CallFunctionStub::Generate(MacroAssembler* masm) {
2397 // rbx : cache cell for call target 2365 // rbx : cache cell for call target
2398 // rdi : the function to call 2366 // rdi : the function to call
2399 Isolate* isolate = masm->isolate(); 2367 Isolate* isolate = masm->isolate();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2436 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); 2404 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY);
2437 { 2405 {
2438 Handle<Code> adaptor = 2406 Handle<Code> adaptor =
2439 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); 2407 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
2440 __ jmp(adaptor, RelocInfo::CODE_TARGET); 2408 __ jmp(adaptor, RelocInfo::CODE_TARGET);
2441 } 2409 }
2442 2410
2443 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead 2411 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
2444 // of the original receiver from the call site). 2412 // of the original receiver from the call site).
2445 __ bind(&non_function); 2413 __ bind(&non_function);
2446 __ movq(args.GetReceiverOperand(), rdi); 2414 __ movp(args.GetReceiverOperand(), rdi);
2447 __ Set(rax, argc_); 2415 __ Set(rax, argc_);
2448 __ Set(rbx, 0); 2416 __ Set(rbx, 0);
2449 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); 2417 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
2450 Handle<Code> adaptor = 2418 Handle<Code> adaptor =
2451 isolate->builtins()->ArgumentsAdaptorTrampoline(); 2419 isolate->builtins()->ArgumentsAdaptorTrampoline();
2452 __ Jump(adaptor, RelocInfo::CODE_TARGET); 2420 __ Jump(adaptor, RelocInfo::CODE_TARGET);
2453 } 2421 }
2454 2422
2455 2423
2456 void CallConstructStub::Generate(MacroAssembler* masm) { 2424 void CallConstructStub::Generate(MacroAssembler* masm) {
2457 // rax : number of arguments 2425 // rax : number of arguments
2458 // rbx : cache cell for call target 2426 // rbx : cache cell for call target
2459 // rdi : constructor function 2427 // rdi : constructor function
2460 Label slow, non_function_call; 2428 Label slow, non_function_call;
2461 2429
2462 // Check that function is not a smi. 2430 // Check that function is not a smi.
2463 __ JumpIfSmi(rdi, &non_function_call); 2431 __ JumpIfSmi(rdi, &non_function_call);
2464 // Check that function is a JSFunction. 2432 // Check that function is a JSFunction.
2465 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); 2433 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
2466 __ j(not_equal, &slow); 2434 __ j(not_equal, &slow);
2467 2435
2468 if (RecordCallTarget()) { 2436 if (RecordCallTarget()) {
2469 GenerateRecordCallTarget(masm); 2437 GenerateRecordCallTarget(masm);
2470 } 2438 }
2471 2439
2472 // Jump to the function-specific construct stub. 2440 // Jump to the function-specific construct stub.
2473 Register jmp_reg = rcx; 2441 Register jmp_reg = rcx;
2474 __ movq(jmp_reg, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); 2442 __ movp(jmp_reg, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
2475 __ movq(jmp_reg, FieldOperand(jmp_reg, 2443 __ movp(jmp_reg, FieldOperand(jmp_reg,
2476 SharedFunctionInfo::kConstructStubOffset)); 2444 SharedFunctionInfo::kConstructStubOffset));
2477 __ lea(jmp_reg, FieldOperand(jmp_reg, Code::kHeaderSize)); 2445 __ lea(jmp_reg, FieldOperand(jmp_reg, Code::kHeaderSize));
2478 __ jmp(jmp_reg); 2446 __ jmp(jmp_reg);
2479 2447
2480 // rdi: called object 2448 // rdi: called object
2481 // rax: number of arguments 2449 // rax: number of arguments
2482 // rcx: object map 2450 // rcx: object map
2483 Label do_call; 2451 Label do_call;
2484 __ bind(&slow); 2452 __ bind(&slow);
2485 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); 2453 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2523 stub.GetCode(isolate); 2491 stub.GetCode(isolate);
2524 CEntryStub save_doubles(1, kSaveFPRegs); 2492 CEntryStub save_doubles(1, kSaveFPRegs);
2525 save_doubles.GetCode(isolate); 2493 save_doubles.GetCode(isolate);
2526 } 2494 }
2527 2495
2528 2496
2529 static void JumpIfOOM(MacroAssembler* masm, 2497 static void JumpIfOOM(MacroAssembler* masm,
2530 Register value, 2498 Register value,
2531 Register scratch, 2499 Register scratch,
2532 Label* oom_label) { 2500 Label* oom_label) {
2533 __ movq(scratch, value); 2501 __ movp(scratch, value);
2534 STATIC_ASSERT(Failure::OUT_OF_MEMORY_EXCEPTION == 3); 2502 STATIC_ASSERT(Failure::OUT_OF_MEMORY_EXCEPTION == 3);
2535 STATIC_ASSERT(kFailureTag == 3); 2503 STATIC_ASSERT(kFailureTag == 3);
2536 __ and_(scratch, Immediate(0xf)); 2504 __ and_(scratch, Immediate(0xf));
2537 __ cmpq(scratch, Immediate(0xf)); 2505 __ cmpq(scratch, Immediate(0xf));
2538 __ j(equal, oom_label); 2506 __ j(equal, oom_label);
2539 } 2507 }
2540 2508
2541 2509
2542 void CEntryStub::GenerateCore(MacroAssembler* masm, 2510 void CEntryStub::GenerateCore(MacroAssembler* masm,
2543 Label* throw_normal_exception, 2511 Label* throw_normal_exception,
(...skipping 18 matching lines...) Expand all
2562 if (FLAG_debug_code) { 2530 if (FLAG_debug_code) {
2563 __ CheckStackAlignment(); 2531 __ CheckStackAlignment();
2564 } 2532 }
2565 2533
2566 if (do_gc) { 2534 if (do_gc) {
2567 // Pass failure code returned from last attempt as first argument to 2535 // Pass failure code returned from last attempt as first argument to
2568 // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the 2536 // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the
2569 // stack is known to be aligned. This function takes one argument which is 2537 // stack is known to be aligned. This function takes one argument which is
2570 // passed in register. 2538 // passed in register.
2571 __ Move(arg_reg_2, ExternalReference::isolate_address(masm->isolate())); 2539 __ Move(arg_reg_2, ExternalReference::isolate_address(masm->isolate()));
2572 __ movq(arg_reg_1, rax); 2540 __ movp(arg_reg_1, rax);
2573 __ Move(kScratchRegister, 2541 __ Move(kScratchRegister,
2574 ExternalReference::perform_gc_function(masm->isolate())); 2542 ExternalReference::perform_gc_function(masm->isolate()));
2575 __ call(kScratchRegister); 2543 __ call(kScratchRegister);
2576 } 2544 }
2577 2545
2578 ExternalReference scope_depth = 2546 ExternalReference scope_depth =
2579 ExternalReference::heap_always_allocate_scope_depth(masm->isolate()); 2547 ExternalReference::heap_always_allocate_scope_depth(masm->isolate());
2580 if (always_allocate_scope) { 2548 if (always_allocate_scope) {
2581 Operand scope_depth_operand = masm->ExternalOperand(scope_depth); 2549 Operand scope_depth_operand = masm->ExternalOperand(scope_depth);
2582 __ incl(scope_depth_operand); 2550 __ incl(scope_depth_operand);
2583 } 2551 }
2584 2552
2585 // Call C function. 2553 // Call C function.
2586 #ifdef _WIN64 2554 #ifdef _WIN64
2587 // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9. 2555 // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9.
2588 // Pass argv and argc as two parameters. The arguments object will 2556 // Pass argv and argc as two parameters. The arguments object will
2589 // be created by stubs declared by DECLARE_RUNTIME_FUNCTION(). 2557 // be created by stubs declared by DECLARE_RUNTIME_FUNCTION().
2590 if (result_size_ < 2) { 2558 if (result_size_ < 2) {
2591 // Pass a pointer to the Arguments object as the first argument. 2559 // Pass a pointer to the Arguments object as the first argument.
2592 // Return result in single register (rax). 2560 // Return result in single register (rax).
2593 __ movq(rcx, r14); // argc. 2561 __ movp(rcx, r14); // argc.
2594 __ movq(rdx, r15); // argv. 2562 __ movp(rdx, r15); // argv.
2595 __ Move(r8, ExternalReference::isolate_address(masm->isolate())); 2563 __ Move(r8, ExternalReference::isolate_address(masm->isolate()));
2596 } else { 2564 } else {
2597 ASSERT_EQ(2, result_size_); 2565 ASSERT_EQ(2, result_size_);
2598 // Pass a pointer to the result location as the first argument. 2566 // Pass a pointer to the result location as the first argument.
2599 __ lea(rcx, StackSpaceOperand(2)); 2567 __ lea(rcx, StackSpaceOperand(2));
2600 // Pass a pointer to the Arguments object as the second argument. 2568 // Pass a pointer to the Arguments object as the second argument.
2601 __ movq(rdx, r14); // argc. 2569 __ movp(rdx, r14); // argc.
2602 __ movq(r8, r15); // argv. 2570 __ movp(r8, r15); // argv.
2603 __ Move(r9, ExternalReference::isolate_address(masm->isolate())); 2571 __ Move(r9, ExternalReference::isolate_address(masm->isolate()));
2604 } 2572 }
2605 2573
2606 #else // _WIN64 2574 #else // _WIN64
2607 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9. 2575 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9.
2608 __ movq(rdi, r14); // argc. 2576 __ movp(rdi, r14); // argc.
2609 __ movq(rsi, r15); // argv. 2577 __ movp(rsi, r15); // argv.
2610 __ Move(rdx, ExternalReference::isolate_address(masm->isolate())); 2578 __ Move(rdx, ExternalReference::isolate_address(masm->isolate()));
2611 #endif 2579 #endif
2612 __ call(rbx); 2580 __ call(rbx);
2613 // Result is in rax - do not destroy this register! 2581 // Result is in rax - do not destroy this register!
2614 2582
2615 if (always_allocate_scope) { 2583 if (always_allocate_scope) {
2616 Operand scope_depth_operand = masm->ExternalOperand(scope_depth); 2584 Operand scope_depth_operand = masm->ExternalOperand(scope_depth);
2617 __ decl(scope_depth_operand); 2585 __ decl(scope_depth_operand);
2618 } 2586 }
2619 2587
2620 // Check for failure result. 2588 // Check for failure result.
2621 Label failure_returned; 2589 Label failure_returned;
2622 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); 2590 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
2623 #ifdef _WIN64 2591 #ifdef _WIN64
2624 // If return value is on the stack, pop it to registers. 2592 // If return value is on the stack, pop it to registers.
2625 if (result_size_ > 1) { 2593 if (result_size_ > 1) {
2626 ASSERT_EQ(2, result_size_); 2594 ASSERT_EQ(2, result_size_);
2627 // Read result values stored on stack. Result is stored 2595 // Read result values stored on stack. Result is stored
2628 // above the four argument mirror slots and the two 2596 // above the four argument mirror slots and the two
2629 // Arguments object slots. 2597 // Arguments object slots.
2630 __ movq(rax, Operand(rsp, 6 * kPointerSize)); 2598 __ movq(rax, Operand(rsp, 6 * kRegisterSize));
2631 __ movq(rdx, Operand(rsp, 7 * kPointerSize)); 2599 __ movq(rdx, Operand(rsp, 7 * kRegisterSize));
2632 } 2600 }
2633 #endif 2601 #endif
2634 __ lea(rcx, Operand(rax, 1)); 2602 __ lea(rcx, Operand(rax, 1));
2635 // Lower 2 bits of rcx are 0 iff rax has failure tag. 2603 // Lower 2 bits of rcx are 0 iff rax has failure tag.
2636 __ testl(rcx, Immediate(kFailureTagMask)); 2604 __ testl(rcx, Immediate(kFailureTagMask));
2637 __ j(zero, &failure_returned); 2605 __ j(zero, &failure_returned);
2638 2606
2639 // Exit the JavaScript to C++ exit frame. 2607 // Exit the JavaScript to C++ exit frame.
2640 __ LeaveExitFrame(save_doubles_); 2608 __ LeaveExitFrame(save_doubles_);
2641 __ ret(0); 2609 __ ret(0);
2642 2610
2643 // Handling of failure. 2611 // Handling of failure.
2644 __ bind(&failure_returned); 2612 __ bind(&failure_returned);
2645 2613
2646 Label retry; 2614 Label retry;
2647 // If the returned exception is RETRY_AFTER_GC continue at retry label 2615 // If the returned exception is RETRY_AFTER_GC continue at retry label
2648 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); 2616 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
2649 __ testl(rax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); 2617 __ testl(rax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
2650 __ j(zero, &retry, Label::kNear); 2618 __ j(zero, &retry, Label::kNear);
2651 2619
2652 // Special handling of out of memory exceptions. 2620 // Special handling of out of memory exceptions.
2653 JumpIfOOM(masm, rax, kScratchRegister, throw_out_of_memory_exception); 2621 JumpIfOOM(masm, rax, kScratchRegister, throw_out_of_memory_exception);
2654 2622
2655 // Retrieve the pending exception. 2623 // Retrieve the pending exception.
2656 ExternalReference pending_exception_address( 2624 ExternalReference pending_exception_address(
2657 Isolate::kPendingExceptionAddress, masm->isolate()); 2625 Isolate::kPendingExceptionAddress, masm->isolate());
2658 Operand pending_exception_operand = 2626 Operand pending_exception_operand =
2659 masm->ExternalOperand(pending_exception_address); 2627 masm->ExternalOperand(pending_exception_address);
2660 __ movq(rax, pending_exception_operand); 2628 __ movp(rax, pending_exception_operand);
2661 2629
2662 // See if we just retrieved an OOM exception. 2630 // See if we just retrieved an OOM exception.
2663 JumpIfOOM(masm, rax, kScratchRegister, throw_out_of_memory_exception); 2631 JumpIfOOM(masm, rax, kScratchRegister, throw_out_of_memory_exception);
2664 2632
2665 // Clear the pending exception. 2633 // Clear the pending exception.
2666 pending_exception_operand = 2634 pending_exception_operand =
2667 masm->ExternalOperand(pending_exception_address); 2635 masm->ExternalOperand(pending_exception_address);
2668 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); 2636 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
2669 __ movq(pending_exception_operand, rdx); 2637 __ movp(pending_exception_operand, rdx);
2670 2638
2671 // Special handling of termination exceptions which are uncatchable 2639 // Special handling of termination exceptions which are uncatchable
2672 // by javascript code. 2640 // by javascript code.
2673 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); 2641 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex);
2674 __ j(equal, throw_termination_exception); 2642 __ j(equal, throw_termination_exception);
2675 2643
2676 // Handle normal exception. 2644 // Handle normal exception.
2677 __ jmp(throw_normal_exception); 2645 __ jmp(throw_normal_exception);
2678 2646
2679 // Retry. 2647 // Retry.
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
2774 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { 2742 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
2775 Label invoke, handler_entry, exit; 2743 Label invoke, handler_entry, exit;
2776 Label not_outermost_js, not_outermost_js_2; 2744 Label not_outermost_js, not_outermost_js_2;
2777 2745
2778 ProfileEntryHookStub::MaybeCallEntryHook(masm); 2746 ProfileEntryHookStub::MaybeCallEntryHook(masm);
2779 2747
2780 { // NOLINT. Scope block confuses linter. 2748 { // NOLINT. Scope block confuses linter.
2781 MacroAssembler::NoRootArrayScope uninitialized_root_register(masm); 2749 MacroAssembler::NoRootArrayScope uninitialized_root_register(masm);
2782 // Set up frame. 2750 // Set up frame.
2783 __ push(rbp); 2751 __ push(rbp);
2784 __ movq(rbp, rsp); 2752 __ movp(rbp, rsp);
2785 2753
2786 // Push the stack frame type marker twice. 2754 // Push the stack frame type marker twice.
2787 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; 2755 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
2788 // Scratch register is neither callee-save, nor an argument register on any 2756 // Scratch register is neither callee-save, nor an argument register on any
2789 // platform. It's free to use at this point. 2757 // platform. It's free to use at this point.
2790 // Cannot use smi-register for loading yet. 2758 // Cannot use smi-register for loading yet.
2791 __ Move(kScratchRegister, Smi::FromInt(marker), RelocInfo::NONE64); 2759 __ Move(kScratchRegister, Smi::FromInt(marker), RelocInfo::NONE64);
2792 __ push(kScratchRegister); // context slot 2760 __ push(kScratchRegister); // context slot
2793 __ push(kScratchRegister); // function slot 2761 __ push(kScratchRegister); // function slot
2794 // Save callee-saved registers (X64/Win64 calling conventions). 2762 // Save callee-saved registers (X64/Win64 calling conventions).
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2831 Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp); 2799 Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp);
2832 __ push(c_entry_fp_operand); 2800 __ push(c_entry_fp_operand);
2833 } 2801 }
2834 2802
2835 // If this is the outermost JS call, set js_entry_sp value. 2803 // If this is the outermost JS call, set js_entry_sp value.
2836 ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate); 2804 ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate);
2837 __ Load(rax, js_entry_sp); 2805 __ Load(rax, js_entry_sp);
2838 __ testq(rax, rax); 2806 __ testq(rax, rax);
2839 __ j(not_zero, &not_outermost_js); 2807 __ j(not_zero, &not_outermost_js);
2840 __ Push(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)); 2808 __ Push(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME));
2841 __ movq(rax, rbp); 2809 __ movp(rax, rbp);
2842 __ Store(js_entry_sp, rax); 2810 __ Store(js_entry_sp, rax);
2843 Label cont; 2811 Label cont;
2844 __ jmp(&cont); 2812 __ jmp(&cont);
2845 __ bind(&not_outermost_js); 2813 __ bind(&not_outermost_js);
2846 __ Push(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME)); 2814 __ Push(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME));
2847 __ bind(&cont); 2815 __ bind(&cont);
2848 2816
2849 // Jump to a faked try block that does the invoke, with a faked catch 2817 // Jump to a faked try block that does the invoke, with a faked catch
2850 // block that sets the pending exception. 2818 // block that sets the pending exception.
2851 __ jmp(&invoke); 2819 __ jmp(&invoke);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2889 2857
2890 // Unlink this frame from the handler chain. 2858 // Unlink this frame from the handler chain.
2891 __ PopTryHandler(); 2859 __ PopTryHandler();
2892 2860
2893 __ bind(&exit); 2861 __ bind(&exit);
2894 // Check if the current stack frame is marked as the outermost JS frame. 2862 // Check if the current stack frame is marked as the outermost JS frame.
2895 __ pop(rbx); 2863 __ pop(rbx);
2896 __ Cmp(rbx, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)); 2864 __ Cmp(rbx, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME));
2897 __ j(not_equal, &not_outermost_js_2); 2865 __ j(not_equal, &not_outermost_js_2);
2898 __ Move(kScratchRegister, js_entry_sp); 2866 __ Move(kScratchRegister, js_entry_sp);
2899 __ movq(Operand(kScratchRegister, 0), Immediate(0)); 2867 __ movp(Operand(kScratchRegister, 0), Immediate(0));
2900 __ bind(&not_outermost_js_2); 2868 __ bind(&not_outermost_js_2);
2901 2869
2902 // Restore the top frame descriptor from the stack. 2870 // Restore the top frame descriptor from the stack.
2903 { Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp); 2871 { Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp);
2904 __ pop(c_entry_fp_operand); 2872 __ pop(c_entry_fp_operand);
2905 } 2873 }
2906 2874
2907 // Restore callee-saved registers (X64 conventions). 2875 // Restore callee-saved registers (X64 conventions).
2908 #ifdef _WIN64 2876 #ifdef _WIN64
2909 // On Win64 XMM6-XMM15 are callee-save 2877 // On Win64 XMM6-XMM15 are callee-save
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2966 // before the offset of the hole value in the root array. 2934 // before the offset of the hole value in the root array.
2967 static const unsigned int kWordBeforeResultValue = 0x458B4906; 2935 static const unsigned int kWordBeforeResultValue = 0x458B4906;
2968 // Only the inline check flag is supported on X64. 2936 // Only the inline check flag is supported on X64.
2969 ASSERT(flags_ == kNoFlags || HasCallSiteInlineCheck()); 2937 ASSERT(flags_ == kNoFlags || HasCallSiteInlineCheck());
2970 int extra_argument_offset = HasCallSiteInlineCheck() ? 1 : 0; 2938 int extra_argument_offset = HasCallSiteInlineCheck() ? 1 : 0;
2971 2939
2972 // Get the object - go slow case if it's a smi. 2940 // Get the object - go slow case if it's a smi.
2973 Label slow; 2941 Label slow;
2974 StackArgumentsAccessor args(rsp, 2 + extra_argument_offset, 2942 StackArgumentsAccessor args(rsp, 2 + extra_argument_offset,
2975 ARGUMENTS_DONT_CONTAIN_RECEIVER); 2943 ARGUMENTS_DONT_CONTAIN_RECEIVER);
2976 __ movq(rax, args.GetArgumentOperand(0)); 2944 __ movp(rax, args.GetArgumentOperand(0));
2977 __ JumpIfSmi(rax, &slow); 2945 __ JumpIfSmi(rax, &slow);
2978 2946
2979 // Check that the left hand is a JS object. Leave its map in rax. 2947 // Check that the left hand is a JS object. Leave its map in rax.
2980 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rax); 2948 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rax);
2981 __ j(below, &slow); 2949 __ j(below, &slow);
2982 __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE); 2950 __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE);
2983 __ j(above, &slow); 2951 __ j(above, &slow);
2984 2952
2985 // Get the prototype of the function. 2953 // Get the prototype of the function.
2986 __ movq(rdx, args.GetArgumentOperand(1)); 2954 __ movp(rdx, args.GetArgumentOperand(1));
2987 // rdx is function, rax is map. 2955 // rdx is function, rax is map.
2988 2956
2989 // If there is a call site cache don't look in the global cache, but do the 2957 // If there is a call site cache don't look in the global cache, but do the
2990 // real lookup and update the call site cache. 2958 // real lookup and update the call site cache.
2991 if (!HasCallSiteInlineCheck()) { 2959 if (!HasCallSiteInlineCheck()) {
2992 // Look up the function and the map in the instanceof cache. 2960 // Look up the function and the map in the instanceof cache.
2993 Label miss; 2961 Label miss;
2994 __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); 2962 __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
2995 __ j(not_equal, &miss, Label::kNear); 2963 __ j(not_equal, &miss, Label::kNear);
2996 __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex); 2964 __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex);
(...skipping 14 matching lines...) Expand all
3011 2979
3012 // Register mapping: 2980 // Register mapping:
3013 // rax is object map. 2981 // rax is object map.
3014 // rdx is function. 2982 // rdx is function.
3015 // rbx is function prototype. 2983 // rbx is function prototype.
3016 if (!HasCallSiteInlineCheck()) { 2984 if (!HasCallSiteInlineCheck()) {
3017 __ StoreRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); 2985 __ StoreRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
3018 __ StoreRoot(rax, Heap::kInstanceofCacheMapRootIndex); 2986 __ StoreRoot(rax, Heap::kInstanceofCacheMapRootIndex);
3019 } else { 2987 } else {
3020 // Get return address and delta to inlined map check. 2988 // Get return address and delta to inlined map check.
3021 __ movq(kScratchRegister, StackOperandForReturnAddress(0)); 2989 __ movp(kScratchRegister, StackOperandForReturnAddress(0));
3022 __ subq(kScratchRegister, args.GetArgumentOperand(2)); 2990 __ subq(kScratchRegister, args.GetArgumentOperand(2));
3023 if (FLAG_debug_code) { 2991 if (FLAG_debug_code) {
3024 __ movl(rdi, Immediate(kWordBeforeMapCheckValue)); 2992 __ movl(rdi, Immediate(kWordBeforeMapCheckValue));
3025 __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi); 2993 __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi);
3026 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCheck); 2994 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCheck);
3027 } 2995 }
3028 __ movq(kScratchRegister, 2996 __ movp(kScratchRegister,
3029 Operand(kScratchRegister, kOffsetToMapCheckValue)); 2997 Operand(kScratchRegister, kOffsetToMapCheckValue));
3030 __ movq(Operand(kScratchRegister, 0), rax); 2998 __ movp(Operand(kScratchRegister, 0), rax);
3031 } 2999 }
3032 3000
3033 __ movq(rcx, FieldOperand(rax, Map::kPrototypeOffset)); 3001 __ movp(rcx, FieldOperand(rax, Map::kPrototypeOffset));
3034 3002
3035 // Loop through the prototype chain looking for the function prototype. 3003 // Loop through the prototype chain looking for the function prototype.
3036 Label loop, is_instance, is_not_instance; 3004 Label loop, is_instance, is_not_instance;
3037 __ LoadRoot(kScratchRegister, Heap::kNullValueRootIndex); 3005 __ LoadRoot(kScratchRegister, Heap::kNullValueRootIndex);
3038 __ bind(&loop); 3006 __ bind(&loop);
3039 __ cmpq(rcx, rbx); 3007 __ cmpq(rcx, rbx);
3040 __ j(equal, &is_instance, Label::kNear); 3008 __ j(equal, &is_instance, Label::kNear);
3041 __ cmpq(rcx, kScratchRegister); 3009 __ cmpq(rcx, kScratchRegister);
3042 // The code at is_not_instance assumes that kScratchRegister contains a 3010 // The code at is_not_instance assumes that kScratchRegister contains a
3043 // non-zero GCable value (the null object in this case). 3011 // non-zero GCable value (the null object in this case).
3044 __ j(equal, &is_not_instance, Label::kNear); 3012 __ j(equal, &is_not_instance, Label::kNear);
3045 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); 3013 __ movp(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
3046 __ movq(rcx, FieldOperand(rcx, Map::kPrototypeOffset)); 3014 __ movp(rcx, FieldOperand(rcx, Map::kPrototypeOffset));
3047 __ jmp(&loop); 3015 __ jmp(&loop);
3048 3016
3049 __ bind(&is_instance); 3017 __ bind(&is_instance);
3050 if (!HasCallSiteInlineCheck()) { 3018 if (!HasCallSiteInlineCheck()) {
3051 __ xorl(rax, rax); 3019 __ xorl(rax, rax);
3052 // Store bitwise zero in the cache. This is a Smi in GC terms. 3020 // Store bitwise zero in the cache. This is a Smi in GC terms.
3053 STATIC_ASSERT(kSmiTag == 0); 3021 STATIC_ASSERT(kSmiTag == 0);
3054 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); 3022 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
3055 } else { 3023 } else {
3056 // Store offset of true in the root array at the inline check site. 3024 // Store offset of true in the root array at the inline check site.
3057 int true_offset = 0x100 + 3025 int true_offset = 0x100 +
3058 (Heap::kTrueValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; 3026 (Heap::kTrueValueRootIndex << kPointerSizeLog2) - kRootRegisterBias;
3059 // Assert it is a 1-byte signed value. 3027 // Assert it is a 1-byte signed value.
3060 ASSERT(true_offset >= 0 && true_offset < 0x100); 3028 ASSERT(true_offset >= 0 && true_offset < 0x100);
3061 __ movl(rax, Immediate(true_offset)); 3029 __ movl(rax, Immediate(true_offset));
3062 __ movq(kScratchRegister, StackOperandForReturnAddress(0)); 3030 __ movp(kScratchRegister, StackOperandForReturnAddress(0));
3063 __ subq(kScratchRegister, args.GetArgumentOperand(2)); 3031 __ subq(kScratchRegister, args.GetArgumentOperand(2));
3064 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); 3032 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax);
3065 if (FLAG_debug_code) { 3033 if (FLAG_debug_code) {
3066 __ movl(rax, Immediate(kWordBeforeResultValue)); 3034 __ movl(rax, Immediate(kWordBeforeResultValue));
3067 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); 3035 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax);
3068 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); 3036 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov);
3069 } 3037 }
3070 __ Set(rax, 0); 3038 __ Set(rax, 0);
3071 } 3039 }
3072 __ ret((2 + extra_argument_offset) * kPointerSize); 3040 __ ret((2 + extra_argument_offset) * kPointerSize);
3073 3041
3074 __ bind(&is_not_instance); 3042 __ bind(&is_not_instance);
3075 if (!HasCallSiteInlineCheck()) { 3043 if (!HasCallSiteInlineCheck()) {
3076 // We have to store a non-zero value in the cache. 3044 // We have to store a non-zero value in the cache.
3077 __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex); 3045 __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex);
3078 } else { 3046 } else {
3079 // Store offset of false in the root array at the inline check site. 3047 // Store offset of false in the root array at the inline check site.
3080 int false_offset = 0x100 + 3048 int false_offset = 0x100 +
3081 (Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; 3049 (Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias;
3082 // Assert it is a 1-byte signed value. 3050 // Assert it is a 1-byte signed value.
3083 ASSERT(false_offset >= 0 && false_offset < 0x100); 3051 ASSERT(false_offset >= 0 && false_offset < 0x100);
3084 __ movl(rax, Immediate(false_offset)); 3052 __ movl(rax, Immediate(false_offset));
3085 __ movq(kScratchRegister, StackOperandForReturnAddress(0)); 3053 __ movp(kScratchRegister, StackOperandForReturnAddress(0));
3086 __ subq(kScratchRegister, args.GetArgumentOperand(2)); 3054 __ subq(kScratchRegister, args.GetArgumentOperand(2));
3087 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); 3055 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax);
3088 if (FLAG_debug_code) { 3056 if (FLAG_debug_code) {
3089 __ movl(rax, Immediate(kWordBeforeResultValue)); 3057 __ movl(rax, Immediate(kWordBeforeResultValue));
3090 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); 3058 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax);
3091 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); 3059 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov);
3092 } 3060 }
3093 } 3061 }
3094 __ ret((2 + extra_argument_offset) * kPointerSize); 3062 __ ret((2 + extra_argument_offset) * kPointerSize);
3095 3063
(...skipping 22 matching lines...) Expand all
3118 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 3086 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
3119 Label flat_string; 3087 Label flat_string;
3120 Label ascii_string; 3088 Label ascii_string;
3121 Label got_char_code; 3089 Label got_char_code;
3122 Label sliced_string; 3090 Label sliced_string;
3123 3091
3124 // If the receiver is a smi trigger the non-string case. 3092 // If the receiver is a smi trigger the non-string case.
3125 __ JumpIfSmi(object_, receiver_not_string_); 3093 __ JumpIfSmi(object_, receiver_not_string_);
3126 3094
3127 // Fetch the instance type of the receiver into result register. 3095 // Fetch the instance type of the receiver into result register.
3128 __ movq(result_, FieldOperand(object_, HeapObject::kMapOffset)); 3096 __ movp(result_, FieldOperand(object_, HeapObject::kMapOffset));
3129 __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); 3097 __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
3130 // If the receiver is not a string trigger the non-string case. 3098 // If the receiver is not a string trigger the non-string case.
3131 __ testb(result_, Immediate(kIsNotStringMask)); 3099 __ testb(result_, Immediate(kIsNotStringMask));
3132 __ j(not_zero, receiver_not_string_); 3100 __ j(not_zero, receiver_not_string_);
3133 3101
3134 // If the index is non-smi trigger the non-smi case. 3102 // If the index is non-smi trigger the non-smi case.
3135 __ JumpIfNotSmi(index_, &index_not_smi_); 3103 __ JumpIfNotSmi(index_, &index_not_smi_);
3136 __ bind(&got_smi_index_); 3104 __ bind(&got_smi_index_);
3137 3105
3138 // Check for index out of range. 3106 // Check for index out of range.
(...skipping 29 matching lines...) Expand all
3168 if (index_flags_ == STRING_INDEX_IS_NUMBER) { 3136 if (index_flags_ == STRING_INDEX_IS_NUMBER) {
3169 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); 3137 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
3170 } else { 3138 } else {
3171 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); 3139 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
3172 // NumberToSmi discards numbers that are not exact integers. 3140 // NumberToSmi discards numbers that are not exact integers.
3173 __ CallRuntime(Runtime::kNumberToSmi, 1); 3141 __ CallRuntime(Runtime::kNumberToSmi, 1);
3174 } 3142 }
3175 if (!index_.is(rax)) { 3143 if (!index_.is(rax)) {
3176 // Save the conversion result before the pop instructions below 3144 // Save the conversion result before the pop instructions below
3177 // have a chance to overwrite it. 3145 // have a chance to overwrite it.
3178 __ movq(index_, rax); 3146 __ movp(index_, rax);
3179 } 3147 }
3180 __ pop(object_); 3148 __ pop(object_);
3181 // Reload the instance type. 3149 // Reload the instance type.
3182 __ movq(result_, FieldOperand(object_, HeapObject::kMapOffset)); 3150 __ movp(result_, FieldOperand(object_, HeapObject::kMapOffset));
3183 __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); 3151 __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
3184 call_helper.AfterCall(masm); 3152 call_helper.AfterCall(masm);
3185 // If index is still not a smi, it must be out of range. 3153 // If index is still not a smi, it must be out of range.
3186 __ JumpIfNotSmi(index_, index_out_of_range_); 3154 __ JumpIfNotSmi(index_, index_out_of_range_);
3187 // Otherwise, return to the fast path. 3155 // Otherwise, return to the fast path.
3188 __ jmp(&got_smi_index_); 3156 __ jmp(&got_smi_index_);
3189 3157
3190 // Call runtime. We get here when the receiver is a string and the 3158 // Call runtime. We get here when the receiver is a string and the
3191 // index is a number, but the code of getting the actual character 3159 // index is a number, but the code of getting the actual character
3192 // is too complex (e.g., when the string needs to be flattened). 3160 // is too complex (e.g., when the string needs to be flattened).
3193 __ bind(&call_runtime_); 3161 __ bind(&call_runtime_);
3194 call_helper.BeforeCall(masm); 3162 call_helper.BeforeCall(masm);
3195 __ push(object_); 3163 __ push(object_);
3196 __ Integer32ToSmi(index_, index_); 3164 __ Integer32ToSmi(index_, index_);
3197 __ push(index_); 3165 __ push(index_);
3198 __ CallRuntime(Runtime::kStringCharCodeAt, 2); 3166 __ CallRuntime(Runtime::kStringCharCodeAt, 2);
3199 if (!result_.is(rax)) { 3167 if (!result_.is(rax)) {
3200 __ movq(result_, rax); 3168 __ movp(result_, rax);
3201 } 3169 }
3202 call_helper.AfterCall(masm); 3170 call_helper.AfterCall(masm);
3203 __ jmp(&exit_); 3171 __ jmp(&exit_);
3204 3172
3205 __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); 3173 __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
3206 } 3174 }
3207 3175
3208 3176
3209 // ------------------------------------------------------------------------- 3177 // -------------------------------------------------------------------------
3210 // StringCharFromCodeGenerator 3178 // StringCharFromCodeGenerator
3211 3179
3212 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { 3180 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
3213 // Fast case of Heap::LookupSingleCharacterStringFromCode. 3181 // Fast case of Heap::LookupSingleCharacterStringFromCode.
3214 __ JumpIfNotSmi(code_, &slow_case_); 3182 __ JumpIfNotSmi(code_, &slow_case_);
3215 __ SmiCompare(code_, Smi::FromInt(String::kMaxOneByteCharCode)); 3183 __ SmiCompare(code_, Smi::FromInt(String::kMaxOneByteCharCode));
3216 __ j(above, &slow_case_); 3184 __ j(above, &slow_case_);
3217 3185
3218 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); 3186 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
3219 SmiIndex index = masm->SmiToIndex(kScratchRegister, code_, kPointerSizeLog2); 3187 SmiIndex index = masm->SmiToIndex(kScratchRegister, code_, kPointerSizeLog2);
3220 __ movq(result_, FieldOperand(result_, index.reg, index.scale, 3188 __ movp(result_, FieldOperand(result_, index.reg, index.scale,
3221 FixedArray::kHeaderSize)); 3189 FixedArray::kHeaderSize));
3222 __ CompareRoot(result_, Heap::kUndefinedValueRootIndex); 3190 __ CompareRoot(result_, Heap::kUndefinedValueRootIndex);
3223 __ j(equal, &slow_case_); 3191 __ j(equal, &slow_case_);
3224 __ bind(&exit_); 3192 __ bind(&exit_);
3225 } 3193 }
3226 3194
3227 3195
3228 void StringCharFromCodeGenerator::GenerateSlow( 3196 void StringCharFromCodeGenerator::GenerateSlow(
3229 MacroAssembler* masm, 3197 MacroAssembler* masm,
3230 const RuntimeCallHelper& call_helper) { 3198 const RuntimeCallHelper& call_helper) {
3231 __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); 3199 __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
3232 3200
3233 __ bind(&slow_case_); 3201 __ bind(&slow_case_);
3234 call_helper.BeforeCall(masm); 3202 call_helper.BeforeCall(masm);
3235 __ push(code_); 3203 __ push(code_);
3236 __ CallRuntime(Runtime::kCharFromCode, 1); 3204 __ CallRuntime(Runtime::kCharFromCode, 1);
3237 if (!result_.is(rax)) { 3205 if (!result_.is(rax)) {
3238 __ movq(result_, rax); 3206 __ movp(result_, rax);
3239 } 3207 }
3240 call_helper.AfterCall(masm); 3208 call_helper.AfterCall(masm);
3241 __ jmp(&exit_); 3209 __ jmp(&exit_);
3242 3210
3243 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); 3211 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
3244 } 3212 }
3245 3213
3246 3214
3247 void StringAddStub::Generate(MacroAssembler* masm) {
3248 Label call_runtime, call_builtin;
3249 Builtins::JavaScript builtin_id = Builtins::ADD;
3250
3251 // Load the two arguments.
3252 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER);
3253 __ movq(rax, args.GetArgumentOperand(0)); // First argument (left).
3254 __ movq(rdx, args.GetArgumentOperand(1)); // Second argument (right).
3255
3256 // Make sure that both arguments are strings if not known in advance.
3257 // Otherwise, at least one of the arguments is definitely a string,
3258 // and we convert the one that is not known to be a string.
3259 if ((flags_ & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
3260 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT);
3261 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT);
3262 __ JumpIfSmi(rax, &call_runtime);
3263 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, r8);
3264 __ j(above_equal, &call_runtime);
3265
3266 // First argument is a a string, test second.
3267 __ JumpIfSmi(rdx, &call_runtime);
3268 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, r9);
3269 __ j(above_equal, &call_runtime);
3270 } else if ((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
3271 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == 0);
3272 GenerateConvertArgument(masm, 2 * kPointerSize, rax, rbx, rcx, rdi,
3273 &call_builtin);
3274 builtin_id = Builtins::STRING_ADD_RIGHT;
3275 } else if ((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
3276 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == 0);
3277 GenerateConvertArgument(masm, 1 * kPointerSize, rdx, rbx, rcx, rdi,
3278 &call_builtin);
3279 builtin_id = Builtins::STRING_ADD_LEFT;
3280 }
3281
3282 // Both arguments are strings.
3283 // rax: first string
3284 // rdx: second string
3285 // Check if either of the strings are empty. In that case return the other.
3286 Label second_not_zero_length, both_not_zero_length;
3287 __ movq(rcx, FieldOperand(rdx, String::kLengthOffset));
3288 __ SmiTest(rcx);
3289 __ j(not_zero, &second_not_zero_length, Label::kNear);
3290 // Second string is empty, result is first string which is already in rax.
3291 Counters* counters = masm->isolate()->counters();
3292 __ IncrementCounter(counters->string_add_native(), 1);
3293 __ ret(2 * kPointerSize);
3294 __ bind(&second_not_zero_length);
3295 __ movq(rbx, FieldOperand(rax, String::kLengthOffset));
3296 __ SmiTest(rbx);
3297 __ j(not_zero, &both_not_zero_length, Label::kNear);
3298 // First string is empty, result is second string which is in rdx.
3299 __ movq(rax, rdx);
3300 __ IncrementCounter(counters->string_add_native(), 1);
3301 __ ret(2 * kPointerSize);
3302
3303 // Both strings are non-empty.
3304 // rax: first string
3305 // rbx: length of first string
3306 // rcx: length of second string
3307 // rdx: second string
3308 // r8: map of first string (if flags_ == NO_STRING_ADD_FLAGS)
3309 // r9: map of second string (if flags_ == NO_STRING_ADD_FLAGS)
3310 Label string_add_flat_result, longer_than_two;
3311 __ bind(&both_not_zero_length);
3312
3313 // If arguments where known to be strings, maps are not loaded to r8 and r9
3314 // by the code above.
3315 if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) {
3316 __ movq(r8, FieldOperand(rax, HeapObject::kMapOffset));
3317 __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset));
3318 }
3319 // Get the instance types of the two strings as they will be needed soon.
3320 __ movzxbl(r8, FieldOperand(r8, Map::kInstanceTypeOffset));
3321 __ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset));
3322
3323 // Look at the length of the result of adding the two strings.
3324 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue / 2);
3325 __ SmiAdd(rbx, rbx, rcx);
3326 // Use the string table when adding two one character strings, as it
3327 // helps later optimizations to return an internalized string here.
3328 __ SmiCompare(rbx, Smi::FromInt(2));
3329 __ j(not_equal, &longer_than_two);
3330
3331 // Check that both strings are non-external ASCII strings.
3332 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx,
3333 &call_runtime);
3334
3335 // Get the two characters forming the sub string.
3336 __ movzxbq(rbx, FieldOperand(rax, SeqOneByteString::kHeaderSize));
3337 __ movzxbq(rcx, FieldOperand(rdx, SeqOneByteString::kHeaderSize));
3338
3339 // Try to lookup two character string in string table. If it is not found
3340 // just allocate a new one.
3341 Label make_two_character_string, make_flat_ascii_string;
3342 StringHelper::GenerateTwoCharacterStringTableProbe(
3343 masm, rbx, rcx, r14, r11, rdi, r15, &make_two_character_string);
3344 __ IncrementCounter(counters->string_add_native(), 1);
3345 __ ret(2 * kPointerSize);
3346
3347 __ bind(&make_two_character_string);
3348 __ Set(rdi, 2);
3349 __ AllocateAsciiString(rax, rdi, r8, r9, r11, &call_runtime);
3350 // rbx - first byte: first character
3351 // rbx - second byte: *maybe* second character
3352 // Make sure that the second byte of rbx contains the second character.
3353 __ movzxbq(rcx, FieldOperand(rdx, SeqOneByteString::kHeaderSize));
3354 __ shll(rcx, Immediate(kBitsPerByte));
3355 __ orl(rbx, rcx);
3356 // Write both characters to the new string.
3357 __ movw(FieldOperand(rax, SeqOneByteString::kHeaderSize), rbx);
3358 __ IncrementCounter(counters->string_add_native(), 1);
3359 __ ret(2 * kPointerSize);
3360
3361 __ bind(&longer_than_two);
3362 // Check if resulting string will be flat.
3363 __ SmiCompare(rbx, Smi::FromInt(ConsString::kMinLength));
3364 __ j(below, &string_add_flat_result);
3365 // Handle exceptionally long strings in the runtime system.
3366 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0);
3367 __ SmiCompare(rbx, Smi::FromInt(String::kMaxLength));
3368 __ j(above, &call_runtime);
3369
3370 // If result is not supposed to be flat, allocate a cons string object. If
3371 // both strings are ASCII the result is an ASCII cons string.
3372 // rax: first string
3373 // rbx: length of resulting flat string
3374 // rdx: second string
3375 // r8: instance type of first string
3376 // r9: instance type of second string
3377 Label non_ascii, allocated, ascii_data;
3378 __ movl(rcx, r8);
3379 __ and_(rcx, r9);
3380 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
3381 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
3382 __ testl(rcx, Immediate(kStringEncodingMask));
3383 __ j(zero, &non_ascii);
3384 __ bind(&ascii_data);
3385 // Allocate an ASCII cons string.
3386 __ AllocateAsciiConsString(rcx, rdi, no_reg, &call_runtime);
3387 __ bind(&allocated);
3388 // Fill the fields of the cons string.
3389 __ movq(FieldOperand(rcx, ConsString::kLengthOffset), rbx);
3390 __ movq(FieldOperand(rcx, ConsString::kHashFieldOffset),
3391 Immediate(String::kEmptyHashField));
3392
3393 Label skip_write_barrier, after_writing;
3394 ExternalReference high_promotion_mode = ExternalReference::
3395 new_space_high_promotion_mode_active_address(masm->isolate());
3396 __ Load(rbx, high_promotion_mode);
3397 __ testb(rbx, Immediate(1));
3398 __ j(zero, &skip_write_barrier);
3399
3400 __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax);
3401 __ RecordWriteField(rcx,
3402 ConsString::kFirstOffset,
3403 rax,
3404 rbx,
3405 kDontSaveFPRegs);
3406 __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx);
3407 __ RecordWriteField(rcx,
3408 ConsString::kSecondOffset,
3409 rdx,
3410 rbx,
3411 kDontSaveFPRegs);
3412 __ jmp(&after_writing);
3413
3414 __ bind(&skip_write_barrier);
3415 __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax);
3416 __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx);
3417
3418 __ bind(&after_writing);
3419
3420 __ movq(rax, rcx);
3421 __ IncrementCounter(counters->string_add_native(), 1);
3422 __ ret(2 * kPointerSize);
3423 __ bind(&non_ascii);
3424 // At least one of the strings is two-byte. Check whether it happens
3425 // to contain only one byte characters.
3426 // rcx: first instance type AND second instance type.
3427 // r8: first instance type.
3428 // r9: second instance type.
3429 __ testb(rcx, Immediate(kOneByteDataHintMask));
3430 __ j(not_zero, &ascii_data);
3431 __ xor_(r8, r9);
3432 STATIC_ASSERT(kOneByteStringTag != 0 && kOneByteDataHintTag != 0);
3433 __ andb(r8, Immediate(kOneByteStringTag | kOneByteDataHintTag));
3434 __ cmpb(r8, Immediate(kOneByteStringTag | kOneByteDataHintTag));
3435 __ j(equal, &ascii_data);
3436 // Allocate a two byte cons string.
3437 __ AllocateTwoByteConsString(rcx, rdi, no_reg, &call_runtime);
3438 __ jmp(&allocated);
3439
3440 // We cannot encounter sliced strings or cons strings here since:
3441 STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength);
3442 // Handle creating a flat result from either external or sequential strings.
3443 // Locate the first characters' locations.
3444 // rax: first string
3445 // rbx: length of resulting flat string as smi
3446 // rdx: second string
3447 // r8: instance type of first string
3448 // r9: instance type of first string
3449 Label first_prepared, second_prepared;
3450 Label first_is_sequential, second_is_sequential;
3451 __ bind(&string_add_flat_result);
3452
3453 __ SmiToInteger32(r14, FieldOperand(rax, SeqString::kLengthOffset));
3454 // r14: length of first string
3455 STATIC_ASSERT(kSeqStringTag == 0);
3456 __ testb(r8, Immediate(kStringRepresentationMask));
3457 __ j(zero, &first_is_sequential, Label::kNear);
3458 // Rule out short external string and load string resource.
3459 STATIC_ASSERT(kShortExternalStringTag != 0);
3460 __ testb(r8, Immediate(kShortExternalStringMask));
3461 __ j(not_zero, &call_runtime);
3462 __ movq(rcx, FieldOperand(rax, ExternalString::kResourceDataOffset));
3463 __ jmp(&first_prepared, Label::kNear);
3464 __ bind(&first_is_sequential);
3465 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
3466 __ lea(rcx, FieldOperand(rax, SeqOneByteString::kHeaderSize));
3467 __ bind(&first_prepared);
3468
3469 // Check whether both strings have same encoding.
3470 __ xorl(r8, r9);
3471 __ testb(r8, Immediate(kStringEncodingMask));
3472 __ j(not_zero, &call_runtime);
3473
3474 __ SmiToInteger32(r15, FieldOperand(rdx, SeqString::kLengthOffset));
3475 // r15: length of second string
3476 STATIC_ASSERT(kSeqStringTag == 0);
3477 __ testb(r9, Immediate(kStringRepresentationMask));
3478 __ j(zero, &second_is_sequential, Label::kNear);
3479 // Rule out short external string and load string resource.
3480 STATIC_ASSERT(kShortExternalStringTag != 0);
3481 __ testb(r9, Immediate(kShortExternalStringMask));
3482 __ j(not_zero, &call_runtime);
3483 __ movq(rdx, FieldOperand(rdx, ExternalString::kResourceDataOffset));
3484 __ jmp(&second_prepared, Label::kNear);
3485 __ bind(&second_is_sequential);
3486 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
3487 __ lea(rdx, FieldOperand(rdx, SeqOneByteString::kHeaderSize));
3488 __ bind(&second_prepared);
3489
3490 Label non_ascii_string_add_flat_result;
3491 // r9: instance type of second string
3492 // First string and second string have the same encoding.
3493 STATIC_ASSERT(kTwoByteStringTag == 0);
3494 __ SmiToInteger32(rbx, rbx);
3495 __ testb(r9, Immediate(kStringEncodingMask));
3496 __ j(zero, &non_ascii_string_add_flat_result);
3497
3498 __ bind(&make_flat_ascii_string);
3499 // Both strings are ASCII strings. As they are short they are both flat.
3500 __ AllocateAsciiString(rax, rbx, rdi, r8, r9, &call_runtime);
3501 // rax: result string
3502 // Locate first character of result.
3503 __ lea(rbx, FieldOperand(rax, SeqOneByteString::kHeaderSize));
3504 // rcx: first char of first string
3505 // rbx: first character of result
3506 // r14: length of first string
3507 StringHelper::GenerateCopyCharacters(masm, rbx, rcx, r14, true);
3508 // rbx: next character of result
3509 // rdx: first char of second string
3510 // r15: length of second string
3511 StringHelper::GenerateCopyCharacters(masm, rbx, rdx, r15, true);
3512 __ IncrementCounter(counters->string_add_native(), 1);
3513 __ ret(2 * kPointerSize);
3514
3515 __ bind(&non_ascii_string_add_flat_result);
3516 // Both strings are ASCII strings. As they are short they are both flat.
3517 __ AllocateTwoByteString(rax, rbx, rdi, r8, r9, &call_runtime);
3518 // rax: result string
3519 // Locate first character of result.
3520 __ lea(rbx, FieldOperand(rax, SeqTwoByteString::kHeaderSize));
3521 // rcx: first char of first string
3522 // rbx: first character of result
3523 // r14: length of first string
3524 StringHelper::GenerateCopyCharacters(masm, rbx, rcx, r14, false);
3525 // rbx: next character of result
3526 // rdx: first char of second string
3527 // r15: length of second string
3528 StringHelper::GenerateCopyCharacters(masm, rbx, rdx, r15, false);
3529 __ IncrementCounter(counters->string_add_native(), 1);
3530 __ ret(2 * kPointerSize);
3531
3532 // Just jump to runtime to add the two strings.
3533 __ bind(&call_runtime);
3534 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
3535
3536 if (call_builtin.is_linked()) {
3537 __ bind(&call_builtin);
3538 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
3539 }
3540 }
3541
3542
3543 void StringAddStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
3544 __ push(rax);
3545 __ push(rdx);
3546 }
3547
3548
3549 void StringAddStub::GenerateRegisterArgsPop(MacroAssembler* masm,
3550 Register temp) {
3551 __ PopReturnAddressTo(temp);
3552 __ pop(rdx);
3553 __ pop(rax);
3554 __ PushReturnAddressFrom(temp);
3555 }
3556
3557
3558 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
3559 int stack_offset,
3560 Register arg,
3561 Register scratch1,
3562 Register scratch2,
3563 Register scratch3,
3564 Label* slow) {
3565 // First check if the argument is already a string.
3566 Label not_string, done;
3567 __ JumpIfSmi(arg, &not_string);
3568 __ CmpObjectType(arg, FIRST_NONSTRING_TYPE, scratch1);
3569 __ j(below, &done);
3570
3571 // Check the number to string cache.
3572 __ bind(&not_string);
3573 // Puts the cached result into scratch1.
3574 __ LookupNumberStringCache(arg, scratch1, scratch2, scratch3, slow);
3575 __ movq(arg, scratch1);
3576 __ movq(Operand(rsp, stack_offset), arg);
3577 __ bind(&done);
3578 }
3579
3580
3581 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
3582 Register dest,
3583 Register src,
3584 Register count,
3585 bool ascii) {
3586 Label loop;
3587 __ bind(&loop);
3588 // This loop just copies one character at a time, as it is only used for very
3589 // short strings.
3590 if (ascii) {
3591 __ movb(kScratchRegister, Operand(src, 0));
3592 __ movb(Operand(dest, 0), kScratchRegister);
3593 __ incq(src);
3594 __ incq(dest);
3595 } else {
3596 __ movzxwl(kScratchRegister, Operand(src, 0));
3597 __ movw(Operand(dest, 0), kScratchRegister);
3598 __ addq(src, Immediate(2));
3599 __ addq(dest, Immediate(2));
3600 }
3601 __ decl(count);
3602 __ j(not_zero, &loop);
3603 }
3604
3605
3606 void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm, 3215 void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm,
3607 Register dest, 3216 Register dest,
3608 Register src, 3217 Register src,
3609 Register count, 3218 Register count,
3610 bool ascii) { 3219 bool ascii) {
3611 // Copy characters using rep movs of doublewords. Align destination on 4 byte 3220 // Copy characters using rep movs of doublewords. Align destination on 4 byte
3612 // boundary before starting rep movs. Copy remaining characters after running 3221 // boundary before starting rep movs. Copy remaining characters after running
3613 // rep movs. 3222 // rep movs.
3614 // Count is positive int32, dest and src are character pointers. 3223 // Count is positive int32, dest and src are character pointers.
3615 ASSERT(dest.is(rdi)); // rep movs destination 3224 ASSERT(dest.is(rdi)); // rep movs destination
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
3652 __ movb(kScratchRegister, Operand(src, 0)); 3261 __ movb(kScratchRegister, Operand(src, 0));
3653 __ movb(Operand(dest, 0), kScratchRegister); 3262 __ movb(Operand(dest, 0), kScratchRegister);
3654 __ incq(src); 3263 __ incq(src);
3655 __ incq(dest); 3264 __ incq(dest);
3656 __ decl(count); 3265 __ decl(count);
3657 __ j(not_zero, &loop); 3266 __ j(not_zero, &loop);
3658 3267
3659 __ bind(&done); 3268 __ bind(&done);
3660 } 3269 }
3661 3270
3662 void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
3663 Register c1,
3664 Register c2,
3665 Register scratch1,
3666 Register scratch2,
3667 Register scratch3,
3668 Register scratch4,
3669 Label* not_found) {
3670 // Register scratch3 is the general scratch register in this function.
3671 Register scratch = scratch3;
3672
3673 // Make sure that both characters are not digits as such strings has a
3674 // different hash algorithm. Don't try to look for these in the string table.
3675 Label not_array_index;
3676 __ leal(scratch, Operand(c1, -'0'));
3677 __ cmpl(scratch, Immediate(static_cast<int>('9' - '0')));
3678 __ j(above, &not_array_index, Label::kNear);
3679 __ leal(scratch, Operand(c2, -'0'));
3680 __ cmpl(scratch, Immediate(static_cast<int>('9' - '0')));
3681 __ j(below_equal, not_found);
3682
3683 __ bind(&not_array_index);
3684 // Calculate the two character string hash.
3685 Register hash = scratch1;
3686 GenerateHashInit(masm, hash, c1, scratch);
3687 GenerateHashAddCharacter(masm, hash, c2, scratch);
3688 GenerateHashGetHash(masm, hash, scratch);
3689
3690 // Collect the two characters in a register.
3691 Register chars = c1;
3692 __ shl(c2, Immediate(kBitsPerByte));
3693 __ orl(chars, c2);
3694
3695 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
3696 // hash: hash of two character string.
3697
3698 // Load the string table.
3699 Register string_table = c2;
3700 __ LoadRoot(string_table, Heap::kStringTableRootIndex);
3701
3702 // Calculate capacity mask from the string table capacity.
3703 Register mask = scratch2;
3704 __ SmiToInteger32(mask,
3705 FieldOperand(string_table, StringTable::kCapacityOffset));
3706 __ decl(mask);
3707
3708 Register map = scratch4;
3709
3710 // Registers
3711 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
3712 // hash: hash of two character string (32-bit int)
3713 // string_table: string table
3714 // mask: capacity mask (32-bit int)
3715 // map: -
3716 // scratch: -
3717
3718 // Perform a number of probes in the string table.
3719 static const int kProbes = 4;
3720 Label found_in_string_table;
3721 Label next_probe[kProbes];
3722 Register candidate = scratch; // Scratch register contains candidate.
3723 for (int i = 0; i < kProbes; i++) {
3724 // Calculate entry in string table.
3725 __ movl(scratch, hash);
3726 if (i > 0) {
3727 __ addl(scratch, Immediate(StringTable::GetProbeOffset(i)));
3728 }
3729 __ andl(scratch, mask);
3730
3731 // Load the entry from the string table.
3732 STATIC_ASSERT(StringTable::kEntrySize == 1);
3733 __ movq(candidate,
3734 FieldOperand(string_table,
3735 scratch,
3736 times_pointer_size,
3737 StringTable::kElementsStartOffset));
3738
3739 // If entry is undefined no string with this hash can be found.
3740 Label is_string;
3741 __ CmpObjectType(candidate, ODDBALL_TYPE, map);
3742 __ j(not_equal, &is_string, Label::kNear);
3743
3744 __ CompareRoot(candidate, Heap::kUndefinedValueRootIndex);
3745 __ j(equal, not_found);
3746 // Must be the hole (deleted entry).
3747 if (FLAG_debug_code) {
3748 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
3749 __ cmpq(kScratchRegister, candidate);
3750 __ Assert(equal, kOddballInStringTableIsNotUndefinedOrTheHole);
3751 }
3752 __ jmp(&next_probe[i]);
3753
3754 __ bind(&is_string);
3755
3756 // If length is not 2 the string is not a candidate.
3757 __ SmiCompare(FieldOperand(candidate, String::kLengthOffset),
3758 Smi::FromInt(2));
3759 __ j(not_equal, &next_probe[i]);
3760
3761 // We use kScratchRegister as a temporary register in assumption that
3762 // JumpIfInstanceTypeIsNotSequentialAscii does not use it implicitly
3763 Register temp = kScratchRegister;
3764
3765 // Check that the candidate is a non-external ASCII string.
3766 __ movzxbl(temp, FieldOperand(map, Map::kInstanceTypeOffset));
3767 __ JumpIfInstanceTypeIsNotSequentialAscii(
3768 temp, temp, &next_probe[i]);
3769
3770 // Check if the two characters match.
3771 __ movl(temp, FieldOperand(candidate, SeqOneByteString::kHeaderSize));
3772 __ andl(temp, Immediate(0x0000ffff));
3773 __ cmpl(chars, temp);
3774 __ j(equal, &found_in_string_table);
3775 __ bind(&next_probe[i]);
3776 }
3777
3778 // No matching 2 character string found by probing.
3779 __ jmp(not_found);
3780
3781 // Scratch register contains result when we fall through to here.
3782 Register result = candidate;
3783 __ bind(&found_in_string_table);
3784 if (!result.is(rax)) {
3785 __ movq(rax, result);
3786 }
3787 }
3788
3789 3271
3790 void StringHelper::GenerateHashInit(MacroAssembler* masm, 3272 void StringHelper::GenerateHashInit(MacroAssembler* masm,
3791 Register hash, 3273 Register hash,
3792 Register character, 3274 Register character,
3793 Register scratch) { 3275 Register scratch) {
3794 // hash = (seed + character) + ((seed + character) << 10); 3276 // hash = (seed + character) + ((seed + character) << 10);
3795 __ LoadRoot(scratch, Heap::kHashSeedRootIndex); 3277 __ LoadRoot(scratch, Heap::kHashSeedRootIndex);
3796 __ SmiToInteger32(scratch, scratch); 3278 __ SmiToInteger32(scratch, scratch);
3797 __ addl(scratch, character); 3279 __ addl(scratch, character);
3798 __ movl(hash, scratch); 3280 __ movl(hash, scratch);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
3859 STRING_ARGUMENT_INDEX, 3341 STRING_ARGUMENT_INDEX,
3860 FROM_ARGUMENT_INDEX, 3342 FROM_ARGUMENT_INDEX,
3861 TO_ARGUMENT_INDEX, 3343 TO_ARGUMENT_INDEX,
3862 SUB_STRING_ARGUMENT_COUNT 3344 SUB_STRING_ARGUMENT_COUNT
3863 }; 3345 };
3864 3346
3865 StackArgumentsAccessor args(rsp, SUB_STRING_ARGUMENT_COUNT, 3347 StackArgumentsAccessor args(rsp, SUB_STRING_ARGUMENT_COUNT,
3866 ARGUMENTS_DONT_CONTAIN_RECEIVER); 3348 ARGUMENTS_DONT_CONTAIN_RECEIVER);
3867 3349
3868 // Make sure first argument is a string. 3350 // Make sure first argument is a string.
3869 __ movq(rax, args.GetArgumentOperand(STRING_ARGUMENT_INDEX)); 3351 __ movp(rax, args.GetArgumentOperand(STRING_ARGUMENT_INDEX));
3870 STATIC_ASSERT(kSmiTag == 0); 3352 STATIC_ASSERT(kSmiTag == 0);
3871 __ testl(rax, Immediate(kSmiTagMask)); 3353 __ testl(rax, Immediate(kSmiTagMask));
3872 __ j(zero, &runtime); 3354 __ j(zero, &runtime);
3873 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx); 3355 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx);
3874 __ j(NegateCondition(is_string), &runtime); 3356 __ j(NegateCondition(is_string), &runtime);
3875 3357
3876 // rax: string 3358 // rax: string
3877 // rbx: instance type 3359 // rbx: instance type
3878 // Calculate length of sub string using the smi values. 3360 // Calculate length of sub string using the smi values.
3879 __ movq(rcx, args.GetArgumentOperand(TO_ARGUMENT_INDEX)); 3361 __ movp(rcx, args.GetArgumentOperand(TO_ARGUMENT_INDEX));
3880 __ movq(rdx, args.GetArgumentOperand(FROM_ARGUMENT_INDEX)); 3362 __ movp(rdx, args.GetArgumentOperand(FROM_ARGUMENT_INDEX));
3881 __ JumpUnlessBothNonNegativeSmi(rcx, rdx, &runtime); 3363 __ JumpUnlessBothNonNegativeSmi(rcx, rdx, &runtime);
3882 3364
3883 __ SmiSub(rcx, rcx, rdx); // Overflow doesn't happen. 3365 __ SmiSub(rcx, rcx, rdx); // Overflow doesn't happen.
3884 __ cmpq(rcx, FieldOperand(rax, String::kLengthOffset)); 3366 __ cmpq(rcx, FieldOperand(rax, String::kLengthOffset));
3885 Label not_original_string; 3367 Label not_original_string;
3886 // Shorter than original string's length: an actual substring. 3368 // Shorter than original string's length: an actual substring.
3887 __ j(below, &not_original_string, Label::kNear); 3369 __ j(below, &not_original_string, Label::kNear);
3888 // Longer than original string's length or negative: unsafe arguments. 3370 // Longer than original string's length or negative: unsafe arguments.
3889 __ j(above, &runtime); 3371 __ j(above, &runtime);
3890 // Return original string. 3372 // Return original string.
(...skipping 21 matching lines...) Expand all
3912 __ testb(rbx, Immediate(kIsIndirectStringMask)); 3394 __ testb(rbx, Immediate(kIsIndirectStringMask));
3913 __ j(zero, &seq_or_external_string, Label::kNear); 3395 __ j(zero, &seq_or_external_string, Label::kNear);
3914 3396
3915 __ testb(rbx, Immediate(kSlicedNotConsMask)); 3397 __ testb(rbx, Immediate(kSlicedNotConsMask));
3916 __ j(not_zero, &sliced_string, Label::kNear); 3398 __ j(not_zero, &sliced_string, Label::kNear);
3917 // Cons string. Check whether it is flat, then fetch first part. 3399 // Cons string. Check whether it is flat, then fetch first part.
3918 // Flat cons strings have an empty second part. 3400 // Flat cons strings have an empty second part.
3919 __ CompareRoot(FieldOperand(rax, ConsString::kSecondOffset), 3401 __ CompareRoot(FieldOperand(rax, ConsString::kSecondOffset),
3920 Heap::kempty_stringRootIndex); 3402 Heap::kempty_stringRootIndex);
3921 __ j(not_equal, &runtime); 3403 __ j(not_equal, &runtime);
3922 __ movq(rdi, FieldOperand(rax, ConsString::kFirstOffset)); 3404 __ movp(rdi, FieldOperand(rax, ConsString::kFirstOffset));
3923 // Update instance type. 3405 // Update instance type.
3924 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); 3406 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
3925 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 3407 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
3926 __ jmp(&underlying_unpacked, Label::kNear); 3408 __ jmp(&underlying_unpacked, Label::kNear);
3927 3409
3928 __ bind(&sliced_string); 3410 __ bind(&sliced_string);
3929 // Sliced string. Fetch parent and correct start index by offset. 3411 // Sliced string. Fetch parent and correct start index by offset.
3930 __ addq(rdx, FieldOperand(rax, SlicedString::kOffsetOffset)); 3412 __ addq(rdx, FieldOperand(rax, SlicedString::kOffsetOffset));
3931 __ movq(rdi, FieldOperand(rax, SlicedString::kParentOffset)); 3413 __ movp(rdi, FieldOperand(rax, SlicedString::kParentOffset));
3932 // Update instance type. 3414 // Update instance type.
3933 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); 3415 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
3934 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 3416 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
3935 __ jmp(&underlying_unpacked, Label::kNear); 3417 __ jmp(&underlying_unpacked, Label::kNear);
3936 3418
3937 __ bind(&seq_or_external_string); 3419 __ bind(&seq_or_external_string);
3938 // Sequential or external string. Just move string to the correct register. 3420 // Sequential or external string. Just move string to the correct register.
3939 __ movq(rdi, rax); 3421 __ movp(rdi, rax);
3940 3422
3941 __ bind(&underlying_unpacked); 3423 __ bind(&underlying_unpacked);
3942 3424
3943 if (FLAG_string_slices) { 3425 if (FLAG_string_slices) {
3944 Label copy_routine; 3426 Label copy_routine;
3945 // rdi: underlying subject string 3427 // rdi: underlying subject string
3946 // rbx: instance type of underlying subject string 3428 // rbx: instance type of underlying subject string
3947 // rdx: adjusted start index (smi) 3429 // rdx: adjusted start index (smi)
3948 // rcx: length 3430 // rcx: length
3949 // If coming from the make_two_character_string path, the string 3431 // If coming from the make_two_character_string path, the string
(...skipping 10 matching lines...) Expand all
3960 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); 3442 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
3961 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); 3443 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
3962 __ testb(rbx, Immediate(kStringEncodingMask)); 3444 __ testb(rbx, Immediate(kStringEncodingMask));
3963 __ j(zero, &two_byte_slice, Label::kNear); 3445 __ j(zero, &two_byte_slice, Label::kNear);
3964 __ AllocateAsciiSlicedString(rax, rbx, r14, &runtime); 3446 __ AllocateAsciiSlicedString(rax, rbx, r14, &runtime);
3965 __ jmp(&set_slice_header, Label::kNear); 3447 __ jmp(&set_slice_header, Label::kNear);
3966 __ bind(&two_byte_slice); 3448 __ bind(&two_byte_slice);
3967 __ AllocateTwoByteSlicedString(rax, rbx, r14, &runtime); 3449 __ AllocateTwoByteSlicedString(rax, rbx, r14, &runtime);
3968 __ bind(&set_slice_header); 3450 __ bind(&set_slice_header);
3969 __ Integer32ToSmi(rcx, rcx); 3451 __ Integer32ToSmi(rcx, rcx);
3970 __ movq(FieldOperand(rax, SlicedString::kLengthOffset), rcx); 3452 __ movp(FieldOperand(rax, SlicedString::kLengthOffset), rcx);
3971 __ movq(FieldOperand(rax, SlicedString::kHashFieldOffset), 3453 __ movp(FieldOperand(rax, SlicedString::kHashFieldOffset),
3972 Immediate(String::kEmptyHashField)); 3454 Immediate(String::kEmptyHashField));
3973 __ movq(FieldOperand(rax, SlicedString::kParentOffset), rdi); 3455 __ movp(FieldOperand(rax, SlicedString::kParentOffset), rdi);
3974 __ movq(FieldOperand(rax, SlicedString::kOffsetOffset), rdx); 3456 __ movp(FieldOperand(rax, SlicedString::kOffsetOffset), rdx);
3975 __ IncrementCounter(counters->sub_string_native(), 1); 3457 __ IncrementCounter(counters->sub_string_native(), 1);
3976 __ ret(3 * kPointerSize); 3458 __ ret(3 * kPointerSize);
3977 3459
3978 __ bind(&copy_routine); 3460 __ bind(&copy_routine);
3979 } 3461 }
3980 3462
3981 // rdi: underlying subject string 3463 // rdi: underlying subject string
3982 // rbx: instance type of underlying subject string 3464 // rbx: instance type of underlying subject string
3983 // rdx: adjusted start index (smi) 3465 // rdx: adjusted start index (smi)
3984 // rcx: length 3466 // rcx: length
3985 // The subject string can only be external or sequential string of either 3467 // The subject string can only be external or sequential string of either
3986 // encoding at this point. 3468 // encoding at this point.
3987 Label two_byte_sequential, sequential_string; 3469 Label two_byte_sequential, sequential_string;
3988 STATIC_ASSERT(kExternalStringTag != 0); 3470 STATIC_ASSERT(kExternalStringTag != 0);
3989 STATIC_ASSERT(kSeqStringTag == 0); 3471 STATIC_ASSERT(kSeqStringTag == 0);
3990 __ testb(rbx, Immediate(kExternalStringTag)); 3472 __ testb(rbx, Immediate(kExternalStringTag));
3991 __ j(zero, &sequential_string); 3473 __ j(zero, &sequential_string);
3992 3474
3993 // Handle external string. 3475 // Handle external string.
3994 // Rule out short external strings. 3476 // Rule out short external strings.
3995 STATIC_CHECK(kShortExternalStringTag != 0); 3477 STATIC_CHECK(kShortExternalStringTag != 0);
3996 __ testb(rbx, Immediate(kShortExternalStringMask)); 3478 __ testb(rbx, Immediate(kShortExternalStringMask));
3997 __ j(not_zero, &runtime); 3479 __ j(not_zero, &runtime);
3998 __ movq(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); 3480 __ movp(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset));
3999 // Move the pointer so that offset-wise, it looks like a sequential string. 3481 // Move the pointer so that offset-wise, it looks like a sequential string.
4000 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 3482 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
4001 __ subq(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 3483 __ subq(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
4002 3484
4003 __ bind(&sequential_string); 3485 __ bind(&sequential_string);
4004 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); 3486 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0);
4005 __ testb(rbx, Immediate(kStringEncodingMask)); 3487 __ testb(rbx, Immediate(kStringEncodingMask));
4006 __ j(zero, &two_byte_sequential); 3488 __ j(zero, &two_byte_sequential);
4007 3489
4008 // Allocate the result. 3490 // Allocate the result.
4009 __ AllocateAsciiString(rax, rcx, r11, r14, r15, &runtime); 3491 __ AllocateAsciiString(rax, rcx, r11, r14, r15, &runtime);
4010 3492
4011 // rax: result string 3493 // rax: result string
4012 // rcx: result string length 3494 // rcx: result string length
4013 __ movq(r14, rsi); // esi used by following code. 3495 __ movp(r14, rsi); // esi used by following code.
4014 { // Locate character of sub string start. 3496 { // Locate character of sub string start.
4015 SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_1); 3497 SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_1);
4016 __ lea(rsi, Operand(rdi, smi_as_index.reg, smi_as_index.scale, 3498 __ lea(rsi, Operand(rdi, smi_as_index.reg, smi_as_index.scale,
4017 SeqOneByteString::kHeaderSize - kHeapObjectTag)); 3499 SeqOneByteString::kHeaderSize - kHeapObjectTag));
4018 } 3500 }
4019 // Locate first character of result. 3501 // Locate first character of result.
4020 __ lea(rdi, FieldOperand(rax, SeqOneByteString::kHeaderSize)); 3502 __ lea(rdi, FieldOperand(rax, SeqOneByteString::kHeaderSize));
4021 3503
4022 // rax: result string 3504 // rax: result string
4023 // rcx: result length 3505 // rcx: result length
4024 // rdi: first character of result 3506 // rdi: first character of result
4025 // rsi: character of sub string start 3507 // rsi: character of sub string start
4026 // r14: original value of rsi 3508 // r14: original value of rsi
4027 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true); 3509 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true);
4028 __ movq(rsi, r14); // Restore rsi. 3510 __ movp(rsi, r14); // Restore rsi.
4029 __ IncrementCounter(counters->sub_string_native(), 1); 3511 __ IncrementCounter(counters->sub_string_native(), 1);
4030 __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize); 3512 __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize);
4031 3513
4032 __ bind(&two_byte_sequential); 3514 __ bind(&two_byte_sequential);
4033 // Allocate the result. 3515 // Allocate the result.
4034 __ AllocateTwoByteString(rax, rcx, r11, r14, r15, &runtime); 3516 __ AllocateTwoByteString(rax, rcx, r11, r14, r15, &runtime);
4035 3517
4036 // rax: result string 3518 // rax: result string
4037 // rcx: result string length 3519 // rcx: result string length
4038 __ movq(r14, rsi); // esi used by following code. 3520 __ movp(r14, rsi); // esi used by following code.
4039 { // Locate character of sub string start. 3521 { // Locate character of sub string start.
4040 SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_2); 3522 SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_2);
4041 __ lea(rsi, Operand(rdi, smi_as_index.reg, smi_as_index.scale, 3523 __ lea(rsi, Operand(rdi, smi_as_index.reg, smi_as_index.scale,
4042 SeqOneByteString::kHeaderSize - kHeapObjectTag)); 3524 SeqOneByteString::kHeaderSize - kHeapObjectTag));
4043 } 3525 }
4044 // Locate first character of result. 3526 // Locate first character of result.
4045 __ lea(rdi, FieldOperand(rax, SeqTwoByteString::kHeaderSize)); 3527 __ lea(rdi, FieldOperand(rax, SeqTwoByteString::kHeaderSize));
4046 3528
4047 // rax: result string 3529 // rax: result string
4048 // rcx: result length 3530 // rcx: result length
4049 // rdi: first character of result 3531 // rdi: first character of result
4050 // rsi: character of sub string start 3532 // rsi: character of sub string start
4051 // r14: original value of rsi 3533 // r14: original value of rsi
4052 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false); 3534 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false);
4053 __ movq(rsi, r14); // Restore esi. 3535 __ movp(rsi, r14); // Restore esi.
4054 __ IncrementCounter(counters->sub_string_native(), 1); 3536 __ IncrementCounter(counters->sub_string_native(), 1);
4055 __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize); 3537 __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize);
4056 3538
4057 // Just jump to runtime to create the sub string. 3539 // Just jump to runtime to create the sub string.
4058 __ bind(&runtime); 3540 __ bind(&runtime);
4059 __ TailCallRuntime(Runtime::kSubString, 3, 1); 3541 __ TailCallRuntime(Runtime::kSubString, 3, 1);
4060 3542
4061 __ bind(&single_char); 3543 __ bind(&single_char);
4062 // rax: string 3544 // rax: string
4063 // rbx: instance type 3545 // rbx: instance type
4064 // rcx: sub string length (smi) 3546 // rcx: sub string length (smi)
4065 // rdx: from index (smi) 3547 // rdx: from index (smi)
4066 StringCharAtGenerator generator( 3548 StringCharAtGenerator generator(
4067 rax, rdx, rcx, rax, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); 3549 rax, rdx, rcx, rax, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER);
4068 generator.GenerateFast(masm); 3550 generator.GenerateFast(masm);
4069 __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize); 3551 __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize);
4070 generator.SkipSlow(masm, &runtime); 3552 generator.SkipSlow(masm, &runtime);
4071 } 3553 }
4072 3554
4073 3555
4074 void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm, 3556 void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm,
4075 Register left, 3557 Register left,
4076 Register right, 3558 Register right,
4077 Register scratch1, 3559 Register scratch1,
4078 Register scratch2) { 3560 Register scratch2) {
4079 Register length = scratch1; 3561 Register length = scratch1;
4080 3562
4081 // Compare lengths. 3563 // Compare lengths.
4082 Label check_zero_length; 3564 Label check_zero_length;
4083 __ movq(length, FieldOperand(left, String::kLengthOffset)); 3565 __ movp(length, FieldOperand(left, String::kLengthOffset));
4084 __ SmiCompare(length, FieldOperand(right, String::kLengthOffset)); 3566 __ SmiCompare(length, FieldOperand(right, String::kLengthOffset));
4085 __ j(equal, &check_zero_length, Label::kNear); 3567 __ j(equal, &check_zero_length, Label::kNear);
4086 __ Move(rax, Smi::FromInt(NOT_EQUAL)); 3568 __ Move(rax, Smi::FromInt(NOT_EQUAL));
4087 __ ret(0); 3569 __ ret(0);
4088 3570
4089 // Check if the length is zero. 3571 // Check if the length is zero.
4090 Label compare_chars; 3572 Label compare_chars;
4091 __ bind(&check_zero_length); 3573 __ bind(&check_zero_length);
4092 STATIC_ASSERT(kSmiTag == 0); 3574 STATIC_ASSERT(kSmiTag == 0);
4093 __ SmiTest(length); 3575 __ SmiTest(length);
(...skipping 23 matching lines...) Expand all
4117 Register right, 3599 Register right,
4118 Register scratch1, 3600 Register scratch1,
4119 Register scratch2, 3601 Register scratch2,
4120 Register scratch3, 3602 Register scratch3,
4121 Register scratch4) { 3603 Register scratch4) {
4122 // Ensure that you can always subtract a string length from a non-negative 3604 // Ensure that you can always subtract a string length from a non-negative
4123 // number (e.g. another length). 3605 // number (e.g. another length).
4124 STATIC_ASSERT(String::kMaxLength < 0x7fffffff); 3606 STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
4125 3607
4126 // Find minimum length and length difference. 3608 // Find minimum length and length difference.
4127 __ movq(scratch1, FieldOperand(left, String::kLengthOffset)); 3609 __ movp(scratch1, FieldOperand(left, String::kLengthOffset));
4128 __ movq(scratch4, scratch1); 3610 __ movp(scratch4, scratch1);
4129 __ SmiSub(scratch4, 3611 __ SmiSub(scratch4,
4130 scratch4, 3612 scratch4,
4131 FieldOperand(right, String::kLengthOffset)); 3613 FieldOperand(right, String::kLengthOffset));
4132 // Register scratch4 now holds left.length - right.length. 3614 // Register scratch4 now holds left.length - right.length.
4133 const Register length_difference = scratch4; 3615 const Register length_difference = scratch4;
4134 Label left_shorter; 3616 Label left_shorter;
4135 __ j(less, &left_shorter, Label::kNear); 3617 __ j(less, &left_shorter, Label::kNear);
4136 // The right string isn't longer that the left one. 3618 // The right string isn't longer that the left one.
4137 // Get the right string's length by subtracting the (non-negative) difference 3619 // Get the right string's length by subtracting the (non-negative) difference
4138 // from the left string's length. 3620 // from the left string's length.
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
4218 3700
4219 void StringCompareStub::Generate(MacroAssembler* masm) { 3701 void StringCompareStub::Generate(MacroAssembler* masm) {
4220 Label runtime; 3702 Label runtime;
4221 3703
4222 // Stack frame on entry. 3704 // Stack frame on entry.
4223 // rsp[0] : return address 3705 // rsp[0] : return address
4224 // rsp[8] : right string 3706 // rsp[8] : right string
4225 // rsp[16] : left string 3707 // rsp[16] : left string
4226 3708
4227 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER); 3709 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER);
4228 __ movq(rdx, args.GetArgumentOperand(0)); // left 3710 __ movp(rdx, args.GetArgumentOperand(0)); // left
4229 __ movq(rax, args.GetArgumentOperand(1)); // right 3711 __ movp(rax, args.GetArgumentOperand(1)); // right
4230 3712
4231 // Check for identity. 3713 // Check for identity.
4232 Label not_same; 3714 Label not_same;
4233 __ cmpq(rdx, rax); 3715 __ cmpq(rdx, rax);
4234 __ j(not_equal, &not_same, Label::kNear); 3716 __ j(not_equal, &not_same, Label::kNear);
4235 __ Move(rax, Smi::FromInt(EQUAL)); 3717 __ Move(rax, Smi::FromInt(EQUAL));
4236 Counters* counters = masm->isolate()->counters(); 3718 Counters* counters = masm->isolate()->counters();
4237 __ IncrementCounter(counters->string_compare_native(), 1); 3719 __ IncrementCounter(counters->string_compare_native(), 1);
4238 __ ret(2 * kPointerSize); 3720 __ ret(2 * kPointerSize);
4239 3721
(...skipping 10 matching lines...) Expand all
4250 __ PushReturnAddressFrom(rcx); 3732 __ PushReturnAddressFrom(rcx);
4251 GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8); 3733 GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8);
4252 3734
4253 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 3735 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
4254 // tagged as a small integer. 3736 // tagged as a small integer.
4255 __ bind(&runtime); 3737 __ bind(&runtime);
4256 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 3738 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
4257 } 3739 }
4258 3740
4259 3741
3742 void ArrayPushStub::Generate(MacroAssembler* masm) {
3743 int argc = arguments_count();
3744
3745 StackArgumentsAccessor args(rsp, argc);
3746 if (argc == 0) {
3747 // Noop, return the length.
3748 __ movp(rax, FieldOperand(rdx, JSArray::kLengthOffset));
3749 __ ret((argc + 1) * kPointerSize);
3750 return;
3751 }
3752
3753 Isolate* isolate = masm->isolate();
3754
3755 if (argc != 1) {
3756 __ TailCallExternalReference(
3757 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
3758 return;
3759 }
3760
3761 Label call_builtin, attempt_to_grow_elements, with_write_barrier;
3762
3763 // Get the elements array of the object.
3764 __ movp(rdi, FieldOperand(rdx, JSArray::kElementsOffset));
3765
3766 if (IsFastSmiOrObjectElementsKind(elements_kind())) {
3767 // Check that the elements are in fast mode and writable.
3768 __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
3769 isolate->factory()->fixed_array_map());
3770 __ j(not_equal, &call_builtin);
3771 }
3772
3773 // Get the array's length into rax and calculate new length.
3774 __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset));
3775 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue);
3776 __ addl(rax, Immediate(argc));
3777
3778 // Get the elements' length into rcx.
3779 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
3780
3781 // Check if we could survive without allocation.
3782 __ cmpl(rax, rcx);
3783
3784 if (IsFastSmiOrObjectElementsKind(elements_kind())) {
3785 __ j(greater, &attempt_to_grow_elements);
3786
3787 // Check if value is a smi.
3788 __ movp(rcx, args.GetArgumentOperand(1));
3789 __ JumpIfNotSmi(rcx, &with_write_barrier);
3790
3791 // Store the value.
3792 __ movp(FieldOperand(rdi,
3793 rax,
3794 times_pointer_size,
3795 FixedArray::kHeaderSize - argc * kPointerSize),
3796 rcx);
3797 } else {
3798 __ j(greater, &call_builtin);
3799
3800 __ movp(rcx, args.GetArgumentOperand(1));
3801 __ StoreNumberToDoubleElements(
3802 rcx, rdi, rax, xmm0, &call_builtin, argc * kDoubleSize);
3803 }
3804
3805 // Save new length.
3806 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
3807
3808 __ Integer32ToSmi(rax, rax); // Return new length as smi.
3809 __ ret((argc + 1) * kPointerSize);
3810
3811 if (IsFastDoubleElementsKind(elements_kind())) {
3812 __ bind(&call_builtin);
3813 __ TailCallExternalReference(
3814 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
3815 return;
3816 }
3817
3818 __ bind(&with_write_barrier);
3819
3820 if (IsFastSmiElementsKind(elements_kind())) {
3821 if (FLAG_trace_elements_transitions) __ jmp(&call_builtin);
3822
3823 __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset),
3824 isolate->factory()->heap_number_map());
3825 __ j(equal, &call_builtin);
3826
3827 ElementsKind target_kind = IsHoleyElementsKind(elements_kind())
3828 ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS;
3829 __ movp(rbx, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX));
3830 __ movp(rbx, FieldOperand(rbx, GlobalObject::kNativeContextOffset));
3831 __ movp(rbx, ContextOperand(rbx, Context::JS_ARRAY_MAPS_INDEX));
3832 const int header_size = FixedArrayBase::kHeaderSize;
3833 // Verify that the object can be transitioned in place.
3834 const int origin_offset = header_size + elements_kind() * kPointerSize;
3835 __ movp(rdi, FieldOperand(rbx, origin_offset));
3836 __ cmpq(rdi, FieldOperand(rdx, HeapObject::kMapOffset));
3837 __ j(not_equal, &call_builtin);
3838
3839 const int target_offset = header_size + target_kind * kPointerSize;
3840 __ movp(rbx, FieldOperand(rbx, target_offset));
3841 ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
3842 masm, DONT_TRACK_ALLOCATION_SITE, NULL);
3843 __ movp(rdi, FieldOperand(rdx, JSArray::kElementsOffset));
3844 }
3845
3846 // Save new length.
3847 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
3848
3849 // Store the value.
3850 __ lea(rdx, FieldOperand(rdi,
3851 rax, times_pointer_size,
3852 FixedArray::kHeaderSize - argc * kPointerSize));
3853 __ movp(Operand(rdx, 0), rcx);
3854
3855 __ RecordWrite(rdi, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
3856 OMIT_SMI_CHECK);
3857
3858 __ Integer32ToSmi(rax, rax); // Return new length as smi.
3859 __ ret((argc + 1) * kPointerSize);
3860
3861 __ bind(&attempt_to_grow_elements);
3862 if (!FLAG_inline_new) {
3863 __ bind(&call_builtin);
3864 __ TailCallExternalReference(
3865 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
3866 return;
3867 }
3868
3869 __ movp(rbx, args.GetArgumentOperand(1));
3870 // Growing elements that are SMI-only requires special handling in case the
3871 // new element is non-Smi. For now, delegate to the builtin.
3872 Label no_fast_elements_check;
3873 __ JumpIfSmi(rbx, &no_fast_elements_check);
3874 __ movp(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
3875 __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar);
3876 __ bind(&no_fast_elements_check);
3877
3878 ExternalReference new_space_allocation_top =
3879 ExternalReference::new_space_allocation_top_address(isolate);
3880 ExternalReference new_space_allocation_limit =
3881 ExternalReference::new_space_allocation_limit_address(isolate);
3882
3883 const int kAllocationDelta = 4;
3884 ASSERT(kAllocationDelta >= argc);
3885 // Load top.
3886 __ Load(rcx, new_space_allocation_top);
3887
3888 // Check if it's the end of elements.
3889 __ lea(rdx, FieldOperand(rdi,
3890 rax, times_pointer_size,
3891 FixedArray::kHeaderSize - argc * kPointerSize));
3892 __ cmpq(rdx, rcx);
3893 __ j(not_equal, &call_builtin);
3894 __ addq(rcx, Immediate(kAllocationDelta * kPointerSize));
3895 Operand limit_operand = masm->ExternalOperand(new_space_allocation_limit);
3896 __ cmpq(rcx, limit_operand);
3897 __ j(above, &call_builtin);
3898
3899 // We fit and could grow elements.
3900 __ Store(new_space_allocation_top, rcx);
3901
3902 // Push the argument...
3903 __ movp(Operand(rdx, 0), rbx);
3904 // ... and fill the rest with holes.
3905 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
3906 for (int i = 1; i < kAllocationDelta; i++) {
3907 __ movp(Operand(rdx, i * kPointerSize), kScratchRegister);
3908 }
3909
3910 if (IsFastObjectElementsKind(elements_kind())) {
3911 // We know the elements array is in new space so we don't need the
3912 // remembered set, but we just pushed a value onto it so we may have to tell
3913 // the incremental marker to rescan the object that we just grew. We don't
3914 // need to worry about the holes because they are in old space and already
3915 // marked black.
3916 __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
3917 }
3918
3919 // Restore receiver to rdx as finish sequence assumes it's here.
3920 __ movp(rdx, args.GetReceiverOperand());
3921
3922 // Increment element's and array's sizes.
3923 __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset),
3924 Smi::FromInt(kAllocationDelta));
3925
3926 // Make new length a smi before returning it.
3927 __ Integer32ToSmi(rax, rax);
3928 __ movp(FieldOperand(rdx, JSArray::kLengthOffset), rax);
3929
3930 __ ret((argc + 1) * kPointerSize);
3931
3932 __ bind(&call_builtin);
3933 __ TailCallExternalReference(
3934 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
3935 }
3936
3937
4260 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { 3938 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) {
4261 // ----------- S t a t e ------------- 3939 // ----------- S t a t e -------------
4262 // -- rdx : left 3940 // -- rdx : left
4263 // -- rax : right 3941 // -- rax : right
4264 // -- rsp[0] : return address 3942 // -- rsp[0] : return address
4265 // ----------------------------------- 3943 // -----------------------------------
4266 Isolate* isolate = masm->isolate(); 3944 Isolate* isolate = masm->isolate();
4267 3945
4268 // Load rcx with the allocation site. We stick an undefined dummy value here 3946 // Load rcx with the allocation site. We stick an undefined dummy value here
4269 // and replace it with the real allocation site later when we instantiate this 3947 // and replace it with the real allocation site later when we instantiate this
(...skipping 24 matching lines...) Expand all
4294 if (GetCondition() == equal) { 3972 if (GetCondition() == equal) {
4295 // For equality we do not care about the sign of the result. 3973 // For equality we do not care about the sign of the result.
4296 __ subq(rax, rdx); 3974 __ subq(rax, rdx);
4297 } else { 3975 } else {
4298 Label done; 3976 Label done;
4299 __ subq(rdx, rax); 3977 __ subq(rdx, rax);
4300 __ j(no_overflow, &done, Label::kNear); 3978 __ j(no_overflow, &done, Label::kNear);
4301 // Correct sign of result in case of overflow. 3979 // Correct sign of result in case of overflow.
4302 __ not_(rdx); 3980 __ not_(rdx);
4303 __ bind(&done); 3981 __ bind(&done);
4304 __ movq(rax, rdx); 3982 __ movp(rax, rdx);
4305 } 3983 }
4306 __ ret(0); 3984 __ ret(0);
4307 3985
4308 __ bind(&miss); 3986 __ bind(&miss);
4309 GenerateMiss(masm); 3987 GenerateMiss(masm);
4310 } 3988 }
4311 3989
4312 3990
4313 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { 3991 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) {
4314 ASSERT(state_ == CompareIC::NUMBER); 3992 ASSERT(state_ == CompareIC::NUMBER);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
4396 Register right = rax; 4074 Register right = rax;
4397 Register tmp1 = rcx; 4075 Register tmp1 = rcx;
4398 Register tmp2 = rbx; 4076 Register tmp2 = rbx;
4399 4077
4400 // Check that both operands are heap objects. 4078 // Check that both operands are heap objects.
4401 Label miss; 4079 Label miss;
4402 Condition cond = masm->CheckEitherSmi(left, right, tmp1); 4080 Condition cond = masm->CheckEitherSmi(left, right, tmp1);
4403 __ j(cond, &miss, Label::kNear); 4081 __ j(cond, &miss, Label::kNear);
4404 4082
4405 // Check that both operands are internalized strings. 4083 // Check that both operands are internalized strings.
4406 __ movq(tmp1, FieldOperand(left, HeapObject::kMapOffset)); 4084 __ movp(tmp1, FieldOperand(left, HeapObject::kMapOffset));
4407 __ movq(tmp2, FieldOperand(right, HeapObject::kMapOffset)); 4085 __ movp(tmp2, FieldOperand(right, HeapObject::kMapOffset));
4408 __ movzxbq(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); 4086 __ movzxbq(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
4409 __ movzxbq(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); 4087 __ movzxbq(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
4410 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 4088 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
4411 __ or_(tmp1, tmp2); 4089 __ or_(tmp1, tmp2);
4412 __ testb(tmp1, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); 4090 __ testb(tmp1, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
4413 __ j(not_zero, &miss, Label::kNear); 4091 __ j(not_zero, &miss, Label::kNear);
4414 4092
4415 // Internalized strings are compared by identity. 4093 // Internalized strings are compared by identity.
4416 Label done; 4094 Label done;
4417 __ cmpq(left, right); 4095 __ cmpq(left, right);
(...skipping 22 matching lines...) Expand all
4440 Register tmp1 = rcx; 4118 Register tmp1 = rcx;
4441 Register tmp2 = rbx; 4119 Register tmp2 = rbx;
4442 4120
4443 // Check that both operands are heap objects. 4121 // Check that both operands are heap objects.
4444 Label miss; 4122 Label miss;
4445 Condition cond = masm->CheckEitherSmi(left, right, tmp1); 4123 Condition cond = masm->CheckEitherSmi(left, right, tmp1);
4446 __ j(cond, &miss, Label::kNear); 4124 __ j(cond, &miss, Label::kNear);
4447 4125
4448 // Check that both operands are unique names. This leaves the instance 4126 // Check that both operands are unique names. This leaves the instance
4449 // types loaded in tmp1 and tmp2. 4127 // types loaded in tmp1 and tmp2.
4450 __ movq(tmp1, FieldOperand(left, HeapObject::kMapOffset)); 4128 __ movp(tmp1, FieldOperand(left, HeapObject::kMapOffset));
4451 __ movq(tmp2, FieldOperand(right, HeapObject::kMapOffset)); 4129 __ movp(tmp2, FieldOperand(right, HeapObject::kMapOffset));
4452 __ movzxbq(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); 4130 __ movzxbq(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
4453 __ movzxbq(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); 4131 __ movzxbq(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
4454 4132
4455 __ JumpIfNotUniqueName(tmp1, &miss, Label::kNear); 4133 __ JumpIfNotUniqueName(tmp1, &miss, Label::kNear);
4456 __ JumpIfNotUniqueName(tmp2, &miss, Label::kNear); 4134 __ JumpIfNotUniqueName(tmp2, &miss, Label::kNear);
4457 4135
4458 // Unique names are compared by identity. 4136 // Unique names are compared by identity.
4459 Label done; 4137 Label done;
4460 __ cmpq(left, right); 4138 __ cmpq(left, right);
4461 // Make sure rax is non-zero. At this point input operands are 4139 // Make sure rax is non-zero. At this point input operands are
(...skipping 23 matching lines...) Expand all
4485 Register tmp1 = rcx; 4163 Register tmp1 = rcx;
4486 Register tmp2 = rbx; 4164 Register tmp2 = rbx;
4487 Register tmp3 = rdi; 4165 Register tmp3 = rdi;
4488 4166
4489 // Check that both operands are heap objects. 4167 // Check that both operands are heap objects.
4490 Condition cond = masm->CheckEitherSmi(left, right, tmp1); 4168 Condition cond = masm->CheckEitherSmi(left, right, tmp1);
4491 __ j(cond, &miss); 4169 __ j(cond, &miss);
4492 4170
4493 // Check that both operands are strings. This leaves the instance 4171 // Check that both operands are strings. This leaves the instance
4494 // types loaded in tmp1 and tmp2. 4172 // types loaded in tmp1 and tmp2.
4495 __ movq(tmp1, FieldOperand(left, HeapObject::kMapOffset)); 4173 __ movp(tmp1, FieldOperand(left, HeapObject::kMapOffset));
4496 __ movq(tmp2, FieldOperand(right, HeapObject::kMapOffset)); 4174 __ movp(tmp2, FieldOperand(right, HeapObject::kMapOffset));
4497 __ movzxbq(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); 4175 __ movzxbq(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
4498 __ movzxbq(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); 4176 __ movzxbq(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
4499 __ movq(tmp3, tmp1); 4177 __ movp(tmp3, tmp1);
4500 STATIC_ASSERT(kNotStringTag != 0); 4178 STATIC_ASSERT(kNotStringTag != 0);
4501 __ or_(tmp3, tmp2); 4179 __ or_(tmp3, tmp2);
4502 __ testb(tmp3, Immediate(kIsNotStringMask)); 4180 __ testb(tmp3, Immediate(kIsNotStringMask));
4503 __ j(not_zero, &miss); 4181 __ j(not_zero, &miss);
4504 4182
4505 // Fast check for identical strings. 4183 // Fast check for identical strings.
4506 Label not_same; 4184 Label not_same;
4507 __ cmpq(left, right); 4185 __ cmpq(left, right);
4508 __ j(not_equal, &not_same, Label::kNear); 4186 __ j(not_equal, &not_same, Label::kNear);
4509 STATIC_ASSERT(EQUAL == 0); 4187 STATIC_ASSERT(EQUAL == 0);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
4578 __ bind(&miss); 4256 __ bind(&miss);
4579 GenerateMiss(masm); 4257 GenerateMiss(masm);
4580 } 4258 }
4581 4259
4582 4260
4583 void ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) { 4261 void ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) {
4584 Label miss; 4262 Label miss;
4585 Condition either_smi = masm->CheckEitherSmi(rdx, rax); 4263 Condition either_smi = masm->CheckEitherSmi(rdx, rax);
4586 __ j(either_smi, &miss, Label::kNear); 4264 __ j(either_smi, &miss, Label::kNear);
4587 4265
4588 __ movq(rcx, FieldOperand(rax, HeapObject::kMapOffset)); 4266 __ movp(rcx, FieldOperand(rax, HeapObject::kMapOffset));
4589 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); 4267 __ movp(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
4590 __ Cmp(rcx, known_map_); 4268 __ Cmp(rcx, known_map_);
4591 __ j(not_equal, &miss, Label::kNear); 4269 __ j(not_equal, &miss, Label::kNear);
4592 __ Cmp(rbx, known_map_); 4270 __ Cmp(rbx, known_map_);
4593 __ j(not_equal, &miss, Label::kNear); 4271 __ j(not_equal, &miss, Label::kNear);
4594 4272
4595 __ subq(rax, rdx); 4273 __ subq(rax, rdx);
4596 __ ret(0); 4274 __ ret(0);
4597 4275
4598 __ bind(&miss); 4276 __ bind(&miss);
4599 GenerateMiss(masm); 4277 GenerateMiss(masm);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
4647 __ and_(index, 4325 __ and_(index,
4648 Immediate(name->Hash() + NameDictionary::GetProbeOffset(i))); 4326 Immediate(name->Hash() + NameDictionary::GetProbeOffset(i)));
4649 4327
4650 // Scale the index by multiplying by the entry size. 4328 // Scale the index by multiplying by the entry size.
4651 ASSERT(NameDictionary::kEntrySize == 3); 4329 ASSERT(NameDictionary::kEntrySize == 3);
4652 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3. 4330 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3.
4653 4331
4654 Register entity_name = r0; 4332 Register entity_name = r0;
4655 // Having undefined at this place means the name is not contained. 4333 // Having undefined at this place means the name is not contained.
4656 ASSERT_EQ(kSmiTagSize, 1); 4334 ASSERT_EQ(kSmiTagSize, 1);
4657 __ movq(entity_name, Operand(properties, 4335 __ movp(entity_name, Operand(properties,
4658 index, 4336 index,
4659 times_pointer_size, 4337 times_pointer_size,
4660 kElementsStartOffset - kHeapObjectTag)); 4338 kElementsStartOffset - kHeapObjectTag));
4661 __ Cmp(entity_name, masm->isolate()->factory()->undefined_value()); 4339 __ Cmp(entity_name, masm->isolate()->factory()->undefined_value());
4662 __ j(equal, done); 4340 __ j(equal, done);
4663 4341
4664 // Stop if found the property. 4342 // Stop if found the property.
4665 __ Cmp(entity_name, Handle<Name>(name)); 4343 __ Cmp(entity_name, Handle<Name>(name));
4666 __ j(equal, miss); 4344 __ j(equal, miss);
4667 4345
4668 Label good; 4346 Label good;
4669 // Check for the hole and skip. 4347 // Check for the hole and skip.
4670 __ CompareRoot(entity_name, Heap::kTheHoleValueRootIndex); 4348 __ CompareRoot(entity_name, Heap::kTheHoleValueRootIndex);
4671 __ j(equal, &good, Label::kNear); 4349 __ j(equal, &good, Label::kNear);
4672 4350
4673 // Check if the entry name is not a unique name. 4351 // Check if the entry name is not a unique name.
4674 __ movq(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset)); 4352 __ movp(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
4675 __ JumpIfNotUniqueName(FieldOperand(entity_name, Map::kInstanceTypeOffset), 4353 __ JumpIfNotUniqueName(FieldOperand(entity_name, Map::kInstanceTypeOffset),
4676 miss); 4354 miss);
4677 __ bind(&good); 4355 __ bind(&good);
4678 } 4356 }
4679 4357
4680 NameDictionaryLookupStub stub(properties, r0, r0, NEGATIVE_LOOKUP); 4358 NameDictionaryLookupStub stub(properties, r0, r0, NEGATIVE_LOOKUP);
4681 __ Push(Handle<Object>(name)); 4359 __ Push(Handle<Object>(name));
4682 __ push(Immediate(name->Hash())); 4360 __ push(Immediate(name->Hash()));
4683 __ CallStub(&stub); 4361 __ CallStub(&stub);
4684 __ testq(r0, r0); 4362 __ testq(r0, r0);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
4765 4443
4766 // If names of slots in range from 1 to kProbes - 1 for the hash value are 4444 // If names of slots in range from 1 to kProbes - 1 for the hash value are
4767 // not equal to the name and kProbes-th slot is not used (its name is the 4445 // not equal to the name and kProbes-th slot is not used (its name is the
4768 // undefined value), it guarantees the hash table doesn't contain the 4446 // undefined value), it guarantees the hash table doesn't contain the
4769 // property. It's true even if some slots represent deleted properties 4447 // property. It's true even if some slots represent deleted properties
4770 // (their names are the null value). 4448 // (their names are the null value).
4771 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER, 4449 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER,
4772 kPointerSize); 4450 kPointerSize);
4773 for (int i = kInlinedProbes; i < kTotalProbes; i++) { 4451 for (int i = kInlinedProbes; i < kTotalProbes; i++) {
4774 // Compute the masked index: (hash + i + i * i) & mask. 4452 // Compute the masked index: (hash + i + i * i) & mask.
4775 __ movq(scratch, args.GetArgumentOperand(1)); 4453 __ movp(scratch, args.GetArgumentOperand(1));
4776 if (i > 0) { 4454 if (i > 0) {
4777 __ addl(scratch, Immediate(NameDictionary::GetProbeOffset(i))); 4455 __ addl(scratch, Immediate(NameDictionary::GetProbeOffset(i)));
4778 } 4456 }
4779 __ and_(scratch, Operand(rsp, 0)); 4457 __ and_(scratch, Operand(rsp, 0));
4780 4458
4781 // Scale the index by multiplying by the entry size. 4459 // Scale the index by multiplying by the entry size.
4782 ASSERT(NameDictionary::kEntrySize == 3); 4460 ASSERT(NameDictionary::kEntrySize == 3);
4783 __ lea(index_, Operand(scratch, scratch, times_2, 0)); // index *= 3. 4461 __ lea(index_, Operand(scratch, scratch, times_2, 0)); // index *= 3.
4784 4462
4785 // Having undefined at this place means the name is not contained. 4463 // Having undefined at this place means the name is not contained.
4786 __ movq(scratch, Operand(dictionary_, 4464 __ movp(scratch, Operand(dictionary_,
4787 index_, 4465 index_,
4788 times_pointer_size, 4466 times_pointer_size,
4789 kElementsStartOffset - kHeapObjectTag)); 4467 kElementsStartOffset - kHeapObjectTag));
4790 4468
4791 __ Cmp(scratch, masm->isolate()->factory()->undefined_value()); 4469 __ Cmp(scratch, masm->isolate()->factory()->undefined_value());
4792 __ j(equal, &not_in_dictionary); 4470 __ j(equal, &not_in_dictionary);
4793 4471
4794 // Stop if found the property. 4472 // Stop if found the property.
4795 __ cmpq(scratch, args.GetArgumentOperand(0)); 4473 __ cmpq(scratch, args.GetArgumentOperand(0));
4796 __ j(equal, &in_dictionary); 4474 __ j(equal, &in_dictionary);
4797 4475
4798 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { 4476 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
4799 // If we hit a key that is not a unique name during negative 4477 // If we hit a key that is not a unique name during negative
4800 // lookup we have to bailout as this key might be equal to the 4478 // lookup we have to bailout as this key might be equal to the
4801 // key we are looking for. 4479 // key we are looking for.
4802 4480
4803 // Check if the entry name is not a unique name. 4481 // Check if the entry name is not a unique name.
4804 __ movq(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); 4482 __ movp(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
4805 __ JumpIfNotUniqueName(FieldOperand(scratch, Map::kInstanceTypeOffset), 4483 __ JumpIfNotUniqueName(FieldOperand(scratch, Map::kInstanceTypeOffset),
4806 &maybe_in_dictionary); 4484 &maybe_in_dictionary);
4807 } 4485 }
4808 } 4486 }
4809 4487
4810 __ bind(&maybe_in_dictionary); 4488 __ bind(&maybe_in_dictionary);
4811 // If we are doing negative lookup then probing failure should be 4489 // If we are doing negative lookup then probing failure should be
4812 // treated as a lookup success. For positive lookup probing failure 4490 // treated as a lookup success. For positive lookup probing failure
4813 // should be treated as lookup failure. 4491 // should be treated as lookup failure.
4814 if (mode_ == POSITIVE_LOOKUP) { 4492 if (mode_ == POSITIVE_LOOKUP) {
4815 __ movq(scratch, Immediate(0)); 4493 __ movp(scratch, Immediate(0));
4816 __ Drop(1); 4494 __ Drop(1);
4817 __ ret(2 * kPointerSize); 4495 __ ret(2 * kPointerSize);
4818 } 4496 }
4819 4497
4820 __ bind(&in_dictionary); 4498 __ bind(&in_dictionary);
4821 __ movq(scratch, Immediate(1)); 4499 __ movp(scratch, Immediate(1));
4822 __ Drop(1); 4500 __ Drop(1);
4823 __ ret(2 * kPointerSize); 4501 __ ret(2 * kPointerSize);
4824 4502
4825 __ bind(&not_in_dictionary); 4503 __ bind(&not_in_dictionary);
4826 __ movq(scratch, Immediate(0)); 4504 __ movp(scratch, Immediate(0));
4827 __ Drop(1); 4505 __ Drop(1);
4828 __ ret(2 * kPointerSize); 4506 __ ret(2 * kPointerSize);
4829 } 4507 }
4830 4508
4831 4509
4832 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( 4510 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(
4833 Isolate* isolate) { 4511 Isolate* isolate) {
4834 StoreBufferOverflowStub stub1(kDontSaveFPRegs); 4512 StoreBufferOverflowStub stub1(kDontSaveFPRegs);
4835 stub1.GetCode(isolate); 4513 stub1.GetCode(isolate);
4836 StoreBufferOverflowStub stub2(kSaveFPRegs); 4514 StoreBufferOverflowStub stub2(kSaveFPRegs);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
4881 masm->set_byte_at(2, kFiveByteNopInstruction); 4559 masm->set_byte_at(2, kFiveByteNopInstruction);
4882 } 4560 }
4883 4561
4884 4562
4885 void RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) { 4563 void RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) {
4886 regs_.Save(masm); 4564 regs_.Save(masm);
4887 4565
4888 if (remembered_set_action_ == EMIT_REMEMBERED_SET) { 4566 if (remembered_set_action_ == EMIT_REMEMBERED_SET) {
4889 Label dont_need_remembered_set; 4567 Label dont_need_remembered_set;
4890 4568
4891 __ movq(regs_.scratch0(), Operand(regs_.address(), 0)); 4569 __ movp(regs_.scratch0(), Operand(regs_.address(), 0));
4892 __ JumpIfNotInNewSpace(regs_.scratch0(), 4570 __ JumpIfNotInNewSpace(regs_.scratch0(),
4893 regs_.scratch0(), 4571 regs_.scratch0(),
4894 &dont_need_remembered_set); 4572 &dont_need_remembered_set);
4895 4573
4896 __ CheckPageFlag(regs_.object(), 4574 __ CheckPageFlag(regs_.object(),
4897 regs_.scratch0(), 4575 regs_.scratch0(),
4898 1 << MemoryChunk::SCAN_ON_SCAVENGE, 4576 1 << MemoryChunk::SCAN_ON_SCAVENGE,
4899 not_zero, 4577 not_zero,
4900 &dont_need_remembered_set); 4578 &dont_need_remembered_set);
4901 4579
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
4955 4633
4956 4634
4957 void RecordWriteStub::CheckNeedsToInformIncrementalMarker( 4635 void RecordWriteStub::CheckNeedsToInformIncrementalMarker(
4958 MacroAssembler* masm, 4636 MacroAssembler* masm,
4959 OnNoNeedToInformIncrementalMarker on_no_need, 4637 OnNoNeedToInformIncrementalMarker on_no_need,
4960 Mode mode) { 4638 Mode mode) {
4961 Label on_black; 4639 Label on_black;
4962 Label need_incremental; 4640 Label need_incremental;
4963 Label need_incremental_pop_object; 4641 Label need_incremental_pop_object;
4964 4642
4965 __ movq(regs_.scratch0(), Immediate(~Page::kPageAlignmentMask)); 4643 __ movp(regs_.scratch0(), Immediate(~Page::kPageAlignmentMask));
4966 __ and_(regs_.scratch0(), regs_.object()); 4644 __ and_(regs_.scratch0(), regs_.object());
4967 __ movq(regs_.scratch1(), 4645 __ movp(regs_.scratch1(),
4968 Operand(regs_.scratch0(), 4646 Operand(regs_.scratch0(),
4969 MemoryChunk::kWriteBarrierCounterOffset)); 4647 MemoryChunk::kWriteBarrierCounterOffset));
4970 __ subq(regs_.scratch1(), Immediate(1)); 4648 __ subq(regs_.scratch1(), Immediate(1));
4971 __ movq(Operand(regs_.scratch0(), 4649 __ movp(Operand(regs_.scratch0(),
4972 MemoryChunk::kWriteBarrierCounterOffset), 4650 MemoryChunk::kWriteBarrierCounterOffset),
4973 regs_.scratch1()); 4651 regs_.scratch1());
4974 __ j(negative, &need_incremental); 4652 __ j(negative, &need_incremental);
4975 4653
4976 // Let's look at the color of the object: If it is not black we don't have 4654 // Let's look at the color of the object: If it is not black we don't have
4977 // to inform the incremental marker. 4655 // to inform the incremental marker.
4978 __ JumpIfBlack(regs_.object(), 4656 __ JumpIfBlack(regs_.object(),
4979 regs_.scratch0(), 4657 regs_.scratch0(),
4980 regs_.scratch1(), 4658 regs_.scratch1(),
4981 &on_black, 4659 &on_black,
4982 Label::kNear); 4660 Label::kNear);
4983 4661
4984 regs_.Restore(masm); 4662 regs_.Restore(masm);
4985 if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 4663 if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
4986 __ RememberedSetHelper(object_, 4664 __ RememberedSetHelper(object_,
4987 address_, 4665 address_,
4988 value_, 4666 value_,
4989 save_fp_regs_mode_, 4667 save_fp_regs_mode_,
4990 MacroAssembler::kReturnAtEnd); 4668 MacroAssembler::kReturnAtEnd);
4991 } else { 4669 } else {
4992 __ ret(0); 4670 __ ret(0);
4993 } 4671 }
4994 4672
4995 __ bind(&on_black); 4673 __ bind(&on_black);
4996 4674
4997 // Get the value from the slot. 4675 // Get the value from the slot.
4998 __ movq(regs_.scratch0(), Operand(regs_.address(), 0)); 4676 __ movp(regs_.scratch0(), Operand(regs_.address(), 0));
4999 4677
5000 if (mode == INCREMENTAL_COMPACTION) { 4678 if (mode == INCREMENTAL_COMPACTION) {
5001 Label ensure_not_white; 4679 Label ensure_not_white;
5002 4680
5003 __ CheckPageFlag(regs_.scratch0(), // Contains value. 4681 __ CheckPageFlag(regs_.scratch0(), // Contains value.
5004 regs_.scratch1(), // Scratch. 4682 regs_.scratch1(), // Scratch.
5005 MemoryChunk::kEvacuationCandidateMask, 4683 MemoryChunk::kEvacuationCandidateMask,
5006 zero, 4684 zero,
5007 &ensure_not_white, 4685 &ensure_not_white,
5008 Label::kNear); 4686 Label::kNear);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
5057 // ----------------------------------- 4735 // -----------------------------------
5058 4736
5059 Label element_done; 4737 Label element_done;
5060 Label double_elements; 4738 Label double_elements;
5061 Label smi_element; 4739 Label smi_element;
5062 Label slow_elements; 4740 Label slow_elements;
5063 Label fast_elements; 4741 Label fast_elements;
5064 4742
5065 // Get array literal index, array literal and its map. 4743 // Get array literal index, array literal and its map.
5066 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER); 4744 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER);
5067 __ movq(rdx, args.GetArgumentOperand(1)); 4745 __ movp(rdx, args.GetArgumentOperand(1));
5068 __ movq(rbx, args.GetArgumentOperand(0)); 4746 __ movp(rbx, args.GetArgumentOperand(0));
5069 __ movq(rdi, FieldOperand(rbx, JSObject::kMapOffset)); 4747 __ movp(rdi, FieldOperand(rbx, JSObject::kMapOffset));
5070 4748
5071 __ CheckFastElements(rdi, &double_elements); 4749 __ CheckFastElements(rdi, &double_elements);
5072 4750
5073 // FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS 4751 // FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS
5074 __ JumpIfSmi(rax, &smi_element); 4752 __ JumpIfSmi(rax, &smi_element);
5075 __ CheckFastSmiElements(rdi, &fast_elements); 4753 __ CheckFastSmiElements(rdi, &fast_elements);
5076 4754
5077 // Store into the array literal requires a elements transition. Call into 4755 // Store into the array literal requires a elements transition. Call into
5078 // the runtime. 4756 // the runtime.
5079 4757
5080 __ bind(&slow_elements); 4758 __ bind(&slow_elements);
5081 __ PopReturnAddressTo(rdi); 4759 __ PopReturnAddressTo(rdi);
5082 __ push(rbx); 4760 __ push(rbx);
5083 __ push(rcx); 4761 __ push(rcx);
5084 __ push(rax); 4762 __ push(rax);
5085 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 4763 __ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
5086 __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); 4764 __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
5087 __ push(rdx); 4765 __ push(rdx);
5088 __ PushReturnAddressFrom(rdi); 4766 __ PushReturnAddressFrom(rdi);
5089 __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1); 4767 __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
5090 4768
5091 // Array literal has ElementsKind of FAST_*_ELEMENTS and value is an object. 4769 // Array literal has ElementsKind of FAST_*_ELEMENTS and value is an object.
5092 __ bind(&fast_elements); 4770 __ bind(&fast_elements);
5093 __ SmiToInteger32(kScratchRegister, rcx); 4771 __ SmiToInteger32(kScratchRegister, rcx);
5094 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); 4772 __ movp(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
5095 __ lea(rcx, FieldOperand(rbx, kScratchRegister, times_pointer_size, 4773 __ lea(rcx, FieldOperand(rbx, kScratchRegister, times_pointer_size,
5096 FixedArrayBase::kHeaderSize)); 4774 FixedArrayBase::kHeaderSize));
5097 __ movq(Operand(rcx, 0), rax); 4775 __ movp(Operand(rcx, 0), rax);
5098 // Update the write barrier for the array store. 4776 // Update the write barrier for the array store.
5099 __ RecordWrite(rbx, rcx, rax, 4777 __ RecordWrite(rbx, rcx, rax,
5100 kDontSaveFPRegs, 4778 kDontSaveFPRegs,
5101 EMIT_REMEMBERED_SET, 4779 EMIT_REMEMBERED_SET,
5102 OMIT_SMI_CHECK); 4780 OMIT_SMI_CHECK);
5103 __ ret(0); 4781 __ ret(0);
5104 4782
5105 // Array literal has ElementsKind of FAST_*_SMI_ELEMENTS or 4783 // Array literal has ElementsKind of FAST_*_SMI_ELEMENTS or
5106 // FAST_*_ELEMENTS, and value is Smi. 4784 // FAST_*_ELEMENTS, and value is Smi.
5107 __ bind(&smi_element); 4785 __ bind(&smi_element);
5108 __ SmiToInteger32(kScratchRegister, rcx); 4786 __ SmiToInteger32(kScratchRegister, rcx);
5109 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); 4787 __ movp(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
5110 __ movq(FieldOperand(rbx, kScratchRegister, times_pointer_size, 4788 __ movp(FieldOperand(rbx, kScratchRegister, times_pointer_size,
5111 FixedArrayBase::kHeaderSize), rax); 4789 FixedArrayBase::kHeaderSize), rax);
5112 __ ret(0); 4790 __ ret(0);
5113 4791
5114 // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS. 4792 // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
5115 __ bind(&double_elements); 4793 __ bind(&double_elements);
5116 4794
5117 __ movq(r9, FieldOperand(rbx, JSObject::kElementsOffset)); 4795 __ movp(r9, FieldOperand(rbx, JSObject::kElementsOffset));
5118 __ SmiToInteger32(r11, rcx); 4796 __ SmiToInteger32(r11, rcx);
5119 __ StoreNumberToDoubleElements(rax, 4797 __ StoreNumberToDoubleElements(rax,
5120 r9, 4798 r9,
5121 r11, 4799 r11,
5122 xmm0, 4800 xmm0,
5123 &slow_elements); 4801 &slow_elements);
5124 __ ret(0); 4802 __ ret(0);
5125 } 4803 }
5126 4804
5127 4805
5128 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { 4806 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
5129 CEntryStub ces(1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs); 4807 CEntryStub ces(1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs);
5130 __ Call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); 4808 __ Call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
5131 int parameter_count_offset = 4809 int parameter_count_offset =
5132 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; 4810 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
5133 __ movq(rbx, MemOperand(rbp, parameter_count_offset)); 4811 __ movp(rbx, MemOperand(rbp, parameter_count_offset));
5134 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); 4812 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
5135 __ PopReturnAddressTo(rcx); 4813 __ PopReturnAddressTo(rcx);
5136 int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE 4814 int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE
5137 ? kPointerSize 4815 ? kPointerSize
5138 : 0; 4816 : 0;
5139 __ lea(rsp, MemOperand(rsp, rbx, times_pointer_size, additional_offset)); 4817 __ lea(rsp, MemOperand(rsp, rbx, times_pointer_size, additional_offset));
5140 __ jmp(rcx); // Return to IC Miss stub, continuation still on stack. 4818 __ jmp(rcx); // Return to IC Miss stub, continuation still on stack.
5141 } 4819 }
5142 4820
5143 4821
5144 void StubFailureTailCallTrampolineStub::Generate(MacroAssembler* masm) { 4822 void StubFailureTailCallTrampolineStub::Generate(MacroAssembler* masm) {
5145 CEntryStub ces(1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs); 4823 CEntryStub ces(1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs);
5146 __ Call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); 4824 __ Call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
5147 __ movq(rdi, rax); 4825 __ movp(rdi, rax);
5148 int parameter_count_offset = 4826 int parameter_count_offset =
5149 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; 4827 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
5150 __ movq(rax, MemOperand(rbp, parameter_count_offset)); 4828 __ movp(rax, MemOperand(rbp, parameter_count_offset));
5151 // The parameter count above includes the receiver for the arguments passed to 4829 // The parameter count above includes the receiver for the arguments passed to
5152 // the deoptimization handler. Subtract the receiver for the parameter count 4830 // the deoptimization handler. Subtract the receiver for the parameter count
5153 // for the call. 4831 // for the call.
5154 __ subl(rax, Immediate(1)); 4832 __ subl(rax, Immediate(1));
5155 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); 4833 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
5156 ParameterCount argument_count(rax); 4834 ParameterCount argument_count(rax);
5157 __ InvokeFunction(rdi, argument_count, JUMP_FUNCTION, NullCallWrapper()); 4835 __ InvokeFunction(rdi, argument_count, JUMP_FUNCTION, NullCallWrapper());
5158 } 4836 }
5159 4837
5160 4838
5161 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { 4839 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) {
5162 if (masm->isolate()->function_entry_hook() != NULL) { 4840 if (masm->isolate()->function_entry_hook() != NULL) {
5163 ProfileEntryHookStub stub; 4841 ProfileEntryHookStub stub;
5164 masm->CallStub(&stub); 4842 masm->CallStub(&stub);
5165 } 4843 }
5166 } 4844 }
5167 4845
5168 4846
5169 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { 4847 void ProfileEntryHookStub::Generate(MacroAssembler* masm) {
5170 // This stub can be called from essentially anywhere, so it needs to save 4848 // This stub can be called from essentially anywhere, so it needs to save
5171 // all volatile and callee-save registers. 4849 // all volatile and callee-save registers.
5172 const size_t kNumSavedRegisters = 2; 4850 const size_t kNumSavedRegisters = 2;
5173 __ push(arg_reg_1); 4851 __ push(arg_reg_1);
5174 __ push(arg_reg_2); 4852 __ push(arg_reg_2);
5175 4853
5176 // Calculate the original stack pointer and store it in the second arg. 4854 // Calculate the original stack pointer and store it in the second arg.
5177 __ lea(arg_reg_2, Operand(rsp, (kNumSavedRegisters + 1) * kPointerSize)); 4855 __ lea(arg_reg_2,
4856 Operand(rsp, kNumSavedRegisters * kRegisterSize + kPCOnStackSize));
5178 4857
5179 // Calculate the function address to the first arg. 4858 // Calculate the function address to the first arg.
5180 __ movq(arg_reg_1, Operand(rsp, kNumSavedRegisters * kPointerSize)); 4859 __ movp(arg_reg_1, Operand(rsp, kNumSavedRegisters * kRegisterSize));
5181 __ subq(arg_reg_1, Immediate(Assembler::kShortCallInstructionLength)); 4860 __ subq(arg_reg_1, Immediate(Assembler::kShortCallInstructionLength));
5182 4861
5183 // Save the remainder of the volatile registers. 4862 // Save the remainder of the volatile registers.
5184 masm->PushCallerSaved(kSaveFPRegs, arg_reg_1, arg_reg_2); 4863 masm->PushCallerSaved(kSaveFPRegs, arg_reg_1, arg_reg_2);
5185 4864
5186 // Call the entry hook function. 4865 // Call the entry hook function.
5187 __ Move(rax, FUNCTION_ADDR(masm->isolate()->function_entry_hook()), 4866 __ Move(rax, FUNCTION_ADDR(masm->isolate()->function_entry_hook()),
5188 RelocInfo::NONE64); 4867 RelocInfo::NONE64);
5189 4868
5190 AllowExternalCallThatCantCauseGC scope(masm); 4869 AllowExternalCallThatCantCauseGC scope(masm);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
5224 // If we reached this point there is a problem. 4903 // If we reached this point there is a problem.
5225 __ Abort(kUnexpectedElementsKindInArrayConstructor); 4904 __ Abort(kUnexpectedElementsKindInArrayConstructor);
5226 } else { 4905 } else {
5227 UNREACHABLE(); 4906 UNREACHABLE();
5228 } 4907 }
5229 } 4908 }
5230 4909
5231 4910
5232 static void CreateArrayDispatchOneArgument(MacroAssembler* masm, 4911 static void CreateArrayDispatchOneArgument(MacroAssembler* masm,
5233 AllocationSiteOverrideMode mode) { 4912 AllocationSiteOverrideMode mode) {
5234 // rbx - type info cell (if mode != DISABLE_ALLOCATION_SITES) 4913 // rbx - allocation site (if mode != DISABLE_ALLOCATION_SITES)
5235 // rdx - kind (if mode != DISABLE_ALLOCATION_SITES) 4914 // rdx - kind (if mode != DISABLE_ALLOCATION_SITES)
5236 // rax - number of arguments 4915 // rax - number of arguments
5237 // rdi - constructor? 4916 // rdi - constructor?
5238 // rsp[0] - return address 4917 // rsp[0] - return address
5239 // rsp[8] - last argument 4918 // rsp[8] - last argument
5240 Handle<Object> undefined_sentinel( 4919 Handle<Object> undefined_sentinel(
5241 masm->isolate()->heap()->undefined_value(), 4920 masm->isolate()->heap()->undefined_value(),
5242 masm->isolate()); 4921 masm->isolate());
5243 4922
5244 Label normal_sequence; 4923 Label normal_sequence;
5245 if (mode == DONT_OVERRIDE) { 4924 if (mode == DONT_OVERRIDE) {
5246 ASSERT(FAST_SMI_ELEMENTS == 0); 4925 ASSERT(FAST_SMI_ELEMENTS == 0);
5247 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 4926 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
5248 ASSERT(FAST_ELEMENTS == 2); 4927 ASSERT(FAST_ELEMENTS == 2);
5249 ASSERT(FAST_HOLEY_ELEMENTS == 3); 4928 ASSERT(FAST_HOLEY_ELEMENTS == 3);
5250 ASSERT(FAST_DOUBLE_ELEMENTS == 4); 4929 ASSERT(FAST_DOUBLE_ELEMENTS == 4);
5251 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); 4930 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
5252 4931
5253 // is the low bit set? If so, we are holey and that is good. 4932 // is the low bit set? If so, we are holey and that is good.
5254 __ testb(rdx, Immediate(1)); 4933 __ testb(rdx, Immediate(1));
5255 __ j(not_zero, &normal_sequence); 4934 __ j(not_zero, &normal_sequence);
5256 } 4935 }
5257 4936
5258 // look at the first argument 4937 // look at the first argument
5259 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); 4938 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER);
5260 __ movq(rcx, args.GetArgumentOperand(0)); 4939 __ movp(rcx, args.GetArgumentOperand(0));
5261 __ testq(rcx, rcx); 4940 __ testq(rcx, rcx);
5262 __ j(zero, &normal_sequence); 4941 __ j(zero, &normal_sequence);
5263 4942
5264 if (mode == DISABLE_ALLOCATION_SITES) { 4943 if (mode == DISABLE_ALLOCATION_SITES) {
5265 ElementsKind initial = GetInitialFastElementsKind(); 4944 ElementsKind initial = GetInitialFastElementsKind();
5266 ElementsKind holey_initial = GetHoleyElementsKind(initial); 4945 ElementsKind holey_initial = GetHoleyElementsKind(initial);
5267 4946
5268 ArraySingleArgumentConstructorStub stub_holey(holey_initial, 4947 ArraySingleArgumentConstructorStub stub_holey(holey_initial,
5269 DISABLE_ALLOCATION_SITES); 4948 DISABLE_ALLOCATION_SITES);
5270 __ TailCallStub(&stub_holey); 4949 __ TailCallStub(&stub_holey);
5271 4950
5272 __ bind(&normal_sequence); 4951 __ bind(&normal_sequence);
5273 ArraySingleArgumentConstructorStub stub(initial, 4952 ArraySingleArgumentConstructorStub stub(initial,
5274 DISABLE_ALLOCATION_SITES); 4953 DISABLE_ALLOCATION_SITES);
5275 __ TailCallStub(&stub); 4954 __ TailCallStub(&stub);
5276 } else if (mode == DONT_OVERRIDE) { 4955 } else if (mode == DONT_OVERRIDE) {
5277 // We are going to create a holey array, but our kind is non-holey. 4956 // We are going to create a holey array, but our kind is non-holey.
5278 // Fix kind and retry (only if we have an allocation site in the cell). 4957 // Fix kind and retry (only if we have an allocation site in the cell).
5279 __ incl(rdx); 4958 __ incl(rdx);
5280 __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset)); 4959
5281 if (FLAG_debug_code) { 4960 if (FLAG_debug_code) {
5282 Handle<Map> allocation_site_map = 4961 Handle<Map> allocation_site_map =
5283 masm->isolate()->factory()->allocation_site_map(); 4962 masm->isolate()->factory()->allocation_site_map();
5284 __ Cmp(FieldOperand(rcx, 0), allocation_site_map); 4963 __ Cmp(FieldOperand(rbx, 0), allocation_site_map);
5285 __ Assert(equal, kExpectedAllocationSiteInCell); 4964 __ Assert(equal, kExpectedAllocationSite);
5286 } 4965 }
5287 4966
5288 // Save the resulting elements kind in type info. We can't just store r3 4967 // Save the resulting elements kind in type info. We can't just store r3
5289 // in the AllocationSite::transition_info field because elements kind is 4968 // in the AllocationSite::transition_info field because elements kind is
5290 // restricted to a portion of the field...upper bits need to be left alone. 4969 // restricted to a portion of the field...upper bits need to be left alone.
5291 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 4970 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
5292 __ SmiAddConstant(FieldOperand(rcx, AllocationSite::kTransitionInfoOffset), 4971 __ SmiAddConstant(FieldOperand(rbx, AllocationSite::kTransitionInfoOffset),
5293 Smi::FromInt(kFastElementsKindPackedToHoley)); 4972 Smi::FromInt(kFastElementsKindPackedToHoley));
5294 4973
5295 __ bind(&normal_sequence); 4974 __ bind(&normal_sequence);
5296 int last_index = GetSequenceIndexFromFastElementsKind( 4975 int last_index = GetSequenceIndexFromFastElementsKind(
5297 TERMINAL_FAST_ELEMENTS_KIND); 4976 TERMINAL_FAST_ELEMENTS_KIND);
5298 for (int i = 0; i <= last_index; ++i) { 4977 for (int i = 0; i <= last_index; ++i) {
5299 Label next; 4978 Label next;
5300 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 4979 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
5301 __ cmpl(rdx, Immediate(kind)); 4980 __ cmpl(rdx, Immediate(kind));
5302 __ j(not_equal, &next); 4981 __ j(not_equal, &next);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
5392 // ----------------------------------- 5071 // -----------------------------------
5393 Handle<Object> undefined_sentinel( 5072 Handle<Object> undefined_sentinel(
5394 masm->isolate()->heap()->undefined_value(), 5073 masm->isolate()->heap()->undefined_value(),
5395 masm->isolate()); 5074 masm->isolate());
5396 5075
5397 if (FLAG_debug_code) { 5076 if (FLAG_debug_code) {
5398 // The array construct code is only set for the global and natives 5077 // The array construct code is only set for the global and natives
5399 // builtin Array functions which always have maps. 5078 // builtin Array functions which always have maps.
5400 5079
5401 // Initial map for the builtin Array function should be a map. 5080 // Initial map for the builtin Array function should be a map.
5402 __ movq(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); 5081 __ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
5403 // Will both indicate a NULL and a Smi. 5082 // Will both indicate a NULL and a Smi.
5404 STATIC_ASSERT(kSmiTag == 0); 5083 STATIC_ASSERT(kSmiTag == 0);
5405 Condition not_smi = NegateCondition(masm->CheckSmi(rcx)); 5084 Condition not_smi = NegateCondition(masm->CheckSmi(rcx));
5406 __ Check(not_smi, kUnexpectedInitialMapForArrayFunction); 5085 __ Check(not_smi, kUnexpectedInitialMapForArrayFunction);
5407 __ CmpObjectType(rcx, MAP_TYPE, rcx); 5086 __ CmpObjectType(rcx, MAP_TYPE, rcx);
5408 __ Check(equal, kUnexpectedInitialMapForArrayFunction); 5087 __ Check(equal, kUnexpectedInitialMapForArrayFunction);
5409 5088
5410 // We should either have undefined in rbx or a valid cell 5089 // We should either have undefined in rbx or a valid cell
5411 Label okay_here; 5090 Label okay_here;
5412 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); 5091 Handle<Map> cell_map = masm->isolate()->factory()->cell_map();
5413 __ Cmp(rbx, undefined_sentinel); 5092 __ Cmp(rbx, undefined_sentinel);
5414 __ j(equal, &okay_here); 5093 __ j(equal, &okay_here);
5415 __ Cmp(FieldOperand(rbx, 0), cell_map); 5094 __ Cmp(FieldOperand(rbx, 0), cell_map);
5416 __ Assert(equal, kExpectedPropertyCellInRegisterRbx); 5095 __ Assert(equal, kExpectedPropertyCellInRegisterRbx);
5417 __ bind(&okay_here); 5096 __ bind(&okay_here);
5418 } 5097 }
5419 5098
5420 Label no_info; 5099 Label no_info;
5421 // If the type cell is undefined, or contains anything other than an 5100 // If the type cell is undefined, or contains anything other than an
5422 // AllocationSite, call an array constructor that doesn't use AllocationSites. 5101 // AllocationSite, call an array constructor that doesn't use AllocationSites.
5423 __ Cmp(rbx, undefined_sentinel); 5102 __ Cmp(rbx, undefined_sentinel);
5424 __ j(equal, &no_info); 5103 __ j(equal, &no_info);
5425 __ movq(rdx, FieldOperand(rbx, Cell::kValueOffset)); 5104 __ movp(rbx, FieldOperand(rbx, Cell::kValueOffset));
5426 __ Cmp(FieldOperand(rdx, 0), 5105 __ Cmp(FieldOperand(rbx, 0),
5427 masm->isolate()->factory()->allocation_site_map()); 5106 masm->isolate()->factory()->allocation_site_map());
5428 __ j(not_equal, &no_info); 5107 __ j(not_equal, &no_info);
5429 5108
5430 // Only look at the lower 16 bits of the transition info. 5109 // Only look at the lower 16 bits of the transition info.
5431 __ movq(rdx, FieldOperand(rdx, AllocationSite::kTransitionInfoOffset)); 5110 __ movp(rdx, FieldOperand(rbx, AllocationSite::kTransitionInfoOffset));
5432 __ SmiToInteger32(rdx, rdx); 5111 __ SmiToInteger32(rdx, rdx);
5433 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 5112 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
5434 __ and_(rdx, Immediate(AllocationSite::ElementsKindBits::kMask)); 5113 __ and_(rdx, Immediate(AllocationSite::ElementsKindBits::kMask));
5435 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); 5114 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE);
5436 5115
5437 __ bind(&no_info); 5116 __ bind(&no_info);
5438 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); 5117 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES);
5439 } 5118 }
5440 5119
5441 5120
5442 void InternalArrayConstructorStub::GenerateCase( 5121 void InternalArrayConstructorStub::GenerateCase(
5443 MacroAssembler* masm, ElementsKind kind) { 5122 MacroAssembler* masm, ElementsKind kind) {
5444 Label not_zero_case, not_one_case; 5123 Label not_zero_case, not_one_case;
5445 Label normal_sequence; 5124 Label normal_sequence;
5446 5125
5447 __ testq(rax, rax); 5126 __ testq(rax, rax);
5448 __ j(not_zero, &not_zero_case); 5127 __ j(not_zero, &not_zero_case);
5449 InternalArrayNoArgumentConstructorStub stub0(kind); 5128 InternalArrayNoArgumentConstructorStub stub0(kind);
5450 __ TailCallStub(&stub0); 5129 __ TailCallStub(&stub0);
5451 5130
5452 __ bind(&not_zero_case); 5131 __ bind(&not_zero_case);
5453 __ cmpl(rax, Immediate(1)); 5132 __ cmpl(rax, Immediate(1));
5454 __ j(greater, &not_one_case); 5133 __ j(greater, &not_one_case);
5455 5134
5456 if (IsFastPackedElementsKind(kind)) { 5135 if (IsFastPackedElementsKind(kind)) {
5457 // We might need to create a holey array 5136 // We might need to create a holey array
5458 // look at the first argument 5137 // look at the first argument
5459 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); 5138 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER);
5460 __ movq(rcx, args.GetArgumentOperand(0)); 5139 __ movp(rcx, args.GetArgumentOperand(0));
5461 __ testq(rcx, rcx); 5140 __ testq(rcx, rcx);
5462 __ j(zero, &normal_sequence); 5141 __ j(zero, &normal_sequence);
5463 5142
5464 InternalArraySingleArgumentConstructorStub 5143 InternalArraySingleArgumentConstructorStub
5465 stub1_holey(GetHoleyElementsKind(kind)); 5144 stub1_holey(GetHoleyElementsKind(kind));
5466 __ TailCallStub(&stub1_holey); 5145 __ TailCallStub(&stub1_holey);
5467 } 5146 }
5468 5147
5469 __ bind(&normal_sequence); 5148 __ bind(&normal_sequence);
5470 InternalArraySingleArgumentConstructorStub stub1(kind); 5149 InternalArraySingleArgumentConstructorStub stub1(kind);
(...skipping 12 matching lines...) Expand all
5483 // -- rdi : constructor 5162 // -- rdi : constructor
5484 // -- rsp[0] : return address 5163 // -- rsp[0] : return address
5485 // -- rsp[8] : last argument 5164 // -- rsp[8] : last argument
5486 // ----------------------------------- 5165 // -----------------------------------
5487 5166
5488 if (FLAG_debug_code) { 5167 if (FLAG_debug_code) {
5489 // The array construct code is only set for the global and natives 5168 // The array construct code is only set for the global and natives
5490 // builtin Array functions which always have maps. 5169 // builtin Array functions which always have maps.
5491 5170
5492 // Initial map for the builtin Array function should be a map. 5171 // Initial map for the builtin Array function should be a map.
5493 __ movq(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); 5172 __ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
5494 // Will both indicate a NULL and a Smi. 5173 // Will both indicate a NULL and a Smi.
5495 STATIC_ASSERT(kSmiTag == 0); 5174 STATIC_ASSERT(kSmiTag == 0);
5496 Condition not_smi = NegateCondition(masm->CheckSmi(rcx)); 5175 Condition not_smi = NegateCondition(masm->CheckSmi(rcx));
5497 __ Check(not_smi, kUnexpectedInitialMapForArrayFunction); 5176 __ Check(not_smi, kUnexpectedInitialMapForArrayFunction);
5498 __ CmpObjectType(rcx, MAP_TYPE, rcx); 5177 __ CmpObjectType(rcx, MAP_TYPE, rcx);
5499 __ Check(equal, kUnexpectedInitialMapForArrayFunction); 5178 __ Check(equal, kUnexpectedInitialMapForArrayFunction);
5500 } 5179 }
5501 5180
5502 // Figure out the right elements kind 5181 // Figure out the right elements kind
5503 __ movq(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); 5182 __ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
5504 5183
5505 // Load the map's "bit field 2" into |result|. We only need the first byte, 5184 // Load the map's "bit field 2" into |result|. We only need the first byte,
5506 // but the following masking takes care of that anyway. 5185 // but the following masking takes care of that anyway.
5507 __ movzxbq(rcx, FieldOperand(rcx, Map::kBitField2Offset)); 5186 __ movzxbq(rcx, FieldOperand(rcx, Map::kBitField2Offset));
5508 // Retrieve elements_kind from bit field 2. 5187 // Retrieve elements_kind from bit field 2.
5509 __ and_(rcx, Immediate(Map::kElementsKindMask)); 5188 __ and_(rcx, Immediate(Map::kElementsKindMask));
5510 __ shr(rcx, Immediate(Map::kElementsKindShift)); 5189 __ shr(rcx, Immediate(Map::kElementsKindShift));
5511 5190
5512 if (FLAG_debug_code) { 5191 if (FLAG_debug_code) {
5513 Label done; 5192 Label done;
(...skipping 13 matching lines...) Expand all
5527 __ bind(&fast_elements_case); 5206 __ bind(&fast_elements_case);
5528 GenerateCase(masm, FAST_ELEMENTS); 5207 GenerateCase(masm, FAST_ELEMENTS);
5529 } 5208 }
5530 5209
5531 5210
5532 #undef __ 5211 #undef __
5533 5212
5534 } } // namespace v8::internal 5213 } } // namespace v8::internal
5535 5214
5536 #endif // V8_TARGET_ARCH_X64 5215 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/code-stubs-x64.h ('k') | src/x64/codegen-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698